Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
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!");
            }
        }