Пример #1
0
        public void SequenceLessThanMinimumHeaderLengthReturnsFalse()
        {
            var reader           = new WebSocketFrameReader();
            var sequence         = new ReadOnlySequence <byte>(new byte[0]);
            SequencePosition pos = default;

            var success = reader.TryParseMessage(sequence, ref pos, ref pos, out var message);

            Assert.False(success);
        }
Пример #2
0
        protected override void PerformHandshake(Stream stream)
        {
            Uri uri = _uri;
            WebSocketFrameReader reader = new WebSocketFrameReader();
            Random rand = new Random();

            byte[] keyAsBytes = new byte[16];
            rand.NextBytes(keyAsBytes);
            string secWebSocketKey = Convert.ToBase64String(keyAsBytes);

            string handshakeHttpRequestTemplate = "GET {0} HTTP/1.1\r\n" +
                                                  "Host: {1}:{2}\r\n" +
                                                  "Upgrade: websocket\r\n" +
                                                  "Connection: Upgrade\r\n" +
                                                  "Origin: http://{1}:{2}\r\n" +
                                                  "Sec-WebSocket-Key: {3}\r\n" +
                                                  "Sec-WebSocket-Version: 13\r\n\r\n";

            string handshakeHttpRequest = string.Format(handshakeHttpRequestTemplate, uri.PathAndQuery, uri.Host, uri.Port, secWebSocketKey);

            byte[] httpRequest = Encoding.UTF8.GetBytes(handshakeHttpRequest);
            stream.Write(httpRequest, 0, httpRequest.Length);
            _logger.Information("", this.GetType(), "Handshake sent. Waiting for response.");

            // make sure we escape the accept string which could contain special regex characters
            string regexPattern = "Sec-WebSocket-Accept: (.*)";
            Regex  regex        = new Regex(regexPattern);

            string response = string.Empty;

            try
            {
                response = HttpHelper.ReadHttpHeader(stream);
            }
            catch (Exception ex)
            {
                throw new WebSocketHandshakeFailedException("Handshake unexpected failure", ex);
            }

            // check the accept string
            string expectedAcceptString = base.ComputeSocketAcceptString(secWebSocketKey);
            string actualAcceptString   = regex.Match(response).Groups[1].Value.Trim();

            if (expectedAcceptString != actualAcceptString)
            {
                throw new WebSocketHandshakeFailedException(string.Format("Handshake failed because the accept string from the server '{0}' was not the expected string '{1}'", expectedAcceptString, actualAcceptString));
            }
            else
            {
                _logger.Information("", this.GetType(), "Handshake response received. Connection upgraded to WebSocket protocol.");
            }
        }
Пример #3
0
        public static WebSocketFrame ReadFrame(Stream stream, bool unmask)
        {
            Console.WriteLine("Reading stream...");
            var frame = WebSocketFrameReader.processHeader(stream.ReadBytes(2));

            WebSocketFrameReader.readExtPayLoadLength(stream, frame);
            WebSocketFrameReader.readMaskingKey(stream, frame);
            WebSocketFrameReader.readPayloadData(stream, frame);

            if (unmask)
            {
                frame.Unmask();
            }
            if (frame.Opcode == Opcode.Close)
            {
                frame.PayloadData.SetClosingCode();
            }

            return(frame);
        }
Пример #4
0
        public void WebSocketFrame_Parse()
        {
            var payload              = "{\"Hello\":\"World\"}";
            var payloadBuffer        = Encoding.UTF8.GetBytes(payload);
            var sourceWebSocketFrame = new WebSocketFrame {
                Opcode = WebSocketOpcode.Binary, Payload = payloadBuffer
            };

            sourceWebSocketFrame.Opcode = WebSocketOpcode.Ping;

            var memoryStream = new MemoryStream();

            new WebSocketFrameWriter(memoryStream).WriteAsync(sourceWebSocketFrame, CancellationToken.None).Wait();

            memoryStream.Position = 0;
            var targetWebSocketFrame = new WebSocketFrameReader(memoryStream).ReadAsync(CancellationToken.None).Result;

            Assert.AreEqual(sourceWebSocketFrame.Fin, targetWebSocketFrame.Fin);
            Assert.AreEqual(sourceWebSocketFrame.Opcode, targetWebSocketFrame.Opcode);
            CollectionAssert.AreEqual(payloadBuffer, targetWebSocketFrame.Payload);
        }
Пример #5
0
 public WebSocketPong(WebSocketFrameReader ping)
     : base(ping.Data)
 {
 }
Пример #6
0
        private void ReceiveThreadFunc()
        {
            try
            {
                using (var bufferedStream = new ReadOnlyBufferedStream(this.Stream))
                {
                    while (!closed)
                    {
                        try
                        {
                            WebSocketFrameReader frame = new WebSocketFrameReader();
                            frame.Read(bufferedStream);

                            lastMessage = DateTime.UtcNow;

                            // A server MUST NOT mask any frames that it sends to the client.  A client MUST close a connection if it detects a masked frame.
                            // In this case, it MAY use the status code 1002 (protocol error)
                            // (These rules might be relaxed in a future specification.)
                            if (frame.HasMask)
                            {
                                Close(1002, "Protocol Error: masked frame received from server!");
                                continue;
                            }

                            if (!frame.IsFinal)
                            {
                                if (OnIncompleteFrame == null)
                                {
                                    IncompleteFrames.Add(frame);
                                }
                                else
                                {
                                    CompletedFrames.Enqueue(frame);
                                }
                                continue;
                            }

                            switch (frame.Type)
                            {
                            // For a complete documentation and rules on fragmentation see http://tools.ietf.org/html/rfc6455#section-5.4
                            // A fragmented Frame's last fragment's opcode is 0 (Continuation) and the FIN bit is set to 1.
                            case WebSocketFrameTypes.Continuation:
                                // Do an assemble pass only if OnFragment is not set. Otherwise put it in the CompletedFrames, we will handle it in the HandleEvent phase.
                                if (OnIncompleteFrame == null)
                                {
                                    frame.Assemble(IncompleteFrames);

                                    // Remove all incomplete frames
                                    IncompleteFrames.Clear();

                                    // Control frames themselves MUST NOT be fragmented. So, its a normal text or binary frame. Go, handle it as usual.
                                    goto case WebSocketFrameTypes.Binary;
                                }
                                else
                                {
                                    CompletedFrames.Enqueue(frame);
                                }
                                break;

                            case WebSocketFrameTypes.Text:
                            case WebSocketFrameTypes.Binary:
                                frame.DecodeWithExtensions(WebSocket);
                                CompletedFrames.Enqueue(frame);
                                break;

                            // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame.
                            case WebSocketFrameTypes.Ping:
                                if (!closeSent && !closed)
                                {
                                    Send(new WebSocketFrame(this.WebSocket, WebSocketFrameTypes.Pong, frame.Data));
                                }
                                break;

                            case WebSocketFrameTypes.Pong:
                                try
                                {
                                    // Get the ticks from the frame's payload
                                    long ticksSent = BitConverter.ToInt64(frame.Data, 0);

                                    // the difference between the current time and the time when the ping message is sent
                                    TimeSpan diff = TimeSpan.FromTicks(lastMessage.Ticks - ticksSent);

                                    // add it to the buffer
                                    this.rtts.Add((int)diff.TotalMilliseconds);

                                    // and calculate the new latency
                                    this.Latency = CalculateLatency();
                                }
                                catch
                                {
                                    // https://tools.ietf.org/html/rfc6455#section-5.5
                                    // A Pong frame MAY be sent unsolicited.  This serves as a
                                    // unidirectional heartbeat.  A response to an unsolicited Pong frame is
                                    // not expected.
                                }

                                break;

                            // If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response.
                            case WebSocketFrameTypes.ConnectionClose:
                                CloseFrame = frame;
                                if (!closeSent)
                                {
                                    Send(new WebSocketFrame(this.WebSocket, WebSocketFrameTypes.ConnectionClose, null));
                                }
                                closed = true;
                                break;
                            }
                        }
#if !NETFX_CORE
                        catch (ThreadAbortException)
                        {
                            IncompleteFrames.Clear();
                            this.baseRequest.State = HTTPRequestStates.Aborted;

                            closed = true;

                            newFrameSignal.Set();
                        }
#endif
                        catch (Exception e)
                        {
                            if (HTTPUpdateDelegator.IsCreated)
                            {
                                this.baseRequest.Exception = e;
                                this.baseRequest.State     = HTTPRequestStates.Error;
                            }
                            else
                            {
                                this.baseRequest.State = HTTPRequestStates.Aborted;
                            }

                            closed = true;
                            newFrameSignal.Set();
                        }
                    }
                }
            }
            finally
            {
                HTTPManager.Heartbeats.Unsubscribe(this);
                HTTPUpdateDelegator.OnApplicationForegroundStateChanged -= OnApplicationForegroundStateChanged;

                HTTPManager.Logger.Information("WebSocketResponse", "ReceiveThread - Closed!");
            }
        }
Пример #7
0
        /// <summary>
        /// Internal function to send out received messages.
        /// </summary>
        internal void HandleEvents()
        {
            lock (FrameLock)
            {
                for (int i = 0; i < CompletedFrames.Count; ++i)
                {
                    WebSocketFrameReader frame = CompletedFrames[i];

                    // Bugs in the clients shouldn't interrupt the code, so we need to try-catch and ignore any exception occuring here
                    try
                    {
                        switch (frame.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            if (OnIncompleteFrame != null)
                            {
                                OnIncompleteFrame(this, frame);
                            }
                            break;

                        case WebSocketFrameTypes.Text:
                            // Any not Final frame is handled as a fragment
                            if (!frame.IsFinal)
                            {
                                goto case WebSocketFrameTypes.Continuation;
                            }

                            if (OnText != null)
                            {
                                OnText(this, Encoding.UTF8.GetString(frame.Data, 0, frame.Data.Length));
                            }
                            break;

                        case WebSocketFrameTypes.Binary:
                            // Any not Final frame is handled as a fragment
                            if (!frame.IsFinal)
                            {
                                goto case WebSocketFrameTypes.Continuation;
                            }

                            if (OnBinary != null)
                            {
                                OnBinary(this, frame.Data);
                            }
                            break;
                        }
                    }
                    catch
                    { }
                }

                CompletedFrames.Clear();
            }//lock (ReadLock)

            if (IsClosed && OnClosed != null)
            {
                try
                {
                    UInt16 statusCode = 0;
                    string msg        = string.Empty;

                    // If we received any data, we will get the status code and the message from it
                    if (CloseFrame != null && CloseFrame.Data != null && CloseFrame.Data.Length >= 2)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(CloseFrame.Data, 0, 2);
                        }
                        statusCode = BitConverter.ToUInt16(CloseFrame.Data, 0);

                        if (CloseFrame.Data.Length > 2)
                        {
                            msg = Encoding.UTF8.GetString(CloseFrame.Data, 2, CloseFrame.Data.Length - 2);
                        }
                    }

                    OnClosed(this, statusCode, msg);
                }
                catch
                { }
            }
        }
Пример #8
0
 public void SequenceLessThanMinimumPlusMaskReturnsFalse()
 {
     var reader      = new WebSocketFrameReader();
     var headerBytes = GetHeaderBytes(WebSocketHeader.CreateMasked(true, default, 64));
Пример #9
0
        private void ReceiveThreadFunc(object param)
        {
            try
            {
                while (!closed)
                {
                    try
                    {
                        WebSocketFrameReader webSocketFrameReader = new WebSocketFrameReader();
                        webSocketFrameReader.Read(Stream);
                        if (webSocketFrameReader.HasMask)
                        {
                            Close(1002, "Protocol Error: masked frame received from server!");
                        }
                        else if (webSocketFrameReader.IsFinal)
                        {
                            switch (webSocketFrameReader.Type)
                            {
                            case (WebSocketFrameTypes)3:
                            case (WebSocketFrameTypes)4:
                            case (WebSocketFrameTypes)5:
                            case (WebSocketFrameTypes)6:
                            case (WebSocketFrameTypes)7:
                                break;

                            case WebSocketFrameTypes.Continuation:
                                if (OnIncompleteFrame != null)
                                {
                                    lock (FrameLock)
                                    {
                                        CompletedFrames.Add(webSocketFrameReader);
                                    }
                                    break;
                                }
                                webSocketFrameReader.Assemble(IncompleteFrames);
                                IncompleteFrames.Clear();
                                goto case WebSocketFrameTypes.Text;

                            case WebSocketFrameTypes.Text:
                            case WebSocketFrameTypes.Binary:
                                lock (FrameLock)
                                {
                                    CompletedFrames.Add(webSocketFrameReader);
                                }
                                break;

                            case WebSocketFrameTypes.Ping:
                                if (!closeSent && !closed)
                                {
                                    Send(new WebSocketPong(webSocketFrameReader));
                                }
                                break;

                            case WebSocketFrameTypes.ConnectionClose:
                                CloseFrame = webSocketFrameReader;
                                if (!closeSent)
                                {
                                    Send(new WebSocketClose());
                                }
                                closed = closeSent;
                                break;
                            }
                        }
                        else if (OnIncompleteFrame == null)
                        {
                            IncompleteFrames.Add(webSocketFrameReader);
                        }
                        else
                        {
                            lock (FrameLock)
                            {
                                CompletedFrames.Add(webSocketFrameReader);
                            }
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        IncompleteFrames.Clear();
                        baseRequest.State = HTTPRequestStates.Aborted;
                        closed            = true;
                    }
                    catch (Exception exception)
                    {
                        if (HTTPUpdateDelegator.IsCreated)
                        {
                            baseRequest.Exception = exception;
                            baseRequest.State     = HTTPRequestStates.Error;
                        }
                        else
                        {
                            baseRequest.State = HTTPRequestStates.Aborted;
                        }
                        closed = true;
                    }
                }
            }
            finally
            {
                HTTPManager.Heartbeats.Unsubscribe(this);
            }
        }
Пример #10
0
        private void ReceiveThreadFunc()
        {
            while (!this.closed)
            {
                try
                {
                    WebSocketFrameReader webSocketFrameReader = new WebSocketFrameReader();
                    webSocketFrameReader.Read(this.Stream);
                    if (webSocketFrameReader.HasMask)
                    {
                        this.Close(1002, "Protocol Error: masked frame received from server!");
                    }
                    else if (!webSocketFrameReader.IsFinal)
                    {
                        if (this.OnIncompleteFrame == null)
                        {
                            this.IncompleteFrames.Add(webSocketFrameReader);
                        }
                        else
                        {
                            object frameLock = this.FrameLock;
                            lock (frameLock)
                            {
                                this.CompletedFrames.Add(webSocketFrameReader);
                            }
                        }
                    }
                    else
                    {
                        switch (webSocketFrameReader.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            if (this.OnIncompleteFrame != null)
                            {
                                object frameLock2 = this.FrameLock;
                                lock (frameLock2)
                                {
                                    this.CompletedFrames.Add(webSocketFrameReader);
                                }
                                continue;
                            }
                            webSocketFrameReader.Assemble(this.IncompleteFrames);
                            this.IncompleteFrames.Clear();
                            break;

                        case WebSocketFrameTypes.Text:
                        case WebSocketFrameTypes.Binary:
                            break;

                        case (WebSocketFrameTypes)3:
                        case (WebSocketFrameTypes)4:
                        case (WebSocketFrameTypes)5:
                        case (WebSocketFrameTypes)6:
                        case (WebSocketFrameTypes)7:
                            continue;

                        case WebSocketFrameTypes.ConnectionClose:
                            this.CloseFrame = webSocketFrameReader;
                            if (!this.closeSent)
                            {
                                this.Send(new WebSocketClose());
                            }
                            this.closed = this.closeSent;
                            continue;

                        case WebSocketFrameTypes.Ping:
                            if (!this.closeSent && !this.closed)
                            {
                                this.Send(new WebSocketPong(webSocketFrameReader));
                            }
                            continue;

                        default:
                            continue;
                        }
                        if (this.OnText != null)
                        {
                            object frameLock3 = this.FrameLock;
                            lock (frameLock3)
                            {
                                this.CompletedFrames.Add(webSocketFrameReader);
                            }
                        }
                    }
                }
                catch (ThreadAbortException)
                {
                    this.IncompleteFrames.Clear();
                    this.closed = true;
                }
                catch (Exception exception)
                {
                    this.baseRequest.Exception = exception;
                    this.closed = true;
                }
            }
            HTTPManager.Heartbeats.Unsubscribe(this);
        }
Пример #11
0
        private void ReceiveThreadFunc()
        {
            while (!closed)
            {
                try
                {
                    WebSocketFrameReader frame = new WebSocketFrameReader();
                    frame.Read(Stream);

                    // A server MUST NOT mask any frames that it sends to the client.  A client MUST close a connection if it detects a masked frame.
                    // In this case, it MAY use the status code 1002 (protocol error)
                    // (These rules might be relaxed in a future specification.)
                    if (frame.HasMask)
                    {
                        Close(1002, "Protocol Error: masked frame received from server!");
                        continue;
                    }

                    if (!frame.IsFinal)
                    {
                        if (OnIncompleteFrame == null)
                        {
                            IncompleteFrames.Add(frame);
                        }
                        else
                        {
                            lock (FrameLock) CompletedFrames.Add(frame);
                        }
                        continue;
                    }

                    switch (frame.Type)
                    {
                    // For a complete documentation and rules on fragmentation see http://tools.ietf.org/html/rfc6455#section-5.4
                    // A fragmented Frame's last fragment's opcode is 0 (Continuation) and the FIN bit is set to 1.
                    case WebSocketFrameTypes.Continuation:
                        // Do an assemble pass only if OnFragment is not set. Otherwise put it in the CompletedFrames, we will handle it in the HandleEvent phase.
                        if (OnIncompleteFrame == null)
                        {
                            frame.Assemble(IncompleteFrames);

                            // Remove all imcomplete frames
                            IncompleteFrames.Clear();

                            // Control frames themselves MUST NOT be fragmented. So, its a normal text or binary frame. Go, handle it as usual.
                            goto case WebSocketFrameTypes.Binary;
                        }
                        else
                        {
                            lock (FrameLock) CompletedFrames.Add(frame);
                        }
                        break;

                    case WebSocketFrameTypes.Text:
                    case WebSocketFrameTypes.Binary:
                        if (OnText != null)
                        {
                            lock (FrameLock) CompletedFrames.Add(frame);
                        }
                        break;

                    // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame.
                    case WebSocketFrameTypes.Ping:
                        if (!closeSent && !closed)
                        {
                            Send(new WebSocketPong(frame));
                        }
                        break;

                    // If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response.
                    case WebSocketFrameTypes.ConnectionClose:
                        CloseFrame = frame;
                        if (!closeSent)
                        {
                            Send(new WebSocketClose());
                        }
                        closed = closeSent;
                        break;
                    }
                }
                catch (ThreadAbortException)
                {
                    IncompleteFrames.Clear();

                    closed = true;
                }
                catch (Exception e)
                {
                    this.baseRequest.Exception = e;
                    closed = true;
                }
            }

            Interlocked.Increment(ref ClosedCount);

            if (PingThread != null)
            {
                // closed is true and the Ping thread should be exit, but if something went very bad we must Abort() the thread
                if (PingThread.Join(1000))
                {
                    PingThread.Abort();
                }
            }
        }
        internal void HandleEvents()
        {
            lock (FrameLock)
            {
                for (int i = 0; i < CompletedFrames.Count; i++)
                {
                    WebSocketFrameReader webSocketFrameReader = CompletedFrames[i];
                    try
                    {
                        switch (webSocketFrameReader.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            if (OnIncompleteFrame != null)
                            {
                                OnIncompleteFrame(this, webSocketFrameReader);
                            }
                            break;

                        case WebSocketFrameTypes.Text:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (OnText != null)
                                {
                                    OnText(this, Encoding.UTF8.GetString(webSocketFrameReader.Data, 0, webSocketFrameReader.Data.Length));
                                }
                                break;
                            }
                            goto case WebSocketFrameTypes.Continuation;

                        case WebSocketFrameTypes.Binary:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (OnBinary != null)
                                {
                                    OnBinary(this, webSocketFrameReader.Data);
                                }
                                break;
                            }
                            goto case WebSocketFrameTypes.Continuation;

                        case WebSocketFrameTypes.Pong:
                            if (OnPong != null)
                            {
                                OnPong(this, webSocketFrameReader.Data);
                            }
                            break;
                        }
                    }
                    catch
                    {
                    }
                }
                CompletedFrames.Clear();
            }
            if (IsClosed && OnClosed != null)
            {
                try
                {
                    ushort arg  = 0;
                    string arg2 = string.Empty;
                    if (CloseFrame != null && CloseFrame.Data != null && CloseFrame.Data.Length >= 2)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(CloseFrame.Data, 0, 2);
                        }
                        arg = BitConverter.ToUInt16(CloseFrame.Data, 0);
                        if (CloseFrame.Data.Length > 2)
                        {
                            arg2 = Encoding.UTF8.GetString(CloseFrame.Data, 2, CloseFrame.Data.Length - 2);
                        }
                    }
                    OnClosed(this, arg, arg2);
                }
                catch
                {
                }
            }
        }
        private void ReceiveThreadFunc()
        {
            while (!closed)
            {
                try
                {
                    WebSocketFrameReader webSocketFrameReader = new WebSocketFrameReader();
                    webSocketFrameReader.Read(Stream);
                    if (webSocketFrameReader.HasMask)
                    {
                        Close(1002, "Protocol Error: masked frame received from server!");
                    }
                    else if (webSocketFrameReader.IsFinal)
                    {
                        switch (webSocketFrameReader.Type)
                        {
                        case (WebSocketFrameTypes)3:
                        case (WebSocketFrameTypes)4:
                        case (WebSocketFrameTypes)5:
                        case (WebSocketFrameTypes)6:
                        case (WebSocketFrameTypes)7:
                            break;

                        case WebSocketFrameTypes.Continuation:
                            if (OnIncompleteFrame != null)
                            {
                                lock (FrameLock)
                                {
                                    CompletedFrames.Add(webSocketFrameReader);
                                }
                                break;
                            }
                            webSocketFrameReader.Assemble(IncompleteFrames);
                            IncompleteFrames.Clear();
                            goto case WebSocketFrameTypes.Text;

                        case WebSocketFrameTypes.Text:
                        case WebSocketFrameTypes.Binary:
                            if (OnText != null)
                            {
                                lock (FrameLock)
                                {
                                    CompletedFrames.Add(webSocketFrameReader);
                                }
                            }
                            break;

                        case WebSocketFrameTypes.Ping:
                            if (!closeSent && !closed)
                            {
                                Send(new WebSocketPong(webSocketFrameReader));
                            }
                            break;

                        case WebSocketFrameTypes.Pong:
                            if (OnPong != null)
                            {
                                lock (FrameLock)
                                {
                                    CompletedFrames.Add(webSocketFrameReader);
                                }
                            }
                            break;

                        case WebSocketFrameTypes.ConnectionClose:
                            CloseFrame = webSocketFrameReader;
                            if (!closeSent)
                            {
                                Send(new WebSocketClose());
                            }
                            closed = closeSent;
                            break;
                        }
                    }
                    else if (OnIncompleteFrame == null)
                    {
                        IncompleteFrames.Add(webSocketFrameReader);
                    }
                    else
                    {
                        lock (FrameLock)
                        {
                            CompletedFrames.Add(webSocketFrameReader);
                        }
                    }
                }
                catch (ThreadAbortException)
                {
                    IncompleteFrames.Clear();
                    closed = true;
                }
                catch (Exception exception)
                {
                    baseRequest.Exception = exception;
                    closed = true;
                }
            }
            Interlocked.Increment(ref ClosedCount);
            if (PingThread != null && PingThread.Join(1000))
            {
                PingThread.Abort();
            }
        }
Пример #14
0
        void IProtocol.HandleEvents()
        {
            lock (FrameLock)
            {
                for (int i = 0; i < CompletedFrames.Count; i++)
                {
                    WebSocketFrameReader webSocketFrameReader = CompletedFrames[i];
                    try
                    {
                        switch (webSocketFrameReader.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            if (OnIncompleteFrame != null)
                            {
                                OnIncompleteFrame(this, webSocketFrameReader);
                            }
                            break;

                        case WebSocketFrameTypes.Text:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (OnText != null)
                                {
                                    OnText(this, Encoding.UTF8.GetString(webSocketFrameReader.Data, 0, webSocketFrameReader.Data.Length));
                                }
                                break;
                            }
                            goto case WebSocketFrameTypes.Continuation;

                        case WebSocketFrameTypes.Binary:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (OnBinary != null)
                                {
                                    OnBinary(this, webSocketFrameReader.Data);
                                }
                                break;
                            }
                            goto case WebSocketFrameTypes.Continuation;
                        }
                    }
                    catch (Exception ex)
                    {
                        HTTPManager.Logger.Exception("WebSocketResponse", "HandleEvents", ex);
                    }
                }
                CompletedFrames.Clear();
            }
            if (IsClosed && OnClosed != null && baseRequest.State == HTTPRequestStates.Processing)
            {
                try
                {
                    ushort arg  = 0;
                    string arg2 = string.Empty;
                    if (CloseFrame != null && CloseFrame.Data != null && CloseFrame.Data.Length >= 2)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(CloseFrame.Data, 0, 2);
                        }
                        arg = BitConverter.ToUInt16(CloseFrame.Data, 0);
                        if (CloseFrame.Data.Length > 2)
                        {
                            arg2 = Encoding.UTF8.GetString(CloseFrame.Data, 2, CloseFrame.Data.Length - 2);
                        }
                    }
                    OnClosed(this, arg, arg2);
                }
                catch (Exception ex2)
                {
                    HTTPManager.Logger.Exception("WebSocketResponse", "HandleEvents - OnClosed", ex2);
                }
            }
        }
Пример #15
0
        private void ReceiveThreadFunc(object param)
        {
            try
            {
                while (!closed)
                {
                    try
                    {
                        WebSocketFrameReader frame = new WebSocketFrameReader();
                        frame.Read(Stream);

                        // A server MUST NOT mask any frames that it sends to the client.  A client MUST close a connection if it detects a masked frame.
                        // In this case, it MAY use the status code 1002 (protocol error)
                        // (These rules might be relaxed in a future specification.)
                        if (frame.HasMask)
                        {
                            Close(1002, "Protocol Error: masked frame received from server!");
                            continue;
                        }

                        if (!frame.IsFinal)
                        {
                            if (OnIncompleteFrame == null)
                            {
                                IncompleteFrames.Add(frame);
                            }
                            else
                            {
                                lock (FrameLock) CompletedFrames.Add(frame);
                            }
                            continue;
                        }

                        switch (frame.Type)
                        {
                        // For a complete documentation and rules on fragmentation see http://tools.ietf.org/html/rfc6455#section-5.4
                        // A fragmented Frame's last fragment's opcode is 0 (Continuation) and the FIN bit is set to 1.
                        case WebSocketFrameTypes.Continuation:
                            // Do an assemble pass only if OnFragment is not set. Otherwise put it in the CompletedFrames, we will handle it in the HandleEvent phase.
                            if (OnIncompleteFrame == null)
                            {
                                frame.Assemble(IncompleteFrames);

                                // Remove all incomplete frames
                                IncompleteFrames.Clear();

                                // Control frames themselves MUST NOT be fragmented. So, its a normal text or binary frame. Go, handle it as usual.
                                goto case WebSocketFrameTypes.Binary;
                            }
                            else
                            {
                                lock (FrameLock) CompletedFrames.Add(frame);
                            }
                            break;

                        case WebSocketFrameTypes.Text:
                        case WebSocketFrameTypes.Binary:
                            frame.DecodeWithExtensions(WebSocket);
                            lock (FrameLock) CompletedFrames.Add(frame);
                            break;

                        // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame.
                        case WebSocketFrameTypes.Ping:
                            if (!closeSent && !closed)
                            {
                                Send(new WebSocketFrame(this.WebSocket, WebSocketFrameTypes.Pong, frame.Data));
                            }
                            break;

                        // If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response.
                        case WebSocketFrameTypes.ConnectionClose:
                            CloseFrame = frame;
                            if (!closeSent)
                            {
                                Send(new WebSocketFrame(this.WebSocket, WebSocketFrameTypes.ConnectionClose, null));
                            }
                            closed = closeSent;
                            break;
                        }
                    }
#if !NETFX_CORE
                    catch (ThreadAbortException)
                    {
                        IncompleteFrames.Clear();
                        this.baseRequest.State = HTTPRequestStates.Aborted;

                        closed = true;
                    }
#endif
                    catch (Exception e)
                    {
                        if (HTTPUpdateDelegator.IsCreated)
                        {
                            this.baseRequest.Exception = e;
                            this.baseRequest.State     = HTTPRequestStates.Error;
                        }
                        else
                        {
                            this.baseRequest.State = HTTPRequestStates.Aborted;
                        }

                        closed = true;
                    }
                }
            }
            finally
            {
                HTTPManager.Heartbeats.Unsubscribe(this);
            }
        }
Пример #16
0
        /// <summary>
        /// Internal function to send out received messages.
        /// </summary>
        void IProtocol.HandleEvents()
        {
            lock (FrameLock)
            {
                for (int i = 0; i < CompletedFrames.Count; ++i)
                {
                    WebSocketFrameReader frame = CompletedFrames[i];

                    // Bugs in the clients shouldn't interrupt the code, so we need to try-catch and ignore any exception occurring here
                    try
                    {
                        switch (frame.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            if (OnIncompleteFrame != null)
                            {
                                OnIncompleteFrame(this, frame);
                            }
                            break;

                        case WebSocketFrameTypes.Text:
                            // Any not Final frame is handled as a fragment
                            if (!frame.IsFinal)
                            {
                                goto case WebSocketFrameTypes.Continuation;
                            }

                            if (OnText != null)
                            {
                                OnText(this, frame.DataAsText);
                            }
                            break;

                        case WebSocketFrameTypes.Binary:
                            // Any not Final frame is handled as a fragment
                            if (!frame.IsFinal)
                            {
                                goto case WebSocketFrameTypes.Continuation;
                            }

                            if (OnBinary != null)
                            {
                                OnBinary(this, frame.Data);
                            }
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        HTTPManager.Logger.Exception("WebSocketResponse", "HandleEvents", ex);
                    }
                }

                CompletedFrames.Clear();
            }//lock (ReadLock)

            // 2015.05.09
            // State checking added because if there is an error the OnClose called first, and then the OnError.
            // Now, when there is an error only the OnError event will be called!
            if (IsClosed && OnClosed != null && baseRequest.State == HTTPRequestStates.Processing)
            {
                try
                {
                    UInt16 statusCode = 0;
                    string msg        = string.Empty;

                    // If we received any data, we will get the status code and the message from it
                    if (CloseFrame != null && CloseFrame.Data != null && CloseFrame.Data.Length >= 2)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(CloseFrame.Data, 0, 2);
                        }
                        statusCode = BitConverter.ToUInt16(CloseFrame.Data, 0);

                        if (CloseFrame.Data.Length > 2)
                        {
                            msg = Encoding.UTF8.GetString(CloseFrame.Data, 2, CloseFrame.Data.Length - 2);
                        }
                    }

                    OnClosed(this, statusCode, msg);
                }
                catch (Exception ex)
                {
                    HTTPManager.Logger.Exception("WebSocketResponse", "HandleEvents - OnClosed", ex);
                }
            }
        }
Пример #17
0
        internal void HandleEvents()
        {
            object frameLock = this.FrameLock;

            lock (frameLock)
            {
                for (int i = 0; i < this.CompletedFrames.Count; i++)
                {
                    WebSocketFrameReader webSocketFrameReader = this.CompletedFrames[i];
                    try
                    {
                        switch (webSocketFrameReader.Type)
                        {
                        case WebSocketFrameTypes.Continuation:
                            break;

                        case WebSocketFrameTypes.Text:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (this.OnText != null)
                                {
                                    this.OnText(this, Encoding.UTF8.GetString(webSocketFrameReader.Data, 0, webSocketFrameReader.Data.Length));
                                }
                                goto IL_D5;
                            }
                            break;

                        case WebSocketFrameTypes.Binary:
                            if (webSocketFrameReader.IsFinal)
                            {
                                if (this.OnBinary != null)
                                {
                                    this.OnBinary(this, webSocketFrameReader.Data);
                                }
                                goto IL_D5;
                            }
                            break;

                        default:
                            goto IL_D5;
                        }
                        if (this.OnIncompleteFrame != null)
                        {
                            this.OnIncompleteFrame(this, webSocketFrameReader);
                        }
                        IL_D5 :;
                    }
                    catch
                    {
                    }
                }
                this.CompletedFrames.Clear();
            }
            if (this.IsClosed && this.OnClosed != null)
            {
                try
                {
                    ushort arg  = 0;
                    string arg2 = string.Empty;
                    if (this.CloseFrame != null && this.CloseFrame.Data != null && this.CloseFrame.Data.Length >= 2)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(this.CloseFrame.Data, 0, 2);
                        }
                        arg = BitConverter.ToUInt16(this.CloseFrame.Data, 0);
                        if (this.CloseFrame.Data.Length > 2)
                        {
                            arg2 = Encoding.UTF8.GetString(this.CloseFrame.Data, 2, this.CloseFrame.Data.Length - 2);
                        }
                    }
                    this.OnClosed(this, arg, arg2);
                }
                catch
                {
                }
            }
        }