private void SendPacket(BasicTunnelPacket packet) { if (IsTunnelEstablished) { #if (DEBUG) Logger.Debug("Sending packet " + packet.ToString()); #endif byte[] sendBytes = packet.getBytes(); _udpClient.Send(sendBytes, sendBytes.Length, _remoteEndpoint); } else { throw new ConnectionException("Cannot send packet [" + packet.ToString() + "], not currently synced with a peer"); } }
private void HandlePacket(BasicTunnelPacket packet) { #if (DEBUG) Logger.Debug("Looking for handler for packet " + packet.ToString() + " from ip " + packet.ip); #endif // data packets must come from the established IP if (packet.type == BasicTunnelPacket.PKT_TYPE_DATA && packet.ip.Equals(_remoteEndpoint)) { #if (DEBUG) Logger.Debug("Got a data packet"); #endif if (ProcessData != null) { try { byte[] data = packet.data; if (DecryptData != null) { try { DecryptData(ref data); } catch (Exception e) { Logger.Error("Encryption failed, shutting down tunnel : " + e.Message, e); this.Close(); } } // a new thread needs to handle this upstream otherwise upstream can hang the whole process Thread processDataThread = new Thread(() => ProcessData(data, Id)) { IsBackground = true }; processDataThread.Name = "processTunnelData[" + Id + "-" + processDataThread.ManagedThreadId + "]"; processDataThread.Start(); } catch (Exception e) { Logger.Error("Failed to call processData on packet " + packet.ToString() + " : " + e.Message); } } else { Logger.Error("Cannot handle packet, no processData method"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_WAVE_RS) { #if (DEBUG) Logger.Debug("Got a wave response from " + packet.ip + ", my address is " + ((StandardWaveTunnelRsPacket)packet).externalEndPoint + "/" + ((StandardWaveTunnelRsPacket)packet).internalEndPoint); #endif if (_waver != null) { _waver.ProcessWaveRs((StandardWaveTunnelRsPacket)packet); } else { Logger.Error("Cannot process wave response, invalid wave handler"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_SYNC_RQ) { #if (DEBUG) Logger.Debug("Got a sync request"); #endif if (_syncer != null) { _syncer.ProcessSyncRq((StandardSyncRqTunnelPacket)packet); } else { Logger.Error("Cannot process sync request, invalid sync handler"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_SYNC_RS) { #if (DEBUG) Logger.Debug("Got a sync response"); #endif if (_syncer != null) { _syncer.ProcessSyncRs((StandardSyncRsTunnelPacket)packet); } else { Logger.Error("Cannot process sync response, invalid sync object"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_PONG && packet.ip.Equals(_remoteEndpoint)) { #if (DEBUG) Logger.Debug("Got a pong"); #endif if (_pinger != null) { _pinger.ProcessPong((StandardPongTunnelPacket)packet); } else { Logger.Error("Cannot process pong, invalid ping object"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_PING && packet.ip.Equals(_remoteEndpoint)) { #if (DEBUG) Logger.Debug("Got a ping"); #endif if (_pinger != null) { _pinger.ProcessPing((StandardPingTunnelPacket)packet, _udpClient); _lastPing = DateTime.Now.Ticks; } else { Logger.Error("Cannot process ping, invalid ping object"); } } else if (packet.type == BasicTunnelPacket.PKT_TYPE_NOP) { #if (DEBUG) Logger.Debug("Got a nop"); #endif } else if (packet.type == BasicTunnelPacket.PKT_TYPE_CLOSE && packet.ip.Equals(_remoteEndpoint)) { #if (DEBUG) Logger.Debug("Got a close package, initialising close"); #endif this.Close(); } else { #if (DEBUG) Logger.Debug("Dropping unknown/invalid data packet " + packet.ToString()); #endif } }
private void ListenForPackets() { #if (DEBUG) Logger.Debug("Started UDP reading thread"); #endif while (true) { IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); Byte[] bytes = null; try { bytes = _udpClient.Receive(ref RemoteIpEndPoint); BasicTunnelPacket packet = StandardUdpPacketFactory.instance.getPacket(bytes, RemoteIpEndPoint); HandlePacket(packet); } catch (UnknownPacketException e) { Logger.Error("Recieved an unknown packet type, dropping : " + e.Message); } catch (SocketException e) { #if (DEBUG) Logger.Debug("Caught a socket exception [" + e.ErrorCode + "] : " + e.Message); #endif if (e.ErrorCode == 10004) // Interrupted { #if (DEBUG) Logger.Debug("Socket has been interrupted, shutting down"); #endif this.Close(); break; } else if (e.ErrorCode == 10054) // Got ICMP connection closed ( we need to ignore this, hole punching causes these during init ) { #if (DEBUG) Logger.Debug("Remote host stated ICMP port closed, ignoring"); #endif } else if (e.ErrorCode == 10052) // Got a ttl expired which can happen since we are spamming both internal and external IP's, ignore { #if (DEBUG) Logger.Debug("Ttl on one of our packets has expired, ignoring."); #endif } else { Logger.Warn("Caught a socket exception [" + e.ErrorCode + "], this looks spurious, ignoring : " + e.Message); Logger.Error("Caught a socket exception [" + e.ErrorCode + "], shutting down read thread : " + e.Message); this.Close(); break; } } catch (ThreadAbortException e) { #if DEBUG Logger.Debug("Thread is aborting, closing : " + e.Message); #endif this.Close(); break; } catch (Exception e) { Logger.Error("Exception while reading from UDP socket, shutting down read thread : " + e.Message, e); // Most likely the link has failed (this side) or the app is closing // either way, close the thread for the moment this.Close(); break; } } }
private void ListenForPackets() { while (true) { IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); Byte[] bytes = null; try { bytes = _udpClient.Receive(ref RemoteIpEndPoint); BasicTunnelPacket packet = StandardUdpPacketFactory.instance.getPacket(bytes, RemoteIpEndPoint); if (packet.type == BasicTunnelPacket.PKT_TYPE_WAVE_RS) { #if (DEBUG) Logger.Debug("Got a wave response from " + packet.ip + ", my address is " + ((StandardWaveTunnelRsPacket)packet).externalEndPoint + "/" + ((StandardWaveTunnelRsPacket)packet).internalEndPoint); #endif ProcessWaveRs((StandardWaveTunnelRsPacket)packet); Logger.Debug("Shutting down wave listener"); break; } else { Logger.Error("Waiting for a wave response, but got unknown packet"); break; } } catch (SocketException e) { #if (DEBUG) Logger.Debug("Caught a socket exception [" + e.ErrorCode + "] : " + e.Message); #endif if (e.ErrorCode == 10004) // Interrupted { #if (DEBUG) Logger.Debug("Socket has been interrupted, shutting down"); #endif _udpClient.Close(); break; } else if (e.ErrorCode == 10054) // Got ICMP connection closed ( we need to ignore this, hole punching causes these during init ) { #if (DEBUG) Logger.Debug("Remote host stated ICMP port closed, ignoring"); #endif } else { Logger.Warn("Caught a socket exception [" + e.ErrorCode + "], this looks spurious, ignoring : " + e.Message); Logger.Error("Caught a socket exception [" + e.ErrorCode + "], shutting down read thread : " + e.Message); _udpClient.Close(); break; } } catch (ThreadAbortException e) { #if DEBUG Logger.Debug("Thread is aborting, closing : " + e.Message); #endif _udpClient.Close(); break; } catch (Exception e) { Logger.Error("Exception while reading from UDP socket, shutting down read thread : " + e.Message, e); // Most likely the link has failed (this side) or the app is closing // either way, close the thread for the moment _udpClient.Close(); break; } } }