private void Process(byte[] data, int length, IPEndPoint receiveAddress) { if (length < 16) { Console.WriteLine($"Rejecting short message from {receiveAddress}"); return; } if (data[0] != 68 || data[1] != 84 || data[2] != 84 || data[3] != 50) { Console.WriteLine($"Rejecting non TCPTunnel traffic from {receiveAddress}"); return; } int connectionID = BitConverter.ToInt32(data, 4); short messageType = BitConverter.ToInt16(data, 8); short messageLength = BitConverter.ToInt16(data, 10); short messageSequence = BitConverter.ToInt16(data, 12); short messageACK = BitConverter.ToInt16(data, 14); if (BitConverter.IsLittleEndian) { connectionID = IPAddress.NetworkToHostOrder(connectionID); messageType = IPAddress.NetworkToHostOrder(messageType); messageLength = IPAddress.NetworkToHostOrder(messageLength); messageSequence = IPAddress.NetworkToHostOrder(messageSequence); messageACK = IPAddress.NetworkToHostOrder(messageACK); } if (messageLength != length - 16) { Console.WriteLine($"Rejecting bad payload TCPTunnel traffic from {receiveAddress}"); return; } //Payload is limited to 500 bytes if (messageLength > 500) { Console.WriteLine($"Broken payload from {connectionID}"); return; } if (!connections.ContainsKey(connectionID)) { //We're the server so we need to grab a new tcp connection for this client if (ConnectLocalTCPConnection != null) { TcpClient newClient = ConnectLocalTCPConnection(); if (newClient == null) { //Server down? Console.WriteLine($"Unable to connect to {settings.tcpPort}, is the server down?"); return; } Bucket newBucket = new Bucket(settings.connectionUpload, settings.connectionUpload, globalLimit); Connection newConnection = new Connection(connectionID, settings, newClient, this, newBucket); newConnection.sendEndpoint = receiveAddress; connections[connectionID] = newConnection; Console.WriteLine($"New connection {connectionID} from {receiveAddress} mapped to {newClient.Client.LocalEndPoint}"); } else { //We can't do anything client side if we don't have an existing TCP connection, ignore the messages Console.WriteLine($"Unknown UDP connection {connectionID} in client mode"); return; } } Connection c = connections[connectionID]; ByteArray payload = null; if (messageLength > 0) { payload = Recycler.Grab(); Array.Copy(data, 16, payload.data, 0, messageLength); payload.length = messageLength; } c.HandleUDPData(messageType, messageLength, messageSequence, messageACK, payload, receiveAddress); }
public Connection(int connectionID, TunnelSettings settings, TcpClient tcpClient, UDPServer udpServer, Bucket uploadBucket, Statistics statistics) { this.connectionID = connectionID; this.tcpClient = tcpClient; this.udpServer = udpServer; this.uploadBucket = uploadBucket; this.settings = settings; this.statistics = statistics; tcpSendTask = new Thread(new ThreadStart(SendLoop)); tcpSendTask.Name = "Connection.SendLoop." + connectionID; tcpSendTask.Start(); tcpReceiveTask = new Thread(new ThreadStart(ReceiveLoop)); tcpReceiveTask.Name = "Connection.ReceiveLoop." + connectionID; tcpReceiveTask.Start(); disconnectTime = DateTime.UtcNow.Ticks + (TimeSpan.TicksPerSecond * 5); }