/// <summary> /// Initializes a new instance of the <see cref="WebSocketFrame"/> class. /// </summary> /// <param name="isEntirePayload">if set to <c>true</c> [is entire payload].</param> /// <param name="isValid">if set to <c>true</c> [is valid].</param> /// <param name="opCode">The op code.</param> /// <param name="decodedPayload">The decoded payload.</param> public WebSocketFrame(bool isEntirePayload, bool isValid, WebSocketOpCode opCode, byte[] decodedPayload) { IsEntirePayload = isEntirePayload; IsValid = isValid; OpCode = opCode; DecodedPayload = decodedPayload; }
public void Write(WebSocketOpCode opCode, byte[] payload, bool isLastFrame) { // best to write everything to a memory stream before we push it onto the wire // not really necessary but I like it this way using (MemoryStream memoryStream = new MemoryStream()) { byte finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; byte byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); // NB, dont set the mask flag. No need to mask data from server to client // depending on the size of the length we want to write it as a byte, ushort or ulong if (payload.Length < 126) { byte byte2 = (byte)payload.Length; memoryStream.WriteByte(byte2); } else if (payload.Length <= ushort.MaxValue) { byte byte2 = 126; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)payload.Length, memoryStream, false); } else { byte byte2 = 127; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)payload.Length, memoryStream, false); } memoryStream.Write(payload, 0, payload.Length); byte[] buffer = memoryStream.ToArray(); _stream.Write(buffer, 0, buffer.Length); } }
public WebSocketFrame(bool isFinBitSet, WebSocketOpCode webSocketOpCode, int count, ArraySegment <byte> maskKey) { IsFinBitSet = isFinBitSet; OpCode = webSocketOpCode; Count = count; MaskKey = maskKey; }
/// <summary> /// Send data to the web socket /// </summary> /// <param name="buffer">the buffer containing data to send</param> /// <param name="messageType">The message type. Can be Text or Binary</param> /// <param name="endOfMessage">True if this message is a standalone message (this is the norm) /// If it is a multi-part message then false (and true for the last message)</param> /// <param name="cancellationToken">the cancellation token</param> public override async Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) { using (MemoryStream stream = _recycledStreamFactory()) { WebSocketOpCode opCode = GetOppCode(messageType); if (_usePerMessageDeflate) { using (MemoryStream temp = new MemoryStream()) { DeflateStream deflateStream = new DeflateStream(temp, CompressionMode.Compress); deflateStream.Write(buffer.Array, buffer.Offset, buffer.Count); deflateStream.Flush(); var compressedBuffer = new ArraySegment <byte>(temp.ToArray()); WebSocketFrameWriter.Write(opCode, compressedBuffer, stream, endOfMessage, _isClient); Events.Log.SendingFrame(_guid, opCode, endOfMessage, compressedBuffer.Count, true); } } else { WebSocketFrameWriter.Write(opCode, buffer, stream, endOfMessage, _isClient); Events.Log.SendingFrame(_guid, opCode, endOfMessage, buffer.Count, false); } await WriteStreamToNetwork(stream, cancellationToken); _isContinuationFrame = !endOfMessage; } }
public void SendingFrame(Guid guid, WebSocketOpCode webSocketOpCode, bool isFinBitSet, int numBytes, bool isPayloadCompressed) { if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None)) { WriteEvent(28, guid, webSocketOpCode, isFinBitSet, numBytes, isPayloadCompressed); } }
public WebSocketFrame(bool isFinBitSet, WebSocketOpCode webSocketOpCode, byte[] decodedPayload, bool isValid) { IsFinBitSet = isFinBitSet; OpCode = webSocketOpCode; DecodedPayload = decodedPayload; IsValid = isValid; }
/// <summary> /// Extracts close status and close description information from the web socket frame /// </summary> /// <param name="isFinBitSet"></param> /// <param name="opCode"></param> /// <param name="count"></param> /// <param name="buffer"></param> /// <returns></returns> static WebSocketFrame DecodeCloseFrame(bool isFinBitSet, WebSocketOpCode opCode, int count, ArraySegment <byte> buffer) { WebSocketCloseStatus closeStatus; string closeStatusDescription; if (count >= 2) { Array.Reverse(buffer.Array, buffer.Offset, 2); // network byte order var closeStatusCode = (int)BitConverter.ToUInt16(buffer.Array, buffer.Offset); closeStatus = Enum.IsDefined(typeof(WebSocketCloseStatus), closeStatusCode) ? (WebSocketCloseStatus)closeStatusCode : WebSocketCloseStatus.Empty; int offset = buffer.Offset + 2; int descCount = count - 2; closeStatusDescription = descCount > 0 ? Encoding.UTF8.GetString(buffer.Array, offset, descCount) : null; } else { closeStatus = WebSocketCloseStatus.Empty; closeStatusDescription = null; } return(new WebSocketFrame(isFinBitSet, opCode, count, closeStatus, closeStatusDescription)); }
public WebSocketFrame(bool isFinBitSet, WebSocketOpCode webSocketOpCode, byte[] decodedPayload, bool isValid) { IsFinBitSet = isFinBitSet; OpCode = webSocketOpCode; DecodedPayload = decodedPayload; IsValid = isValid; }
/// <summary> /// Send data to the web socket /// </summary> /// <param name="buffer">the buffer containing data to send</param> /// <param name="messageType">The message type. Can be Text or Binary</param> /// <param name="endOfMessage">True if this message is a standalone message (this is the norm) /// If it is a multi-part message then false (and true for the last message)</param> /// <param name="cancellationToken">the cancellation token</param> public override async Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) { using (MemoryStream stream = _recycledStreamFactory()) { WebSocketOpCode opCode = GetOppCode(messageType); if (_usePerMessageDeflate) { // NOTE: Compression is currently work in progress and should NOT be used in this library. // The code below is very inefficient for small messages. Ideally we would like to have some sort of moving window // of data to get the best compression. And we don't want to create new buffers which is bad for GC. using (MemoryStream temp = new MemoryStream()) { DeflateStream deflateStream = new DeflateStream(temp, CompressionMode.Compress); deflateStream.Write(buffer.Array, buffer.Offset, buffer.Count); deflateStream.Flush(); ArraySegment <byte> compressedBuffer = new ArraySegment <byte>(temp.ToArray()); WebSocketFrameWriter.Write(opCode, compressedBuffer, stream, endOfMessage, _isClient); Events.Log.SendingFrame(_guid, opCode, endOfMessage, compressedBuffer.Count, true); } } else { WebSocketFrameWriter.Write(opCode, buffer, stream, endOfMessage, _isClient); Events.Log.SendingFrame(_guid, opCode, endOfMessage, buffer.Count, false); } await WriteStreamToNetwork(stream, cancellationToken); // TODO: is this correct?? _isContinuationFrame = !endOfMessage; } }
public void ReceivedFrame(Guid guid, WebSocketOpCode webSocketOpCode, bool isFinBitSet, int numBytes) { if (IsEnabled(EventLevel.Verbose, EventKeywords.None)) { WriteEvent(29, guid, webSocketOpCode, isFinBitSet, numBytes); } }
public byte[] GetFrameBytesFromData(WebSocketOpCode opCode, byte[] payload, bool isLastFrame) { using (MemoryStream memoryStream = new MemoryStream()) { byte finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; byte byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); // NB, dont set the mask flag. No need to mask data from server to client // depending on the size of the length we want to write it as a byte, ushort or ulong if (payload.Length < 126) { byte byte2 = (byte)payload.Length; memoryStream.WriteByte(byte2); } else if (payload.Length <= ushort.MaxValue) { byte byte2 = 126; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)payload.Length, memoryStream, false); } else { byte byte2 = 127; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)payload.Length, memoryStream, false); } memoryStream.Write(payload, 0, payload.Length); byte[] buffer = memoryStream.ToArray(); return(buffer); } }
/// Send data to the web socket public void Send(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage) { using (MemoryStream stream = _recycledStreamFactory()) { WebSocketOpCode opCode = GetOppCode(messageType); if (_usePerMessageDeflate) { // NOTE: Compression is currently work in progress and should NOT be used in this library. // The code below is very inefficient for small messages. Ideally we would like to have some sort of moving window // of data to get the best compression. And we don't want to create new buffers which is bad for GC. using (MemoryStream temp = new MemoryStream()) { DeflateStream deflateStream = new DeflateStream(temp, CompressionMode.Compress); deflateStream.Write(buffer.Array, buffer.Offset, buffer.Count); deflateStream.Flush(); var compressedBuffer = new ArraySegment <byte>(temp.ToArray()); WebSocketFrameWriter.Write(opCode, compressedBuffer, stream, endOfMessage, _isClient); _logger(LogLevel.Debug, $"websocket.SendingFrame: {opCode}, {endOfMessage}, {compressedBuffer.Count}, compressed"); } } else { WebSocketFrameWriter.Write(opCode, buffer, stream, endOfMessage, _isClient); _logger(LogLevel.Debug, $"websocket.SendingFrame: {opCode}, {endOfMessage}, {buffer.Count}, uncompressed"); } WriteStreamToNetwork(stream); _isContinuationFrame = !endOfMessage; // TODO: is this correct?? } }
public void Write(WebSocketOpCode opCode, byte[] payload, bool isLastFrame) { using (var memoryStream = new MemoryStream()) { var finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; var byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); if (payload.Length < 126) { var byte2 = (byte)payload.Length; memoryStream.WriteByte(byte2); } else if (payload.Length <= ushort.MaxValue) { byte byte2 = 126; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)payload.Length, memoryStream); } else { byte byte2 = 127; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)payload.Length, memoryStream); } memoryStream.Write(payload, 0, payload.Length); var buffer = memoryStream.ToArray(); _stream.Write(buffer, 0, buffer.Length); } }
public void Write(WebSocketOpCode opCode, byte[] payload, bool isLastFrame) { // best to write everything to a memory stream before we push it onto the wire // not really necessary but I like it this way using (MemoryStream memoryStream = new MemoryStream()) { byte finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; byte byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); // NB, dont set the mask flag. No need to mask data from server to client // depending on the size of the length we want to write it as a byte, ushort or ulong if (payload.Length < 126) { byte byte2 = (byte)payload.Length; memoryStream.WriteByte(byte2); } else if (payload.Length <= ushort.MaxValue) { byte byte2 = 126; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)payload.Length, memoryStream, false); } else { byte byte2 = 127; memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)payload.Length, memoryStream, false); } memoryStream.Write(payload, 0, payload.Length); byte[] buffer = memoryStream.ToArray(); _stream.Write(buffer, 0, buffer.Length); } }
public WebSocketFrame() { Payload = null; OpCode = WebSocketOpCode.Continue; IsFinal = false; IsMasked = false; }
/// <summary> /// Reads the specified stream. /// </summary> /// <param name="connection">The connection.</param> /// <returns></returns> public IWebSocketFrame Read(TcpClient connection) { const byte FIN_BIT_FLAG = 0x80; const byte OP_CODE_FLAG = 0x0F; const byte MASK_FLAG = 0x80; const int KEY_LENGTH = 4; if (!connection.Connected) { return(null); } //Process the first byte of the packet byte firstByte; try { firstByte = (byte)Stream.ReadByte(); } catch (IOException ex) { _logger.Error(ex); return(null); } bool isFinBitSet = (firstByte & FIN_BIT_FLAG) == FIN_BIT_FLAG; //Gets the op code which tells us what kind of payload we're looking at (binary, message, etc) WebSocketOpCode opCode = (WebSocketOpCode)(firstByte & OP_CODE_FLAG); //Process the second byte of the packet byte secondByte = (byte)Stream.ReadByte(); //Get the mask bit and toss an exception if it's false. Per the RFC this should never be false. bool isMaskBitSet = (secondByte & MASK_FLAG) == MASK_FLAG; if (!isMaskBitSet) { return(null); } //Grab the payload length uint payloadLength = ReadPayloadLength(secondByte, Stream); //Grab the crypto key from the stream byte[] maskKey = StreamHelper.ReadExactly(KEY_LENGTH, Stream); //Grab the encrypted payload byte[] encodedPayload = StreamHelper.ReadExactly((int)payloadLength, Stream); //Decrypt the payload byte[] decodedPayload = new byte[payloadLength]; for (int i = 0; i < encodedPayload.Length; i++) { decodedPayload[i] = (Byte)(encodedPayload[i] ^ maskKey[i % KEY_LENGTH]); } return(new WebSocketFrame(isFinBitSet, true, opCode, decodedPayload)); }
protected override void Send(WebSocketOpCode opCode, byte[] toSend, bool isLastFrame) { byte[] buffer = _frameBuilder.GetFrameBytesFromData(opCode, toSend, isLastFrame); if (_socketHandler != null) { _socketHandler.Send(buffer); } }
public WebSocketFrame(bool isFinBitSet, WebSocketOpCode webSocketOpCode, int count) { IsFinBitSet = isFinBitSet; OpCode = webSocketOpCode; Count = count; CloseStatus = WebSocketCloseStatus.None; CloseStatusDescription = null; }
public static bool IsValidCode(WebSocketOpCode opCode) { return(opCode == WebSocketOpCode.ContinuationFrame || opCode == WebSocketOpCode.TextFrame || opCode == WebSocketOpCode.BinaryFrame || opCode == WebSocketOpCode.ConnectionClose || opCode == WebSocketOpCode.Ping || opCode == WebSocketOpCode.Pong); }
public void SendFrame(string Data, WebSocketOpCode OpCode, bool LastFrame) { if (ConnectedSocket.Connected) { WebSocketFrame Frame = new WebSocketFrame(Data, OpCode); byte[] FrameBuffer = Frame.GetRawBuffer(LastFrame); ConnectedSocket.BeginSend(FrameBuffer, 0, FrameBuffer.Length, SocketFlags.None, SendMessageCallback, null); } }
public WebSocketFrame Read(Stream stream, Socket socket) { byte byte1; try { byte1 = (byte)stream.ReadByte(); } catch (IOException) { if (socket.Connected) { throw; } else { return(null); } } // process first byte byte finBitFlag = 0x80; byte opCodeFlag = 0x0F; bool isFinBitSet = (byte1 & finBitFlag) == finBitFlag; WebSocketOpCode opCode = (WebSocketOpCode)(byte1 & opCodeFlag); // read and process second byte byte byte2 = (byte)stream.ReadByte(); byte maskFlag = 0x80; bool isMaskBitSet = (byte2 & maskFlag) == maskFlag; uint len = ReadLength(byte2, stream); byte[] decodedPayload; // use the masking key to decode the data if needed if (isMaskBitSet) { const int maskKeyLen = 4; byte[] maskKey = BinaryReaderWriter.ReadExactly(maskKeyLen, stream); byte[] encodedPayload = BinaryReaderWriter.ReadExactly((int)len, stream); decodedPayload = new byte[len]; // apply the mask key for (int i = 0; i < encodedPayload.Length; i++) { decodedPayload[i] = (Byte)(encodedPayload[i] ^ maskKey[i % maskKeyLen]); } } else { decodedPayload = BinaryReaderWriter.ReadExactly((int)len, stream); } WebSocketFrame frame = new WebSocketFrame(isFinBitSet, opCode, decodedPayload, true); return(frame); }
/// <summary> /// Read a WebSocket frame from the stream /// </summary> /// <param name="fromStream">The stream to read from</param> /// <param name="intoBuffer">The buffer to read into</param> /// <param name="cancellationToken">the cancellation token</param> /// <returns>A websocket frame</returns> public static async Task <WebSocketFrame> ReadAsync(Stream fromStream, ArraySegment <byte> intoBuffer, CancellationToken cancellationToken) { // allocate a small buffer to read small chunks of data from the stream var smallBuffer = new ArraySegment <byte>(new byte[8]); await BinaryReaderWriter.ReadExactly(2, fromStream, smallBuffer, cancellationToken); byte byte1 = smallBuffer.Array[0]; byte byte2 = smallBuffer.Array[1]; // process first byte byte finBitFlag = 0x80; byte opCodeFlag = 0x0F; bool isFinBitSet = (byte1 & finBitFlag) == finBitFlag; WebSocketOpCode opCode = (WebSocketOpCode)(byte1 & opCodeFlag); // read and process second byte byte maskFlag = 0x80; bool isMaskBitSet = (byte2 & maskFlag) == maskFlag; uint len = await ReadLength(byte2, smallBuffer, fromStream, cancellationToken); int count = (int)len; try { // use the masking key to decode the data if needed if (isMaskBitSet) { ArraySegment <byte> maskKey = new ArraySegment <byte>(smallBuffer.Array, 0, WebSocketFrameCommon.MaskKeyLength); await BinaryReaderWriter.ReadExactly(maskKey.Count, fromStream, maskKey, cancellationToken); await BinaryReaderWriter.ReadExactly(count, fromStream, intoBuffer, cancellationToken); ArraySegment <byte> payloadToMask = new ArraySegment <byte>(intoBuffer.Array, intoBuffer.Offset, count); WebSocketFrameCommon.ToggleMask(maskKey, payloadToMask); } else { await BinaryReaderWriter.ReadExactly(count, fromStream, intoBuffer, cancellationToken); } } catch (InternalBufferOverflowException e) { throw new InternalBufferOverflowException($"Supplied buffer too small to read {0} bytes from {Enum.GetName(typeof(WebSocketOpCode), opCode)} frame", e); } if (opCode == WebSocketOpCode.ConnectionClose) { return(DecodeCloseFrame(isFinBitSet, opCode, count, intoBuffer)); } else { // note that by this point the payload will be populated return(new WebSocketFrame(isFinBitSet, opCode, count)); } }
public void ReceivePayload(Socket ClientSocket) { byte[] PayloadBuffer = new byte[HeaderFrame.PayloadLength]; ClientSocket.Receive(PayloadBuffer); for (int i = 0; i < PayloadBuffer.Length; i++) { PayloadBuffer[i] = (byte)(PayloadBuffer[i] ^ HeaderFrame.MaskKey[i % 4]); } PayloadData = Encoding.UTF8.GetString(PayloadBuffer); PayloadOpCode = HeaderFrame.OpCode; }
public WebSocketFrame Read(Stream stream, Socket socket) { byte byte1; try { byte1 = (byte)stream.ReadByte(); } catch (IOException) { if (socket.Connected) { throw; } else { return(null); } } // process first byte byte finBitFlag = 0x80; byte opCodeFlag = 0x0F; bool isFinBitSet = (byte1 & finBitFlag) == finBitFlag; WebSocketOpCode opCode = (WebSocketOpCode)(byte1 & opCodeFlag); // read and process second byte byte byte2 = (byte)stream.ReadByte(); byte maskFlag = 0x80; bool isMaskBitSet = (byte2 & maskFlag) == maskFlag; uint len = ReadLength(byte2, stream); byte[] payload; // use the masking key to decode the data if needed if (isMaskBitSet) { byte[] maskKey = BinaryReaderWriter.ReadExactly(WebSocketFrameCommon.MaskKeyLength, stream); payload = BinaryReaderWriter.ReadExactly((int)len, stream); // apply the mask key to the payload (which will be mutated) WebSocketFrameCommon.ToggleMask(maskKey, payload); } else { payload = BinaryReaderWriter.ReadExactly((int)len, stream); } WebSocketFrame frame = new WebSocketFrame(isFinBitSet, opCode, payload, true); return(frame); }
public void SendFrames(List <string> Data, WebSocketOpCode OpCode) { // Skicka initiella framen SendFrame(Data[0], OpCode, false); for (int i = 1; i < Data.Count - 1; i++) { SendFrame(Data[i], WebSocketOpCode.ContinuationFrame, false); } //Skicka sista framen SendFrame(Data[Data.Count - 1], WebSocketOpCode.ContinuationFrame, true); }
protected virtual void Send(WebSocketOpCode opCode, byte[] toSend, bool isLastFrame) { if (_isOpen) { lock (_sendLocker) { if (_isOpen) { _writer.Write(opCode, toSend, isLastFrame); } } } }
protected override void Send(WebSocketOpCode opCode, byte[] toSend, bool isLastFrame) { if (!IsConnected) { OnError(this, new ErrorEventArgs((Int32)SocketError.NotConnected, string.Format("Connection not available for {0} {1} ", _channelParameters.IP, _channelParameters.Port))); return; } byte[] buffer = _frameBuilder.GetFrameBytesFromData(opCode, toSend, isLastFrame); if (_socketHandler != null) { _socketHandler.Send(buffer); } }
protected virtual void Send(WebSocketOpCode opCode, byte[] toSend, bool isLastFrame) { if (_isOpen) { //_logger.Information(this.GetType(), "WebsocketBase:Send() sending information"); lock (_sendLocker) { if (_isOpen) { _writer.Write(opCode, toSend, isLastFrame); } } } }
public void ParsePayload(WebSocketFlags fl, WebSocketOpCode op, bool mask, UInt64 len, byte[] maskkey, byte[] payload) { Flags = fl; OpCode = op; Mask = mask; PayloadLength = len; MaskingKey = maskkey; Payload = payload; if (Mask && Payload != null) { MaskPayload(); //unmask } }
/// <summary> /// No async await stuff here because we are dealing with a memory stream /// </summary> /// <param name="opCode">The web socket opcode</param> /// <param name="fromPayload">Array segment to get payload data from</param> /// <param name="toStream">Stream to write to</param> /// <param name="isLastFrame">True is this is the last frame in this message (usually true)</param> public static void Write(WebSocketOpCode opCode, ArraySegment <byte> fromPayload, MemoryStream toStream, bool isLastFrame, bool isClient) { MemoryStream memoryStream = toStream; byte finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; byte byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); // NB, set the mask flag if we are constructing a client frame byte maskBitSetAsByte = isClient ? (byte)0x80 : (byte)0x00; // depending on the size of the length we want to write it as a byte, ushort or ulong if (fromPayload.Count < 126) { byte byte2 = (byte)(maskBitSetAsByte | (byte)fromPayload.Count); memoryStream.WriteByte(byte2); } else if (fromPayload.Count <= ushort.MaxValue) { byte byte2 = (byte)(maskBitSetAsByte | 126); memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)fromPayload.Count, memoryStream, false); } else { byte byte2 = (byte)(maskBitSetAsByte | 127); memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)fromPayload.Count, memoryStream, false); } // if we are creating a client frame then we MUST mack the payload as per the spec if (isClient) { byte[] maskKey = new byte[WebSocketFrameCommon.MaskKeyLength]; _random.NextBytes(maskKey); memoryStream.Write(maskKey, 0, maskKey.Length); // mask the payload var maskKeyArraySegment = new ArraySegment <byte>(maskKey, 0, maskKey.Length); WebSocketFrameCommon.ToggleMask(maskKeyArraySegment, fromPayload); memoryStream.Write(fromPayload.Array, fromPayload.Offset, fromPayload.Count); // unmask it so we don't destroy user's data WebSocketFrameCommon.ToggleMask(maskKeyArraySegment, fromPayload); return; } memoryStream.Write(fromPayload.Array, fromPayload.Offset, fromPayload.Count); }
public void Write(WebSocketOpCode opCode, byte[] payload, bool isLastFrame) { // best to write everything to a memory stream before we push it onto the wire // not really necessary but I like it this way using (MemoryStream memoryStream = new MemoryStream()) { byte finBitSetAsByte = isLastFrame ? (byte)0x80 : (byte)0x00; byte byte1 = (byte)(finBitSetAsByte | (byte)opCode); memoryStream.WriteByte(byte1); // NB, set the mask flag if we are constructing a client frame byte maskBitSetAsByte = _isClient ? (byte)0x80 : (byte)0x00; // depending on the size of the length we want to write it as a byte, ushort or ulong if (payload.Length < 126) { byte byte2 = (byte)(maskBitSetAsByte | (byte)payload.Length); memoryStream.WriteByte(byte2); } else if (payload.Length <= ushort.MaxValue) { byte byte2 = (byte)(maskBitSetAsByte | 126); memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteUShort((ushort)payload.Length, memoryStream, false); } else { byte byte2 = (byte)(maskBitSetAsByte | 127); memoryStream.WriteByte(byte2); BinaryReaderWriter.WriteULong((ulong)payload.Length, memoryStream, false); } // if we are creating a client frame then we MUST mack the payload as per the spec if (_isClient) { byte[] maskKey = new byte[WebSocketFrameCommon.MaskKeyLength]; _random.NextBytes(maskKey); memoryStream.Write(maskKey, 0, maskKey.Length); // mask the payload WebSocketFrameCommon.ToggleMask(maskKey, payload); } memoryStream.Write(payload, 0, payload.Length); byte[] buffer = memoryStream.ToArray(); _stream.Write(buffer, 0, buffer.Length); } }
internal void Send(WebSocketOpCode opCode, byte[] payloadBytes, bool disconnectionInProgress) { try { // Start creating a WebSocket packet const int DefaultCapacity = 64; var result = new List <byte>(DefaultCapacity); result.Add((byte)(128 | (byte)opCode)); // Add the payload bytes to the WebSocket packet, prefixed with a properly encoded length if (payloadBytes.Length <= 125) { result.Add((byte)payloadBytes.Length); } if (payloadBytes.Length > 125 && payloadBytes.Length <= ushort.MaxValue) { result.Add(126); var interim = BitConverter.GetBytes((ushort)payloadBytes.Length); Array.Reverse(interim); result.AddRange(interim); } if (payloadBytes.Length > ushort.MaxValue) { result.Add(127); var interim = BitConverter.GetBytes((ulong)payloadBytes.Length); Array.Reverse(interim); result.AddRange(interim); } result.AddRange(payloadBytes); // Send the data Socket.Send(result.ToArray()); } catch (Exception ex) { // Make one attempt to nicely disconnect the socket and raise a disconnection packet if (!disconnectionInProgress) { Disconnect(4000, ex.Message); var disconnectionPacket = new Packet(RemoteEndPoint, WebSocketAction.Disconnect, ex.Message); PacketReceived?.Invoke(disconnectionPacket); } } }
private void MainReadLoop() { NetworkStream networkStream = _networkStream; WebSocketFrameReader reader = new WebSocketFrameReader(); List<WebSocketFrame> fragmentedFrames = new List<WebSocketFrame>(); while (true) { WebSocketFrame frame = reader.Read(networkStream); // if we have received unexpected data if (!frame.IsValid) { return; } if (frame.OpCode == WebSocketOpCode.ContinuationFrame) { switch (_multiFrameOpcode) { case WebSocketOpCode.TextFrame: String data = Encoding.UTF8.GetString(frame.DecodedPayload, 0, frame.DecodedPayload.Length); OnTextMultiFrame(data, frame.IsFinBitSet); break; case WebSocketOpCode.BinaryFrame: OnBinaryMultiFrame(frame.DecodedPayload, frame.IsFinBitSet); break; } } else { switch (frame.OpCode) { case WebSocketOpCode.ConnectionClose: OnConnectionClosed(frame.DecodedPayload); return; case WebSocketOpCode.Ping: OnPing(frame.DecodedPayload); break; case WebSocketOpCode.TextFrame: String data = Encoding.UTF8.GetString(frame.DecodedPayload, 0, frame.DecodedPayload.Length); if (frame.IsFinBitSet) { OnTextFrame(data); } else { _multiFrameOpcode = frame.OpCode; OnTextMultiFrame(data, frame.IsFinBitSet); } break; case WebSocketOpCode.BinaryFrame: if (frame.IsFinBitSet) { OnBinaryFrame(frame.DecodedPayload); } else { _multiFrameOpcode = frame.OpCode; OnBinaryMultiFrame(frame.DecodedPayload, frame.IsFinBitSet); } break; } } } }
private bool ReadStart(BinaryReader reader) { if (reader.BaseStream.Length < 2) return (false); var data = reader.ReadByte(); var nibble2 = (byte)(data & 0x0F); var nibble1 = (byte)(data & 0xF0); if ((nibble1 & EndBit) == EndBit) IsEnd = true; data = reader.ReadByte(); PayloadSize = (byte)(data & 0x7F); IsMasked = (byte)(data & 0x80) > 0; OpCode = (WebSocketOpCode)nibble2; return (true); }
public void Write(WebSocketOpCode opCode, byte[] payload) { Write(opCode, payload, true); }
/// <summary> /// Read web socket frame info /// </summary> /// <param name="buffer">received buffer</param> /// <param name="offset">received offset</param> /// <param name="isFin">is message fin</param> /// <param name="isRSVNull">is all three RSV bits false</param> /// <param name="opCode">operation code</param> /// <param name="isMasked">is payLoadDataMasked (for message from client /// always true, for message from server always false</param> /// <param name="maskBegin">mask begin byte number</param> /// <param name="length">full message length</param> /// <returns>Is whole message received</returns> private static bool GetFrameInfo(byte[] buffer, int offset, int remainingBytesToProcess, out bool isFin, out bool isRSVNull, out WebSocketOpCode opCode, out bool isMasked, out int maskBegin, out int length) { // From specification // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-------+-+-------------+-------------------------------+ // |F|R|R|R| opcode|M| Payload len | Extended payload length | // |I|S|S|S| (4) |A| (7) | (16/64) | // |N|V|V|V| |S| | (if payload len==126/127) | // | |1|2|3| |K| | | // +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + // | Extended payload length continued, if payload len == 127 | // + - - - - - - - - - - - - - - - +-------------------------------+ // | |Masking-key, if MASK set to 1 | // +-------------------------------+-------------------------------+ // | Masking-key (continued) | Payload Data | // +-------------------------------- - - - - - - - - - - - - - - - + // : Payload Data continued ... : // + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // | Payload Data continued ... | // +---------------------------------------------------------------+ isFin = BitOperations.GetBitFromByte(buffer[offset], 8); isRSVNull = (buffer[offset] & 0x70) == 0x00; opCode = (WebSocketOpCode)(buffer[offset] & 0xF); isMasked = BitOperations.GetBitFromByte(buffer[offset + 1], 8); var payLoadLength = buffer[offset + 1] & 0x7F; maskBegin = 2; if (payLoadLength == 0x7E) { payLoadLength = BitConverter.ToUInt16(buffer, offset + 2); maskBegin = 4; } if (payLoadLength == 0x7F) { //IMPORTANT! Converting ulong to int for simplify, //for long data doesn't work! payLoadLength = (int)BitConverter.ToUInt64(buffer, offset + 4); maskBegin = 10; } //4 is a mask length length = maskBegin + payLoadLength + 4; return remainingBytesToProcess >= length; }
internal DataFrame(byte[] payload, WebSocketOpCode opcode) { this.Payload = payload; this.OpCode = opcode; }