Example #1
0
 private void BtnSend_Click(object sender, RoutedEventArgs e)
 {
     if (UdpSocket != null)
     {
         CommPacket oCommPacket = new CommPacket()
         {
             PacketID = int.Parse(TxtProtocolID.Text),
             Content  = TxtProtoclContet.Text,
         };
         UdpSocket.UserToken.SendAsync(oCommPacket);
     }
 }
Example #2
0
        private void ProcessUdpPacket(CommPacket packet, IPEndPoint ep)
        {
            PeerData peer = null;

            if (packet is UdpConnectingConfirmation)
            {
                AddPeerToDictionaries(NewPeer);
                if (ReceivedConfirmation != null)
                {
                    ReceivedConfirmation.Set();
                }
            }
            else if (packet is UdpNewPeerPacket)
            {
                UdpNewPeerPacket newPeerPacket = packet as UdpNewPeerPacket;
                if (newPeerPacket.RecipientIsNew && AwaitingExternalConnection)
                {
                    AwaitingExternalConnection = false;
                    AddPeersToDictionaries(newPeerPacket.Peers);

                    StartDriver(newPeerPacket.SubnetworkData, newPeerPacket.SubnetworkIP, newPeerPacket.Name);
                    OnConnected(this, null);

                    UdpConnectingConfirmation confirmPacket = new UdpConnectingConfirmation();
                    SendPacket <UdpConnectingConfirmation>(confirmPacket, ep);

                    Thread.Sleep(100);
                    NegotiateKey(PeersRxSupport[ep], null);
                }
                else
                {
                    if (newPeerPacket.Peers != null && !newPeerPacket.RecipientIsNew)
                    {
                        if (newPeerPacket.Peers.Length != 0)
                        {
                            AddPeerToDictionaries(newPeerPacket.Peers[0]);
                            NegotiateKey(peer, null);
                        }
                    }
                }
            }
            else if (packet is UdpKeyNegotiationPacket)
            {
                if (!PeersRxSupport.TryGetValue(ep, out peer))
                {
                    peer = NewPeer;
                }
                NegotiateKey(peer, packet as UdpKeyNegotiationPacket);
            }
            else if (packet is UdpGoodbye)
            {
                RemovePeerFromDictionaries(PeersRxSupport[ep], "goodbye");
            }
            else if (packet is UdpHeartbeat)
            {
                if (PeersRxSupport.TryGetValue(ep, out peer))
                {
                    peer.Heartbeat();
                }
            }
        }
Example #3
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
            {
                return;
            }

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

                try
                {
                    bool isWebSocket = false;

                    while (true)
                    {
                        try
                        {
                            destination.Flush();
                        }
                        catch
                        {
                            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
                                {
                                    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
                                    {
                                        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 { }

                            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
                            {
                                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 { }

                            if (ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().CaptureEnabled)
                            {
                                var parentPacket = new CommPacket
                                {
                                    Data         = frame.HeaderBytes,
                                    Direction    = direction,
                                    Id           = Guid.NewGuid(),
                                    Instance     = m_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     = m_connectionInstance,
                                        ParentPacket = parentPacket,
                                        Header       = $"Websocket Message[0x{curMessage.ApiId ?? 0:X2}]",
                                    };

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

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

                                ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().SendBytesToUi(m_connectionInstance, parentPacket);
                            }
                        }

                        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();
                            }
                        }
                    }

                    Kill(direction == CommPacketDirection.ClientToServer);
                }
                catch (Exception)
                {
                    //MainWindow.Instance.Dispatcher.Invoke(new Action(() =>
                    //{
                    //    MessageBox.Show($"4 Fatal error: {ex.Message}");
                    //}));

                    Kill(direction == CommPacketDirection.ClientToServer);
                }
            }).Start();
        }