Example #1
0
 private bool processFrame(WsFrame frame)
 {
     return frame.IsCompressed && _compression == CompressionMethod.NONE
      ? processUnsupportedFrame (
          frame,
          CloseStatusCode.INCORRECT_DATA,
          "A compressed data has been received without available decompression method.")
      : frame.IsFragmented
        ? processFragmentedFrame (frame)
        : frame.IsData
          ? processDataFrame (frame)
          : frame.IsPing
            ? processPingFrame (frame)
            : frame.IsPong
              ? processPongFrame ()
              : frame.IsClose
                ? processCloseFrame (frame)
                : processUnsupportedFrame (frame, CloseStatusCode.POLICY_VIOLATION, null);
 }
Example #2
0
        private bool processUnsupportedFrame(WsFrame frame, CloseStatusCode code, string reason)
        {
            _logger.Debug ("Unsupported frame:\n" + frame.PrintToString (false));
              processException (new WebSocketException (code, reason), null);

              return false;
        }
Example #3
0
        private bool processCloseFrame(WsFrame frame)
        {
            var payload = frame.PayloadData;
              close (payload, !payload.ContainsReservedCloseStatusCode, false);

              return false;
        }
Example #4
0
 private bool processFragmentedFrame(WsFrame frame)
 {
     return frame.IsContinuation // Not first fragment
      ? true
      : processFragments (frame);
 }
Example #5
0
 private bool acceptFrame(WsFrame frame)
 {
     return frame.IsCompressed && _compression == CompressionMethod.None
      ? acceptUnsupportedFrame (
          frame,
          CloseStatusCode.IncorrectData,
          "A compressed data has been received without available decompression method.")
      : frame.IsFragmented
        ? acceptFragmentedFrame (frame)
        : frame.IsData
          ? acceptDataFrame (frame)
          : frame.IsPing
            ? acceptPingFrame (frame)
            : frame.IsPong
              ? acceptPongFrame (frame)
              : frame.IsClose
                ? acceptCloseFrame (frame)
                : acceptUnsupportedFrame (frame, CloseStatusCode.PolicyViolation, null);
 }
Example #6
0
        private bool acceptPongFrame(WsFrame frame)
        {
            _receivePong.Set ();
              _logger.Trace ("Received a Pong.");

              return true;
        }
Example #7
0
        private bool processData(WsFrame frame)
        {
            if (!frame.IsData)
            return false;

              if (frame.IsCompressed && _compression == CompressionMethod.NONE)
            return false;

              var args = frame.IsCompressed
               ? new MessageEventArgs (
                   frame.Opcode, frame.PayloadData.ApplicationData.Decompress (_compression))
               : new MessageEventArgs (frame.Opcode, frame.PayloadData);

              OnMessage.Emit (this, args);
              return true;
        }
Example #8
0
        private bool acceptDataFrame(WsFrame frame)
        {
            var args = frame.IsCompressed
                 ? new MessageEventArgs (
                     frame.Opcode, frame.PayloadData.ApplicationData.Decompress (_compression))
                 : new MessageEventArgs (frame.Opcode, frame.PayloadData);

              if (_readyState == WebSocketState.Open)
            OnMessage.Emit (this, args);

              return true;
        }
Example #9
0
        private bool processAbnormal(WsFrame frame)
        {
            if (frame != null)
            return false;

              _logger.Trace ("Start closing handshake.");
              var code = CloseStatusCode.ABNORMAL;
              Close (code, code.GetMessage ());

              return true;
        }
Example #10
0
        private bool processClose(WsFrame frame)
        {
            if (!frame.IsClose)
            return false;

              _logger.Trace ("Start closing handshake.");
              close (frame.PayloadData);

              return true;
        }
Example #11
0
        private bool processPong(WsFrame frame)
        {
            if (!frame.IsPong)
            return false;

              #if DEBUG
              Console.WriteLine("WS: Info@processPong: Receive Pong.");
              #endif
              _receivePong.Set();

              return true;
        }
Example #12
0
        private bool processPing(WsFrame frame)
        {
            if (!frame.IsPing)
            return false;

              #if DEBUG
              Console.WriteLine("WS: Info@processPing: Return Pong.");
              #endif
              pong(frame.PayloadData);

              return true;
        }
Example #13
0
        private bool processClose(WsFrame frame)
        {
            if (!frame.IsClose)
            return false;

              #if DEBUG
              Console.WriteLine("WS: Info@processClose: Start closing handshake.");
              #endif
              close(frame.PayloadData);

              return true;
        }
Example #14
0
        private bool processAbnormal(WsFrame frame)
        {
            if (frame != null)
            return false;

              #if DEBUG
              Console.WriteLine("WS: Info@processAbnormal: Start closing handshake.");
              #endif
              var code = CloseStatusCode.ABNORMAL;
              Close(code, code.GetMessage());

              return true;
        }
Example #15
0
        private bool processFragmented(WsFrame frame)
        {
            // Not first fragment
              if (frame.IsContinuation)
            return true;

              // Not fragmented
              if (frame.IsFinal)
            return false;

              bool incorrect = !frame.IsData ||
                       (frame.IsCompressed && _compression == CompressionMethod.NONE);

              if (!incorrect)
            processFragments (frame);
              else
            processIncorrectFrame ();

              return true;
        }
        public bool WriteFrame(WsFrame frame)
        {
            lock (_forWrite)
              {
            try
            {
              var buffer = frame.ToBytes();
              write(buffer, 0, buffer.Length);

              return true;
            }
            catch
            {
              return false;
            }
              }
        }
Example #17
0
        private void processFrame(WsFrame frame)
        {
            bool processed = processAbnormal (frame) ||
                       processFragmented (frame) ||
                       processData (frame) ||
                       processPing (frame) ||
                       processPong (frame) ||
                       processClose (frame);

              if (!processed)
            processIncorrectFrame ();
        }
Example #18
0
 private bool acceptFragmentedFrame(WsFrame frame)
 {
     return frame.IsContinuation // Not first fragment
      ? true
      : acceptFragments (frame);
 }
Example #19
0
        private bool processPing(WsFrame frame)
        {
            if (!frame.IsPing)
            return false;

              _logger.Trace ("Return Pong.");
              pong (frame.PayloadData);

              return true;
        }
Example #20
0
        private bool acceptPingFrame(WsFrame frame)
        {
            var mask = _client ? Mask.Mask : Mask.Unmask;
              if (send (WsFrame.CreatePongFrame (mask, frame.PayloadData)))
            _logger.Trace ("Returned a Pong.");

              return true;
        }
Example #21
0
        private bool processPong(WsFrame frame)
        {
            if (!frame.IsPong)
            return false;

              _logger.Trace ("Receive Pong.");
              _receivePong.Set ();

              return true;
        }
Example #22
0
        private bool send(WsFrame frame)
        {
            lock (_forConn) {
            if (_readyState != WebSocketState.Open) {
              _logger.Warn ("Sending has been interrupted.");
              return false;
            }

            return _stream.Write (frame.ToByteArray ());
              }
        }
Example #23
0
        private bool send(WsFrame frame)
        {
            lock (_forFrame)
              {
            var ready = _stream == null
                    ? false
                    : _readyState == WebSocketState.OPEN
                      ? true
                      : _readyState == WebSocketState.CLOSING
                        ? frame.IsClose
                        : false;

            if (!ready)
            {
              var msg = "The WebSocket connection isn't established or has been closed.";
              _logger.Error (msg);
              error (msg);

              return false;
            }

            return _stream.WriteFrame (frame);
              }
        }
Example #24
0
        private bool processDataFrame(WsFrame frame)
        {
            var args = frame.IsCompressed
               ? new MessageEventArgs (
                   frame.Opcode, frame.PayloadData.ApplicationData.Decompress (_compression))
               : new MessageEventArgs (frame.Opcode, frame.PayloadData);

              OnMessage.Emit (this, args);
              return true;
        }
Example #25
0
        private static WsFrame createControlFrame(Opcode opcode, PayloadData payloadData, bool client)
        {
            var mask = client ? Mask.MASK : Mask.UNMASK;
              var frame = new WsFrame (Fin.FINAL, opcode, mask, payloadData);

              return frame;
        }
Example #26
0
        private bool processFragments(WsFrame first)
        {
            using (var concatenated = new MemoryStream ())
              {
            concatenated.WriteBytes (first.PayloadData.ApplicationData);
            if (!concatenateFragmentsInto (concatenated))
              return false;

            byte [] data;
            if (_compression != CompressionMethod.NONE)
            {
              data = concatenated.DecompressToArray (_compression);
            }
            else
            {
              concatenated.Close ();
              data = concatenated.ToArray ();
            }

            OnMessage.Emit (this, new MessageEventArgs (first.Opcode, data));
            return true;
              }
        }
Example #27
0
        private static WsFrame createFrame(
      Fin fin, Opcode opcode, PayloadData payloadData, bool compressed, bool client)
        {
            var mask = client ? Mask.MASK : Mask.UNMASK;
              var frame = new WsFrame (fin, opcode, mask, payloadData, compressed);

              return frame;
        }
Example #28
0
        private bool processPingFrame(WsFrame frame)
        {
            if (send (WsFrame.CreatePongFrame (_client ? Mask.MASK : Mask.UNMASK, frame.PayloadData)))
            _logger.Trace ("Returned Pong.");

              return true;
        }
 public bool WriteFrame(WsFrame frame)
 {
     return Write (frame.ToByteArray ());
 }
Example #30
0
        private bool send(WsFrame frame)
        {
            if (_readyState != WebSocketState.OPEN)
              {
            var msg = "A WebSocket connection isn't established or has been closed.";
            _logger.Error (msg);
            error (msg);

            return false;
              }

              return _stream.Write (frame.ToByteArray ());
        }
Example #31
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();
        }