예제 #1
0
        public void WebSocketFrame_TryParse_Valid_DataFrame_Text_SingleFrame()
        {
            string testContent = "test!";

            bool            fin    = true;
            WebSocketOPCode OPCode = WebSocketOPCode.Text;

            byte[] payload = System.Text.Encoding.UTF8.GetBytes(testContent);



            // Manually craft a WebSocketFrame
            Random rnd = new Random();

            byte[] maskingK = new byte[4];
            // The masking key is supposed to be cryptographically secure but this will suffice for testing purposes
            rnd.NextBytes(maskingK);
        }
예제 #2
0
        /// <summary>
        /// Tries to parse a byte[] header into a SocketDataFrame object.
        /// Returns a null reference if object cannot be parsed
        /// </summary>
        /// <param name="headerBytes">A byte array containing the read frame header bytes</param>
        /// <param name="socket">A reference to the socket from which to parse the SocketFrame</param>
        /// <returns>
        /// If pasrse is successful, an Object of a type that is derived from SocketFrame.abstract Returns a null pointer otherwise.
        /// </returns>
        /// <remarks>
        /// This method is not exactly like the Int*.TryParse() methods as it doesn't take an 'out' parameter and return a
        /// boolean value but rather returns either the parsed object reference or a null reference, which means that callers of this method need to check
        /// for null before using the return value.
        /// Furthermore, if the parse is successful, a caller should check the type of the object that is returned to, for example,
        /// differenciate between a SocketDataFrame and a SocketControlFrame, which are both derived from SocketFrame.
        /// It is necessary to pass a reference to the socket because of the way the WebSocket protocol is made.abstract It is impossible to know
        /// the length of the frame before having parsed the headers hence it is possible that more bytes will need to be read from the socket buffer.
        /// </remarks>
        public static WebSocketFrame TryParse(byte[] headerBytes, Socket socket)
        {
            int             headerSize    = headerBytes.Length;
            bool            fin           = (headerBytes[0] >> 7) != 0;
            WebSocketOPCode opcode        = (WebSocketOPCode)((byte)(headerBytes[0] & 0b00001111));
            bool            masked        = (headerBytes[1] & 0b10000000) != 0;
            ushort          contentLength = (ushort)(headerBytes[1] & 0b01111111);

            if (contentLength <= 126)
            {
                if (contentLength == 126)
                {
                    headerSize = 4;
                    byte[] largerHeader = new byte[headerSize];
                    headerBytes.CopyTo(largerHeader, 0);
                    // Read next two bytes and interpret them as the content length
                    socket.Receive(largerHeader, 2, 2, SocketFlags.None);
                    contentLength = (ushort)(largerHeader[2] <<  8 | largerHeader[3]);
                }

                byte[] maskingKey = new byte[4];
                socket.Receive(maskingKey);

                byte[] contentBuffer = new byte[contentLength];
                if (contentLength > 0)
                {
                    socket.Receive(contentBuffer);
                }

                WebSocketFrame frame;
                if (opcode == WebSocketOPCode.Text || opcode == WebSocketOPCode.Binary)
                {
                    frame = new WebSocketDataFrame(fin, masked, contentBuffer, (WebSocketDataFrame.DataFrameType)opcode, ApplyMask(contentBuffer, maskingKey));
                }
                else if (opcode == WebSocketOPCode.Close)
                {
                    WebSocketCloseFrame closeFrame = new WebSocketCloseFrame();
                    if (contentLength >= 2)
                    {
                        byte[]             unmasked  = ApplyMask(contentBuffer, maskingKey);
                        WebSocketCloseCode closeCode = (WebSocketCloseCode)BitConverter.ToUInt16(unmasked);
                        closeFrame.CloseCode = closeCode;

                        if (contentLength > 2)
                        {
                            byte[] closeReasonBytes = new byte[contentLength - 2];
                            Array.Copy(contentBuffer, 2, closeReasonBytes, 0, closeReasonBytes.Length);
                            closeFrame.CloseReason = System.Text.Encoding.UTF8.GetString(closeReasonBytes);
                        }
                    }

                    frame = closeFrame;
                }
                else
                {
                    frame = new WebSocketControlFrame(fin, masked, (WebSocketOPCode)opcode);
                }

                return(frame);
            }

            return(null);
        }
예제 #3
0
 /// <summary>
 /// Initializes a new instance of the SocketControlFrame class
 /// </summary>
 /// <param name="fin"></param>
 /// <param name="masked"></param>
 /// <param name="controlOpCode">The control OPCode of the current SocketControlFrame</param>
 public WebSocketControlFrame(bool fin, bool masked, WebSocketOPCode controlOpCode)
     : base(true, false, new byte[0], WebSocketDataFrame.DataFrameType.Binary)
 {
     this.opcode = (byte)controlOpCode;
 }