Exemple #1
0
        /// <summary>
        /// Returns a new WebSocketFrameHeader constructed from a set of fragments.
        /// </summary>
        /// <param name="fragmentStart">The header of the frame that started the set of fragments.</param>
        /// <param name="payloadLength">The combined total length of the payloads of all fragments in the set.</param>
        /// <returns></returns>
        internal static WebSocketFrameHeader FromFragments(WebSocketFrameHeader fragmentStart, int payloadLength)
        {
            WebSocketFrameHeader h = new WebSocketFrameHeader(fragmentStart);

            h.payloadLength = (ulong)payloadLength;
            return(h);
        }
Exemple #2
0
 internal WebSocketFrameHeader(WebSocketFrameHeader other)
 {
     fin           = other.fin;
     opcode        = other.opcode;
     mask          = other.mask;
     maskBytes     = other.maskBytes;
     payloadLength = other.payloadLength;
 }
Exemple #3
0
 internal void SendFrame(WebSocketOpcode opcode, byte[] data)
 {
     lock (sendLock)
     {
         // Write frame header
         WebSocketFrameHeader head = new WebSocketFrameHeader(opcode, data.Length);
         head.Write(tcpStream);
         // Write payload
         tcpStream.Write(data, 0, data.Length);
     }
 }
Exemple #4
0
        internal WebSocketBinaryFrame(WebSocketFrameHeader head, Stream stream) : base(head)
        {
            if (!head.fin || head.opcode == WebSocketOpcode.Continuation)
            {
                throw new WebSocketException(WebSocketCloseCode.InternalError, "WebSocketBinaryFrame stream constructor is not compatible with fragmented frames.");
            }

            if (head.payloadLength > (ulong)WebSocket.MAX_PAYLOAD_BYTES)
            {
                throw new WebSocketException(WebSocketCloseCode.MessageTooBig, null);
            }

            this.Data = ByteUtil.ReadNBytes(stream, (int)head.payloadLength);
            Head.XORMask(this.Data);
        }
Exemple #5
0
        internal WebSocketCloseFrame(WebSocketFrameHeader head, Stream stream) : base(head, stream)
        {
            if (Data.Length > 1)
            {
                CloseCode = (WebSocketCloseCode)ByteUtil.ReadInt16(Data, 0);
            }
            else
            {
                CloseCode = WebSocketCloseCode.None;
            }

            if (Data.Length > 2)
            {
                Message = ByteUtil.ReadUtf8(Data, 2, Data.Length - 2);
            }
        }
Exemple #6
0
        private void WebSocketRead()
        {
            WebSocketCloseFrame closeFrame = null;

            try
            {
                WebSocketFrameHeader fragmentStart = null;
                List <byte[]>        fragments     = new List <byte[]>();
                ulong totalLength = 0;
                while (true)
                {
                    WebSocketFrameHeader head = new WebSocketFrameHeader(tcpStream);

                    if (head.opcode == WebSocketOpcode.Close)
                    {
                        closeFrame = new WebSocketCloseFrame(head, tcpStream);
                        Send(WebSocketCloseCode.Normal);
                        //SimpleHttpLogger.LogVerbose("WebSocket connection closed with code: "
                        //	+ (ushort)closeFrame.CloseCode
                        //	+ " (" + closeFrame.CloseCode + ")"
                        //	 + (!string.IsNullOrEmpty(closeFrame.Message) ? " -- \"" + closeFrame.Message + "\"" : ""));
                        return;
                    }
                    else if (head.opcode == WebSocketOpcode.Ping)
                    {
                        WebSocketPingFrame pingFrame = new WebSocketPingFrame(head, tcpStream);
                        SendFrame(WebSocketOpcode.Pong, pingFrame.Data);
                        continue;
                    }
                    else if (head.opcode == WebSocketOpcode.Pong)
                    {
                        WebSocketPongFrame pingFrame = new WebSocketPongFrame(head, tcpStream);
                        continue;
                    }
                    else if (head.opcode == WebSocketOpcode.Continuation || head.opcode == WebSocketOpcode.Text || head.opcode == WebSocketOpcode.Binary)
                    {
                        // The WebSocket protocol supports payload fragmentation, which is the
                        // reason for much of the complexity to follow.
                        // (The primary purpose of fragmentation is to allow sending a message
                        // that is of unknown size when the message is started without having to
                        // buffer that message.)

                        // Validate Payload Length
                        totalLength += head.payloadLength;
                        if (totalLength > (ulong)MAX_PAYLOAD_BYTES)
                        {
                            throw new WebSocketException(WebSocketCloseCode.MessageTooBig);
                        }

                        // Keep track of the frame that started each set of fragments
                        if (fragmentStart == null)
                        {
                            if (head.opcode == WebSocketOpcode.Continuation)
                            {
                                throw new WebSocketException(WebSocketCloseCode.ProtocolError, "Continuation frame did not follow a Text or Binary frame.");
                            }
                            fragmentStart = head;
                        }

                        // Read the Frame's Payload
                        fragments.Add(ByteUtil.ReadNBytes(tcpStream, (int)head.payloadLength));

                        if (head.fin)
                        {
                            // This ends a set of 1 or more fragments.

                            // Assemble the final payload.
                            byte[] payload;
                            if (fragments.Count == 1)
                            {
                                payload = fragments[0];
                            }
                            else
                            {
                                // We must assemble a fragmented payload.
                                payload = new byte[(int)totalLength];
                                int soFar = 0;
                                for (int i = 0; i < fragments.Count; i++)
                                {
                                    byte[] part = fragments[i];
                                    fragments[i] = null;
                                    Array.Copy(part, 0, payload, soFar, part.Length);
                                    soFar += part.Length;
                                }
                            }

                            // Call onMessageReceived callback
                            try
                            {
                                if (fragmentStart.opcode == WebSocketOpcode.Text)
                                {
                                    onMessageReceived(new WebSocketTextFrame(fragmentStart, payload));
                                }
                                else
                                {
                                    onMessageReceived(new WebSocketBinaryFrame(fragmentStart, payload));
                                }
                            }
                            catch (ThreadAbortException) { }
                            catch (Exception ex)
                            {
                                if (!HttpProcessor.IsOrdinaryDisconnectException(ex))
                                {
                                    SimpleHttpLogger.Log(ex);
                                }
                            }

                            // Reset fragmentation state
                            fragmentStart = null;
                            fragments.Clear();
                            totalLength = 0;
                        }
                    }
                }
            }
            catch (ThreadAbortException)
            {
                if (closeFrame == null)
                {
                    closeFrame           = new WebSocketCloseFrame();
                    closeFrame.CloseCode = WebSocketCloseCode.Normal;
                }
                Try.Swallow(() =>
                {
                    tcpClient.SendTimeout = Math.Min(tcpClient.SendTimeout, 1000);
                    Send(closeFrame.CloseCode);
                });
            }
            catch (Exception ex)
            {
                bool isDisconnect = HttpProcessor.IsOrdinaryDisconnectException(ex);
                if (!isDisconnect)
                {
                    SimpleHttpLogger.LogVerbose(ex);
                }

                if (closeFrame == null)
                {
                    closeFrame           = new WebSocketCloseFrame();
                    closeFrame.CloseCode = isDisconnect ? WebSocketCloseCode.ConnectionLost : WebSocketCloseCode.InternalError;
                }
                Try.Swallow(() => { Send(closeFrame.CloseCode); });
            }
            finally
            {
                try
                {
                    if (closeFrame == null)
                    {
                        // This should not happen, but it is possible that further development could leave a code path where closeFrame did not get set.
                        closeFrame           = new WebSocketCloseFrame();
                        closeFrame.CloseCode = WebSocketCloseCode.InternalError;
                    }
                    onClose(closeFrame);
                }
                catch (ThreadAbortException) { }
                catch (Exception) { }
            }
        }
Exemple #7
0
 internal WebSocketPingFrame(WebSocketFrameHeader head, Stream stream) : base(head, stream)
 {
 }
Exemple #8
0
 internal WebSocketTextFrame(WebSocketFrameHeader head, byte[] data) : base(head, data)
 {
     this.Text = ByteUtil.ReadUtf8(Data);
 }
Exemple #9
0
 internal WebSocketTextFrame(WebSocketFrameHeader head, Stream stream) : base(head, stream)
 {
     this.Text = ByteUtil.ReadUtf8(Data);
 }
Exemple #10
0
 internal WebSocketBinaryFrame(WebSocketFrameHeader head, byte[] data) : base(head)
 {
     this.Data = data;
     Head.XORMask(this.Data);
 }
Exemple #11
0
 internal WebSocketFrame(WebSocketFrameHeader head)
 {
     this.Head = head;
 }