protected void smWaitCloseResponse() { int bytesRead = 0; this.posHeaderEOF = 0; this.bytesInBuffer = 0; if (this.socket.Poll(this.waitCloseMsgTimeout, SelectMode.SelectRead) == true && this.socket.Available > 0) { do { bytesRead = this.socketStream.Read(this.receiveBuffer, this.bytesInBuffer, this.receiveBuffer.Length - this.bytesInBuffer); if (bytesRead > 0) { this.bytesInBuffer += bytesRead; if (WSFrame.TryParse(this.receiveBuffer, 0, this.bytesInBuffer, this.options.MaxReceiveFrameLength, out this.lastRcvdFrame) == true) { // remove data-frame from buffer Array.Copy(this.receiveBuffer, this.lastRcvdFrame.FrameData.Length, this.receiveBuffer, 0, this.bytesInBuffer - this.lastRcvdFrame.FrameData.Length); this.bytesInBuffer = this.bytesInBuffer - this.lastRcvdFrame.FrameData.Length; // check for close frame if (this.lastRcvdFrame.OpCode == WSFrameType.Close) { this.LogBufferContent("Close frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); this.subState = SubState.CloseTcpConnection; return; } this.LogBufferContent("Data frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); } } }while (this.socket.Available > 0 && this.bytesInBuffer < this.receiveBuffer.Length); } Logger.WriteError(this.loggerID, "Close frame not received."); this.subState = SubState.Failed; }
protected void smReceive() { int bytesRead = 0; this.lastRcvdFrame = null; // start activity timer if (this.activityTimerEnabled) { this.activityTimer.Start(this.waitActivityTimeout, ActivityTimerState.WaitingForMessage); } while (this.State == WebSocketState.Connected) { // process data in buffer if (this.bytesInBuffer > 0) { if (WSFrame.TryParse(this.receiveBuffer, 0, this.bytesInBuffer, this.options.MaxReceiveFrameLength, out this.lastRcvdFrame) == true) { // restart activity timer if (this.activityTimerEnabled) { this.activityTimer.Restart(ActivityTimerState.WaitingForMessage); } // remove data-frame from buffer Array.Copy(this.receiveBuffer, this.lastRcvdFrame.FrameData.Length, this.receiveBuffer, 0, this.bytesInBuffer - this.lastRcvdFrame.FrameData.Length); this.bytesInBuffer = this.bytesInBuffer - this.lastRcvdFrame.FrameData.Length; // take action based on opcode switch (this.lastRcvdFrame.OpCode) { case WSFrameType.Continuation: // TODO - implement continuation frames break; case WSFrameType.Text: this.LogBufferContent("Text frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); this.OnTextReceived(this.lastRcvdFrame.PayloadText); break; case WSFrameType.Binary: this.LogBufferContent("Data frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); this.OnDataReceived(this.lastRcvdFrame.PayloadBytes); break; case WSFrameType.Close: this.LogBufferContent("Close frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); // based on RFC6455 we must stop sending and receiving messages after Close response is sent this.activityTimer.Stop(); this.state = WebSocketState.Disconnecting; this.subState = SubState.CloseTcpConnection; this.smSendCloseResponse(); return; case WSFrameType.Ping: this.LogBufferContent("Ping frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); this.smSendPongMessage(); break; case WSFrameType.Pong: this.LogBufferContent("Pong frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); // no need to do anything break; default: this.LogBufferContent("Unknown frame received: ", this.lastRcvdFrame.FrameData, 0, this.lastRcvdFrame.FrameData.Length); break; } } } // send queued messages if (this.DequeueAndSendMessages() && this.activityTimerEnabled) { this.activityTimer.Restart(ActivityTimerState.MessageSent); } // get more data if (this.socket.Poll(this.waitReceiveTimeout, SelectMode.SelectRead) == true && this.socket.Available > 0) { bytesRead = this.socketStream.Read(this.receiveBuffer, this.bytesInBuffer, this.receiveBuffer.Length - this.bytesInBuffer); this.bytesInBuffer += bytesRead; continue; } // check activity timer if (this.activityTimer.HasTimedOut) { switch ((ActivityTimerState)this.activityTimer.State) { case ActivityTimerState.MessageSent: case ActivityTimerState.WaitingForMessage: this.smSendPingMessage(); activityTimer.Restart(ActivityTimerState.WaitingForPingResponse); break; case ActivityTimerState.WaitingForPingResponse: Logger.WriteError(this.loggerID, string.Concat("Ping response timed out.")); activityTimer.Stop(); this.state = WebSocketState.Disconnecting; this.subState = SubState.CloseTcpConnection; break; } } } }