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); }
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."); } }
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); }
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); }
public WebSocketPong(WebSocketFrameReader ping) : base(ping.Data) { }
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!"); } }
/// <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 { } } }
public void SequenceLessThanMinimumPlusMaskReturnsFalse() { var reader = new WebSocketFrameReader(); var headerBytes = GetHeaderBytes(WebSocketHeader.CreateMasked(true, default, 64));
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); } }
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(); } } }
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(); } }
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); } } }
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); } }
/// <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); } } }
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 { } } }