Esempio n. 1
0
        private void SendBytesToUi(byte[] saveData, CommPacketDirection direction)
        {
            var length             = saveData.Search(saveData.Length, new byte[] { 13, 10 });
            var dataStringSegments = Encoding.UTF8.GetString(saveData, 0, length).Split(' ');

            string header = "HTTP Data";

            if (dataStringSegments[2].StartsWith("HTTP"))
            {
                header = $"{dataStringSegments[0]} {dataStringSegments[1]}";
            }
            else if (dataStringSegments[0].StartsWith("HTTP"))
            {
                var desc = dataStringSegments[2];

                for (int i = 3; i < dataStringSegments.Length; ++i)
                {
                    desc += $" {dataStringSegments[i]}";
                }

                header = $"{dataStringSegments[1]} {desc}";
            }

            ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().SendBytesToUi(m_connectionInstance, new CommPacket
            {
                Data         = saveData,
                Direction    = direction,
                Id           = Guid.NewGuid(),
                Instance     = m_connectionInstance,
                ParentPacket = null,
                Header       = header,
            });
        }
Esempio n. 2
0
 private void DestinationWrite(Stream destination, byte[] buffer, int count, CommPacketDirection direction)
 {
     Application.Current.Dispatcher.Invoke(() =>
     {
         ProxyUiWindow.WriteBytes(buffer, count, direction, m_connectionInstance);
     });
     TryWriteStream(destination, buffer, 0, count, direction == CommPacketDirection.ServerToClient);
 }
        private void Forward(Stream source, Stream destination, IAsyncResult asyncResult, byte[] buffer)
        {
            try
            {
                CommPacketDirection direction = (CommPacketDirection)asyncResult.AsyncState;

                var bytesRead = source.EndRead(asyncResult);
                if (bytesRead == 0)
                {
                    Kill();
                    return;
                }

                if (ReplaceIpaddr && buffer.Search(bytesRead, ipAddrBytes) > 0)
                {
                    string request = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    Regex ipSubPattern = new Regex("\\,\"ipAddr\":\"[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\"\\,");
                    Match ipSubMatch   = ipSubPattern.Match(request);

                    if (ipSubMatch.Success)
                    {
                        string org = ipSubMatch.Groups[0].Value;
                        string rep = ",\"ipAddr\":\"127.0.0.1\",";

                        Regex reg = new Regex("Content-Length\\: ([0-9]*)");
                        Match m   = reg.Match(request);

                        if (!m.Success)
                        {
                        }

                        int length    = Convert.ToInt32(m.Groups[1].Value);
                        int newLength = length + rep.Length - org.Length;

                        request = request.Replace(org, rep);
                        request = request.Replace($"Content-Length: {length}", $"Content-Length: {newLength}");

                        byte[] sendBytes = Encoding.UTF8.GetBytes(request);
                        DestinationWrite(destination, sendBytes, sendBytes.Length, direction);
                    }
                    else
                    {
                        DestinationWrite(destination, buffer, bytesRead, direction);
                    }
                }
                else
                {
                    DestinationWrite(destination, buffer, bytesRead, direction);
                }

                ForwardStream(source, destination, buffer, direction);
            }
            catch
            {
                Kill();
            }
        }
 private void ForwardStream(Stream source, Stream destination, byte[] buffer, CommPacketDirection direction)
 {
     try
     {
         source.BeginRead(buffer, 0, buffer.Length, r => Forward(source, destination, r, buffer), direction);
     }
     catch
     {
         Kill();
     }
 }
Esempio n. 5
0
        private void DestinationWrite(Stream destination, byte[] buffer, int count, CommPacketDirection direction)
        {
            if (ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().CaptureEnabled)
            {
                byte[] saveData = new byte[count];
                Buffer.BlockCopy(buffer, 0, saveData, 0, count);
                SendBytesToUi(saveData, direction);
            }

            TryWriteStream(destination, buffer, 0, count, direction == CommPacketDirection.ServerToClient);
        }
        public static void AddFrame(WsFrame frame, CommPacketDirection direction, ConnectionInstance connectionInstance)
        {
            if (instance == null || !instance.Data.CaptureEnabled)
            {
                return;
            }

            try
            {
                var parentPacket = new CommPacket
                {
                    Data         = frame.HeaderBytes,
                    Direction    = direction,
                    Id           = Guid.NewGuid(),
                    Instance     = connectionInstance,
                    ParentPacket = null,
                    Header       = "Websocket Frame",
                };

                foreach (var curMessage in frame.Messages)
                {
                    var headerPacket = new CommPacket
                    {
                        Data         = BitConverter.GetBytes((ushort)(curMessage.Buffer.Length + 1)).Concat(new byte[] { curMessage.ApiId ?? 0 }).ToArray(),
                        Direction    = direction,
                        Id           = Guid.NewGuid(),
                        Instance     = connectionInstance,
                        ParentPacket = parentPacket,
                        Header       = $"Websocket Message[0x{curMessage.ApiId ?? 0:X2}]",
                    };

                    var payloadPacket = new CommPacket
                    {
                        Data         = curMessage.Buffer,
                        Direction    = direction,
                        Id           = Guid.NewGuid(),
                        Instance     = connectionInstance,
                        ParentPacket = parentPacket,
                        Header       = $"Websocket Payload",
                    };

                    headerPacket.ChildPackets.Add(payloadPacket);
                    parentPacket.ChildPackets.Add(headerPacket);
                }
                ;

                instance.Data.SendBytesToUi(connectionInstance, parentPacket);
            }
            catch (Exception ex) {
                Log.Error(ex, "Error in AddFrame");
            }
        }
Esempio n. 7
0
        public static void AddOutgoingMessage(string planet, CommPacketDirection direction, WsMessage message)
        {
            var outgoingQueue = OutgoingQueueDirection[direction];

            if (!outgoingQueue.TryGetValue(planet, out var collection))
            {
                collection = new BlockingCollection <WsMessage>();
                if (!outgoingQueue.TryAdd(planet, collection))
                {
                    collection = outgoingQueue[planet];
                }
            }

            collection.Add(message);
        }
        public static void WriteBytes(byte[] buffer, int count, CommPacketDirection direction, ConnectionInstance connectionInstance)
        {
            if (instance == null || !instance.Data.CaptureEnabled)
            {
                return;
            }

            try
            {
                byte[] saveData = new byte[count];
                Buffer.BlockCopy(buffer, 0, saveData, 0, count);

                var length             = saveData.Search(saveData.Length, new byte[] { 13, 10 });
                var dataStringSegments = Encoding.UTF8.GetString(saveData, 0, length).Split(' ');

                string header = "HTTP Data";

                if (dataStringSegments[2].StartsWith("HTTP"))
                {
                    header = $"{dataStringSegments[0]} {dataStringSegments[1]}";
                }
                else if (dataStringSegments[0].StartsWith("HTTP"))
                {
                    var desc = dataStringSegments[2];

                    for (int i = 3; i < dataStringSegments.Length; ++i)
                    {
                        desc += $" {dataStringSegments[i]}";
                    }

                    header = $"{dataStringSegments[1]} {desc}";
                }

                instance.Data.SendBytesToUi(connectionInstance, new CommPacket
                {
                    Data         = saveData,
                    Direction    = direction,
                    Id           = Guid.NewGuid(),
                    Instance     = connectionInstance,
                    ParentPacket = null,
                    Header       = header,
                });
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error in WriteBytes");
            }
        }
Esempio n. 9
0
        private static List <WsMessage> GetOutgoingMessages(string planet, CommPacketDirection direction)
        {
            var outgoingQueue = OutgoingQueueDirection[direction];

            List <WsMessage> result = new List <WsMessage>();

            if (outgoingQueue.TryGetValue(planet, out var collection))
            {
                while (collection.TryTake(out var curItem))
                {
                    result.Add(curItem);
                }
            }

            return(result);
        }
Esempio n. 10
0
        private void Dispatcher(CommPacketDirection direction)
        {
            new Thread(() =>
            {
                try
                {
                    var myQueue = websocketDataQueue[direction];
                    OnFrameHandler myHandler()
                    {
                        return(direction == CommPacketDirection.ClientToServer ? onFrameOut : onFrameIn);
                    }

                    while (true)
                    {
                        WsFrame curFrame;

                        try
                        {
                            curFrame = myQueue.Take();
                        }
                        catch
                        {
                            break;
                        }

                        var curHandler = myHandler();

                        if (curHandler != null)
                        {
                            foreach (OnFrameHandler curInvoke in curHandler.GetInvocationList())
                            {
                                try
                                {
                                    curInvoke(planetId, planetDisplayName ?? string.Empty, curFrame);
                                }
                                catch
                                {
                                }
                            }
                        }
                    }
                }
                catch
                {
                }
            }).Start();
        }
        private void DestinationWrite(Stream destination, byte[] buffer, int count, CommPacketDirection direction)
        {
            if (m_connectionInstance.Parent.Model.CaptureEnabled)
            {
                byte[] saveData = buffer.Take(count).ToArray();

                MainWindow.Instance.Dispatcher.BeginInvoke(new Action(() =>
                {
                    var packet = new CommPacket
                    {
                        Data      = saveData,
                        Direction = direction,
                        HostName  = m_connectionInstance.HostName,
                        Id        = Guid.NewGuid(),
                        Parent    = m_connectionInstance,
                    };

                    m_connectionInstance.Packets.Add(packet);

                    while (m_connectionInstance.Packets.Count > 1000)
                    {
                        var curPacket = m_connectionInstance.Packets[0];

                        m_connectionInstance.Packets.RemoveAt(0);

                        curPacket.Searches.ToList().ForEach(cur => cur.Packets.Remove(curPacket));
                    }

                    foreach (var curSearch in m_connectionInstance.Parent.Model.Searches)
                    {
                        if (saveData.Search(count, curSearch.searchBytes) > -1)
                        {
                            packet.Searches.Add(curSearch);
                            curSearch.Packets.Add(packet);
                        }
                    }
                }));
            }

            destination.Write(buffer, 0, count);
        }
Esempio n. 12
0
 private void DestinationWrite(Stream destination, string entireMessage, CommPacketDirection direction)
 {
     byte[] sendBytes = Encoding.UTF8.GetBytes(entireMessage);
     DestinationWrite(destination, sendBytes, sendBytes.Length, direction);
 }
Esempio n. 13
0
        private void ForwardHttpData(Stream destination, string entireMessage, CommPacketDirection direction)
        {
            if (planetDisplayName == null &&
                entireMessage.Contains("\"worldData\"") &&
                entireMessage.Contains("\"displayName\"") &&
                entireMessage.Contains("\"id\"") &&
                entireMessage.Contains("\"name\""))
            {
                try
                {
                    var gameserverJson = JObject.Parse(entireMessage.Substring(entireMessage.IndexOf("\r\n\r\n") + 4));

                    planetId          = gameserverJson["worldData"]["id"].Value <int>();
                    planetDisplayName = gameserverJson["worldData"]["displayName"].ToString();
                    planetStringName  = gameserverJson["worldData"]["name"].ToString();

                    if (!planetLookup.ContainsKey(planetStringName))
                    {
                        planetLookup.Add(planetStringName, new KeyValuePair <string, int>(planetDisplayName, planetId));
                    }
                }
                catch { }
            }

            if (ReplaceIpaddr && entireMessage.Contains("ipAddr"))
            {
                Regex ipSubPattern = new Regex("\\,\"ipAddr\":\"(?!127\\.0\\.0\\.1)[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\"\\,");
                Match ipSubMatch   = ipSubPattern.Match(entireMessage);

                if (ipSubMatch.Success)
                {
                    Regex reg = new Regex("Content-Length\\: ([0-9]+)", RegexOptions.IgnoreCase);
                    Match m   = reg.Match(entireMessage);

                    int length    = Convert.ToInt32(m.Groups[1].Value);
                    int newLength = length;

                    if (!m.Success)
                    {
                        throw new Exception("This shouldn't happen...");
                    }

                    int lenBeforeReplace = entireMessage.Length;

                    while (ipSubMatch.Success)
                    {
                        string org = ipSubMatch.Groups[0].Value;
                        string rep = ",\"ipAddr\":\"127.0.0.1\",";
                        entireMessage = entireMessage.Replace(org, rep);

                        ipSubMatch = ipSubPattern.Match(entireMessage);
                    }

                    int lenAfterReplace = entireMessage.Length;
                    newLength += lenAfterReplace - lenBeforeReplace;

                    entireMessage = entireMessage.Replace(m.Groups[0].Value, $"Content-Length: {newLength}");

                    DestinationWrite(destination, entireMessage, direction);
                }
                else
                {
                    DestinationWrite(destination, entireMessage, direction);
                }
            }
            else
            {
                DestinationWrite(destination, entireMessage, direction);
            }
        }
Esempio n. 14
0
        private void ForwardStreamNew(Stream source, Stream destination, byte[] buffer, CommPacketDirection direction)
        {
            var rawVerbs = new string[] { "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" };

            byte[][] verbs = rawVerbs.Select(cur => Encoding.UTF8.GetBytes(cur).Take(2).ToArray()).ToArray();
            Regex    requestLinePattern   = new Regex($"^({string.Join("|", rawVerbs)}) [^ ]+ HTTP/1.1$");
            Regex    contentLengthPattern = new Regex($"^Content-Length: ([0-9]+)$");
            Regex    chunkedPattern       = new Regex($"^Transfer-Encoding: chunked$");
            Regex    statusLinePattern    = new Regex($"^HTTP/1.1 ([0-9]+) (.*)$");
            Regex    websocketPlanet      = new Regex("GET /([0-9]+)/websocket/game HTTP/1.1");
            Regex    udpPortPattern       = new Regex("\"udpPort\"\\:([0-9]+)\\,");

            try
            {
                destination = new BufferedStream(destination);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating buffered stream");
                return;
            }

            new Thread(() =>
            {
                MemoryStream ms = null;

                try
                {
                    bool isWebSocket = false;

                    while (true)
                    {
                        try
                        {
                            destination.Flush();
                        }
                        catch (Exception ex)
                        {
                            Log.Error(ex, "Error Flushing stream");
                            Kill(direction == CommPacketDirection.ServerToClient);
                        }

                        if (!m_connectionInstance.IsConnectionOpen)
                        {
                            break;
                        }

                        //if (ms != null)
                        //{
                        //    ms.Position = 0;
                        //    messagecache[direction].Enqueue(ms);
                        //}

                        //while (messagecache[direction].Count > 10)
                        //{
                        //    messagecache[direction].Dequeue();
                        //}

                        ms = new MemoryStream();
                        StreamWriter sw = null;

                        bool ReadBytes(int count)
                        {
                            int offset = 0;

                            while (offset < count)
                            {
                                int bytesRead = 0;

                                try
                                {
                                    bytesRead = source.Read(buffer, offset, count - offset);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error(ex, "Error Reading stream");
                                    Kill(direction == CommPacketDirection.ClientToServer);
                                }

                                if (bytesRead == 0)
                                {
                                    return(false);
                                }

                                offset += bytesRead;
                            }

                            return(true);
                        }

                        string ReadLine()
                        {
                            List <byte> result = new List <byte>();

                            byte?prevByte = null;

                            while (true)
                            {
                                byte[] readBuffer = new byte[1];
                                if (source.Read(readBuffer, 0, 1) != 1)
                                {
                                    return(null);
                                }

                                result.Add(readBuffer[0]);

                                if (prevByte == '\r' && readBuffer[0] == '\n')
                                {
                                    break;
                                }

                                prevByte = readBuffer[0];
                            }

                            return(Encoding.UTF8.GetString(result.ToArray()).TrimEnd('\r', '\n'));
                        }

                        void DoHttpHeadersContentAndForward()
                        {
                            List <string> headers = new List <string>();

                            ulong contentLength = 0;
                            bool chunked        = false;

                            string curLine = null;
                            while ((curLine = ReadLine()) != null && curLine != string.Empty)
                            {
                                sw.WriteLine(curLine);

                                curLine = curLine.Trim();

                                Match m = contentLengthPattern.Match(curLine);
                                if (m.Success)
                                {
                                    contentLength = Convert.ToUInt64(m.Groups[1].Value);
                                }

                                m = chunkedPattern.Match(curLine);
                                if (m.Success)
                                {
                                    chunked = true;
                                }

                                headers.Add(curLine.ToLower());
                            }

                            sw.WriteLine();
                            sw.Flush();

                            if (curLine == null)
                            {
                                throw new Exception("HTTP unexpected end of stream while reading headers");
                            }

                            if (chunked && contentLength > 0)
                            {
                                throw new Exception("Chunked content with length not supported");
                            }

                            void DoReadLength(ulong curLength)
                            {
                                while (curLength > 0)
                                {
                                    int bytesRead = 0;

                                    try
                                    {
                                        bytesRead = source.Read(buffer, 0, Math.Min(buffer.Length, (int)Math.Min(int.MaxValue, curLength)));
                                    }
                                    catch (Exception ex)
                                    {
                                        Log.Error(ex, "Error reading bytes");
                                        Kill(direction == CommPacketDirection.ClientToServer);
                                    }

                                    if (bytesRead == 0)
                                    {
                                        throw new Exception("HTTP unexpected end of stream while reading content");
                                    }

                                    ms.Write(buffer, 0, bytesRead);
                                    curLength -= (ulong)bytesRead;
                                }
                            }

                            DoReadLength(contentLength);

                            if (chunked)
                            {
                                bool lastChunk = false;

                                while (!lastChunk && (curLine = ReadLine()) != null && curLine != string.Empty)
                                {
                                    sw.WriteLine(curLine);
                                    sw.Flush();

                                    var length = ulong.Parse(curLine.Trim());

                                    if (length > 0)
                                    {
                                        DoReadLength(length);
                                    }
                                    else
                                    {
                                        lastChunk = true;
                                    }

                                    curLine = ReadLine();

                                    if (curLine == null || curLine.Length != 0)
                                    {
                                        throw new Exception("HTTP protocol failure");
                                    }

                                    sw.WriteLine();
                                    sw.Flush();
                                }
                            }

                            ms.Position = 0;
                            if (!headers.Contains("content-type: application/json".ToLower()))
                            {
                                DestinationWrite(destination, ms.ToArray(), (int)ms.Length, direction);
                            }
                            else
                            {
                                var orgLength        = ms.Length;
                                string entireMessage = new StreamReader(ms).ReadToEnd();
                                ForwardHttpData(destination, entireMessage, direction);
                            }
                        }

                        void forwardWebsocketFrame()
                        {
                            WsFrame frame = null;

                            try
                            {
                                frame = new WsFrame(buffer, 2, source);
                            }
                            catch (Exception ex) {
                                Log.Error(ex, "Error creating WsFrame");
                            }

                            var worldData = frame?.Messages.FirstOrDefault(cur => cur.ApiId.HasValue && cur.ApiId.Value == 0);

                            if (worldData != null)
                            {
                                string theJson = Encoding.UTF8.GetString(worldData.Buffer, 0, worldData.Buffer.Length);

                                Match m = udpPortPattern.Match(theJson);

                                if (m.Success && planetStringName != null)
                                {
                                    int serverPort = Convert.ToInt32(m.Groups[1].Value);

                                    if (serverPort.ToString().Length != 4)
                                    {
                                        throw new Exception("Length change of udpPort");
                                    }

                                    if (!planetPorts.ContainsKey(planetStringName))
                                    {
                                        //throw new Exception($"Planet dictionary does not contain {planetStringName}");
                                    }
                                    else
                                    {
                                        planetPorts[planetStringName].RemotePort = serverPort;
                                        theJson = udpPortPattern.Replace(theJson, $"\"udpPort\":{planetPorts[planetStringName].LocalPort},");

                                        byte[] sendData = Encoding.UTF8.GetBytes(theJson);

                                        if (sendData.Length != worldData.Buffer.Length)
                                        {
                                            throw new Exception("JSON length error");
                                        }

                                        worldData.Buffer = sendData;
                                    }
                                }
                            }

                            if (planetStringName != null)
                            {
                                frame?.Messages.AddRange(GetOutgoingMessages(planetStringName, direction));
                            }

                            try
                            {
                                frame?.Send(destination);
                            }
                            catch (Exception ex)
                            {
                                Log.Error(ex, "Error sending frame");
                                Kill(direction == CommPacketDirection.ServerToClient);
                            }

                            //if (frame.readStream.Length != frame.writeStream.Length)
                            //{
                            //    throw new Exception("frame length mismatch.");
                            //}

                            //if (!frame.readStream.ToArray().SequenceEqual(frame.writeStream.ToArray()))
                            //{
                            //    throw new Exception("frame data mismatch.");
                            //}

                            if (frame == null)
                            {
                                frame = new WsFrame()
                                {
                                    Messages = new List <WsMessage>
                                    {
                                        new WsMessage(24, null, Encoding.UTF8.GetBytes("Frame decoding failure!")),
                                    },
                                };
                            }

                            try
                            {
                                websocketDataQueue[direction].Add(frame);
                            }
                            catch (Exception ex) {
                                Log.Error(ex, "Error adding frame to queue");
                            }

                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                ProxyUiWindow.AddFrame(frame, direction, m_connectionInstance);
                            });
                        }

                        if (!ReadBytes(2))
                        {
                            // Connection terminated waiting for new message. This is fine.
                            break;
                        }

                        if (direction == CommPacketDirection.ClientToServer)
                        {
                            if (!verbs.Any(cur => cur[0] == buffer[0] && cur[1] == buffer[1]) && !isWebSocket)
                            {
                                isWebSocket = true;
                                ProxyManagerWindow.Instance.Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    m_connectionInstance.Parent.Instances.Remove(m_connectionInstance);

                                    var wsg = ComponentEngine.Instance.GetComponent <TcpComponent>().websocketGroup;
                                    m_connectionInstance.Parent = wsg;
                                    wsg.Instances.Add(m_connectionInstance);
                                }));
                            }

                            if (!isWebSocket)
                            {
                                // GET /index.html HTTP/1.1
                                sw = new StreamWriter(ms);

                                string requestLine = (Encoding.UTF8.GetString(buffer, 0, 2) + ReadLine()).Trim();
                                sw.WriteLine(requestLine);

                                if (!requestLinePattern.IsMatch(requestLine))
                                {
                                    throw new Exception("HTTP request line invalid");
                                }

                                Match m = websocketPlanet.Match(requestLine);
                                if (m.Success)
                                {
                                    var newVal = Convert.ToInt32(m.Groups[1].Value);

                                    if (planetId != -1)
                                    {
                                        if (planetId != newVal)
                                        {
                                            throw new Exception("Multiple planets detected on a single stream");
                                        }
                                    }
                                    else
                                    {
                                        planetId          = newVal;
                                        planetStringName  = planetLookup.Where(cur => cur.Value.Value == newVal).FirstOrDefault().Key;
                                        planetDisplayName = planetLookup[planetStringName].Key;
                                    }
                                }

                                DoHttpHeadersContentAndForward();
                            }
                            else
                            {
                                forwardWebsocketFrame();
                            }
                        }
                        else
                        {
                            if ((buffer[0] != 'H' || buffer[1] != 'T') && !isWebSocket)
                            {
                                isWebSocket = true;
                                ProxyManagerWindow.Instance.Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    m_connectionInstance.Parent.Instances.Remove(m_connectionInstance);

                                    var wsg = ComponentEngine.Instance.GetComponent <TcpComponent>().websocketGroup;
                                    m_connectionInstance.Parent = wsg;
                                    wsg.Instances.Add(m_connectionInstance);
                                }));
                            }

                            if (!isWebSocket)
                            {
                                // HTTP/1.1 200 OK
                                sw = new StreamWriter(ms);

                                string statusLine = (Encoding.UTF8.GetString(buffer, 0, 2) + ReadLine()).Trim();

                                sw.WriteLine(statusLine);

                                if (!statusLinePattern.IsMatch(statusLine))
                                {
                                    throw new Exception("HTTP status line invalid");
                                }

                                DoHttpHeadersContentAndForward();
                            }
                            else
                            {
                                forwardWebsocketFrame();
                            }
                        }
                    }

                    Log.Information("Killing connection");
                    Kill(direction == CommPacketDirection.ClientToServer);
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Forward Stream error");
                    Kill(direction == CommPacketDirection.ClientToServer);
                }
            }).Start();
        }