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); } }
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!"); } }
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); }
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(); } } }
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(); } }
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); } }