/// <summary> /// A Pong frame sent in response to a Ping frame must have identical "Application data" as found in the message body of the Ping frame being replied to. /// </summary> public WebSocketPong(WebSocketFrameReader ping) : base(ping.Data) { }
private void ReceiveThreadFunc() { try { while (!closed) { try { // TODO: reuse WebSocketFrameReader instances 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: 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(); this.baseRequest.State = HTTPRequestStates.Aborted; closed = true; } catch (Exception e) { this.baseRequest.Exception = e; this.baseRequest.State = HTTPRequestStates.Error; closed = true; } } } finally { HTTPManager.Heartbeats.Unsubscribe(this); } }