/// <summary> /// Closes the websocket connection. Sends a close message to the other side if it hasn't already done so. /// </summary> /// <param name="message"></param> public void Close(string message) { if (_initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } if (_networkContext == null) { return; } if (_networkContext.Stream != null) { if (_networkContext.Stream.CanWrite) { byte[] messagedata = Encoding.UTF8.GetBytes(message); WebSocketFrame closeResponseFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; closeResponseFrame.Header.Opcode = WebSocketReader.OpCode.Close; closeResponseFrame.Header.PayloadLen = (ulong)messagedata.Length; closeResponseFrame.Header.IsEnd = true; SendSocket(closeResponseFrame.ToBytes()); } } CloseDelegate closeD = OnClose; if (closeD != null) { closeD(this, new CloseEventArgs()); } _closing = true; }
/// <summary> /// Processes a websocket frame and triggers consumer events /// </summary> /// <param name="psocketState">We need to modify the websocket state here depending on the frame</param> private void ProcessFrame(WebSocketState psocketState) { if (psocketState.Header.IsMasked) { byte[] unmask = psocketState.ReceivedBytes.ToArray(); WebSocketReader.Mask(psocketState.Header.Mask, unmask); psocketState.ReceivedBytes = new List<byte>(unmask); } if (psocketState.Header.Opcode != WebSocketReader.OpCode.Continue && _initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } switch (psocketState.Header.Opcode) { case WebSocketReader.OpCode.Ping: PingDelegate pingD = OnPing; if (pingD != null) { pingD(this, new PingEventArgs()); } WebSocketFrame pongFrame = new WebSocketFrame(){Header = WebsocketFrameHeader.HeaderDefault(),WebSocketPayload = new byte[0]}; pongFrame.Header.Opcode = WebSocketReader.OpCode.Pong; pongFrame.Header.IsEnd = true; SendSocket(pongFrame.ToBytes()); break; case WebSocketReader.OpCode.Pong: PongDelegate pongD = OnPong; if (pongD != null) { pongD(this, new PongEventArgs(){PingResponseMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),_pingtime)}); } break; case WebSocketReader.OpCode.Binary: if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame. { psocketState.ContinuationFrame = new WebSocketFrame { Header = psocketState.Header, WebSocketPayload = psocketState.ReceivedBytes.ToArray() }; } else { // Send Done Event! DataDelegate dataD = OnData; if (dataD != null) { dataD(this,new WebsocketDataEventArgs(){Data = psocketState.ReceivedBytes.ToArray()}); } } break; case WebSocketReader.OpCode.Text: if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame. { psocketState.ContinuationFrame = new WebSocketFrame { Header = psocketState.Header, WebSocketPayload = psocketState.ReceivedBytes.ToArray() }; } else { TextDelegate textD = OnText; if (textD != null) { textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(psocketState.ReceivedBytes.ToArray()) }); } // Send Done Event! } break; case WebSocketReader.OpCode.Continue: // Continuation. Multiple frames worth of data for one message. Only valid when not using Control Opcodes //Console.WriteLine("currhead " + psocketState.Header.IsEnd); //Console.WriteLine("Continuation! " + psocketState.ContinuationFrame.Header.IsEnd); byte[] combineddata = new byte[psocketState.ReceivedBytes.Count+psocketState.ContinuationFrame.WebSocketPayload.Length]; byte[] newdata = psocketState.ReceivedBytes.ToArray(); Buffer.BlockCopy(psocketState.ContinuationFrame.WebSocketPayload, 0, combineddata, 0, psocketState.ContinuationFrame.WebSocketPayload.Length); Buffer.BlockCopy(newdata, 0, combineddata, psocketState.ContinuationFrame.WebSocketPayload.Length, newdata.Length); psocketState.ContinuationFrame.WebSocketPayload = combineddata; psocketState.Header.PayloadLen = (ulong)combineddata.Length; if (psocketState.Header.IsEnd) { if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Text) { // Send Done event TextDelegate textD = OnText; if (textD != null) { textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(combineddata) }); } } else if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Binary) { // Send Done event DataDelegate dataD = OnData; if (dataD != null) { dataD(this, new WebsocketDataEventArgs() { Data = combineddata }); } } else { // protocol violation } psocketState.ContinuationFrame = null; } break; case WebSocketReader.OpCode.Close: Close(string.Empty); break; } psocketState.Header.SetDefault(); psocketState.ReceivedBytes.Clear(); psocketState.ExpectedBytes = 0; }
/// <summary> /// Closes the websocket connection. Sends a close message to the other side if it hasn't already done so. /// </summary> /// <param name="message"></param> public void Close(string message) { if (_initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } if (_networkContext == null) return; if (_networkContext.Stream != null) { if (_networkContext.Stream.CanWrite) { byte[] messagedata = Encoding.UTF8.GetBytes(message); WebSocketFrame closeResponseFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; closeResponseFrame.Header.Opcode = WebSocketReader.OpCode.Close; closeResponseFrame.Header.PayloadLen = (ulong) messagedata.Length; closeResponseFrame.Header.IsEnd = true; SendSocket(closeResponseFrame.ToBytes()); } } CloseDelegate closeD = OnClose; if (closeD != null) { closeD(this, new CloseEventArgs()); } _closing = true; }
/// <summary> /// Sends a Ping check to the other side. The other side SHOULD respond as soon as possible with a pong frame. This interleaves with incoming fragmented frames. /// </summary> public void SendPingCheck() { if (_initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; pingFrame.Header.IsEnd = true; _pingtime = Util.EnvironmentTickCount(); SendSocket(pingFrame.ToBytes()); }
public void SendData(byte[] data) { if (_initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; dataMessageFrame.Header.IsEnd = true; dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; SendSocket(dataMessageFrame.ToBytes()); }
/// <summary> /// Sends a string to the other side /// </summary> /// <param name="message">the string message that is to be sent</param> public void SendMessage(string message) { if (_initialMsgTimeout > 0) { _receiveDone.Set(); _initialMsgTimeout = 0; } byte[] messagedata = Encoding.UTF8.GetBytes(message); WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; textMessageFrame.Header.IsEnd = true; SendSocket(textMessageFrame.ToBytes()); }
/// <summary> /// Processes a websocket frame and triggers consumer events /// </summary> /// <param name="psocketState">We need to modify the websocket state here depending on the frame</param> private void ProcessFrame(WebSocketState psocketState) { if (psocketState.Header.IsMasked) { byte[] unmask = psocketState.ReceivedBytes.ToArray(); WebSocketReader.Mask(psocketState.Header.Mask, unmask); psocketState.ReceivedBytes = new List <byte>(unmask); } switch (psocketState.Header.Opcode) { case WebSocketReader.OpCode.Ping: PingDelegate pingD = OnPing; if (pingD != null) { pingD(this, new PingEventArgs()); } WebSocketFrame pongFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; pongFrame.Header.Opcode = WebSocketReader.OpCode.Pong; pongFrame.Header.IsEnd = true; SendSocket(pongFrame.ToBytes()); break; case WebSocketReader.OpCode.Pong: PongDelegate pongD = OnPong; if (pongD != null) { pongD(this, new PongEventArgs() { PingResponseMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _pingtime) }); } break; case WebSocketReader.OpCode.Binary: if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame. { psocketState.ContinuationFrame = new WebSocketFrame { Header = psocketState.Header, WebSocketPayload = psocketState.ReceivedBytes.ToArray() }; } else { // Send Done Event! DataDelegate dataD = OnData; if (dataD != null) { dataD(this, new WebsocketDataEventArgs() { Data = psocketState.ReceivedBytes.ToArray() }); } } break; case WebSocketReader.OpCode.Text: if (!psocketState.Header.IsEnd) // Not done, so we need to store this and wait for the end frame. { psocketState.ContinuationFrame = new WebSocketFrame { Header = psocketState.Header, WebSocketPayload = psocketState.ReceivedBytes.ToArray() }; } else { TextDelegate textD = OnText; if (textD != null) { textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(psocketState.ReceivedBytes.ToArray()) }); } // Send Done Event! } break; case WebSocketReader.OpCode.Continue: // Continuation. Multiple frames worth of data for one message. Only valid when not using Control Opcodes //Console.WriteLine("currhead " + psocketState.Header.IsEnd); //Console.WriteLine("Continuation! " + psocketState.ContinuationFrame.Header.IsEnd); byte[] combineddata = new byte[psocketState.ReceivedBytes.Count + psocketState.ContinuationFrame.WebSocketPayload.Length]; byte[] newdata = psocketState.ReceivedBytes.ToArray(); Buffer.BlockCopy(psocketState.ContinuationFrame.WebSocketPayload, 0, combineddata, 0, psocketState.ContinuationFrame.WebSocketPayload.Length); Buffer.BlockCopy(newdata, 0, combineddata, psocketState.ContinuationFrame.WebSocketPayload.Length, newdata.Length); psocketState.ContinuationFrame.WebSocketPayload = combineddata; psocketState.Header.PayloadLen = (ulong)combineddata.Length; if (psocketState.Header.IsEnd) { if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Text) { // Send Done event TextDelegate textD = OnText; if (textD != null) { textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(combineddata) }); } } else if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Binary) { // Send Done event DataDelegate dataD = OnData; if (dataD != null) { dataD(this, new WebsocketDataEventArgs() { Data = combineddata }); } } else { // protocol violation } psocketState.ContinuationFrame = null; } break; case WebSocketReader.OpCode.Close: Close(string.Empty); break; } psocketState.Header.SetDefault(); psocketState.ReceivedBytes.Clear(); psocketState.ExpectedBytes = 0; }
/// <summary> /// Sends a Ping check to the other side. The other side SHOULD respond as soon as possible with a pong frame. This interleaves with incoming fragmented frames. /// </summary> public void SendPingCheck() { WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; pingFrame.Header.IsEnd = true; _pingtime = Util.EnvironmentTickCount(); SendSocket(pingFrame.ToBytes()); }
public void SendData(byte[] data) { WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; dataMessageFrame.Header.IsEnd = true; dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; SendSocket(dataMessageFrame.ToBytes()); }
/// <summary> /// Sends a string to the other side /// </summary> /// <param name="message">the string message that is to be sent</param> public void SendMessage(string message) { byte[] messagedata = Encoding.UTF8.GetBytes(message); WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; textMessageFrame.Header.IsEnd = true; SendSocket(textMessageFrame.ToBytes()); }