public void big_start_frame() { var buffer = new byte[0x010000]; var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketOpcode.Binary, WebSocketMask.Unmask, new MemoryStream(buffer)); frame.PayloadLength.Should().Be(127); frame.ExtPayloadLength.Should().BeEquivalentTo(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }); }
public void small_end_frame() { var buffer = new byte[125]; var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketOpcode.Binary, WebSocketMask.Unmask, new MemoryStream(buffer)); frame.PayloadLength.Should().Be(125); frame.ExtPayloadLength.Should().BeNullOrEmpty(); }
public void medium_end_frame() { var buffer = new byte[0x00FFFF]; var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketOpcode.Binary, WebSocketMask.Unmask, new MemoryStream(buffer)); frame.PayloadLength.Should().Be(126); frame.ExtPayloadLength.Should().BeEquivalentTo(new byte[] { 255, 255 }); }
public void empty_frame() { var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketOpcode.Text, WebSocketMask.Unmask, null); frame.Fin.Should().Be(WebSocketFin.Final); frame.Opcode.Should().Be(WebSocketOpcode.Text); frame.Mask.Should().Be(WebSocketMask.Unmask); frame.Rsv1.Should().Be(WebSocketRsv.Off); frame.Rsv2.Should().Be(WebSocketRsv.Off); frame.Rsv3.Should().Be(WebSocketRsv.Off); frame.MaskingKey.Should().BeNullOrEmpty(); frame.PayloadLength.Should().Be(0); frame.ExtPayloadLength.Should().BeNullOrEmpty(); }
/// <summary> /// Buffer structure used for socket send operations. /// </summary> /// <param name="buffer"> /// Do note that there are not buffer attached to the structure, you have to assign one yourself using /// <see cref="ISocketBuffer.SetBuffer(int,int)" />. This choice was made /// to prevent unnecessary copy operations. /// </param> public void Send(ISocketBuffer buffer) { if (_message == null) { _httpMessageEncoder.Send(buffer); } else { // last send operation did not send all bytes enqueued in the buffer // so let's just continue until doing next message if (_bytesToSend > 0) { buffer.SetBuffer(_buffer, _offset, _bytesToSend); return; } var offset = (int)_message.Payload.Position; var length = (int)_message.Payload.Length; var frameLength = length - offset; var fin = WebSocketFin.Final; if (frameLength > WebSocketFrame.FragmentLength) { frameLength = WebSocketFrame.FragmentLength; fin = WebSocketFin.More; } var opcode = WebSocketOpcode.Continuation; if (offset == 0) // first frame { opcode = _message.Opcode; } var buff = new byte[frameLength]; _message.Payload.Read(buff, 0, buff.Length); var payload = new MemoryStream(buff); WebSocketFrame frame = new WebSocketFrame(fin, opcode, (_handshake is IHttpRequest) ? WebSocketMask.Mask : WebSocketMask.Unmask, payload); using (var stream = new MemoryStream()) { var header = (int)frame.Fin; header = (header << 1) + (int)frame.Rsv1; header = (header << 1) + (int)frame.Rsv2; header = (header << 1) + (int)frame.Rsv3; header = (header << 4) + (int)frame.Opcode; header = (header << 1) + (int)frame.Mask; header = (header << 7) + (int)frame.PayloadLength; stream.Write(WebSocketUtils.GetBigEndianBytes((ushort)header), 0, 2); if (frame.PayloadLength > 125) { stream.Write(frame.ExtPayloadLength, 0, frame.ExtPayloadLength.Length); } if (frame.Mask == WebSocketMask.Mask) { stream.Write(frame.MaskingKey, 0, frame.MaskingKey.Length); frame.Unmask(); } _totalAmountToSend += (int)stream.Length; if (frame.PayloadLength > 0) { frame.Payload.CopyTo(stream); } buffer.UserToken = _message; _buffer = stream.ToArray(); _bytesToSend = _buffer.Length; buffer.SetBuffer(_buffer, 0, _bytesToSend); } } }
public WebSocketResponse(WebSocketFrame frame) : base(frame.Opcode, frame.Payload) { }
/// <summary> /// We've received bytes from the socket. Build a message out of them. /// </summary> /// <param name="buffer">Buffer</param> public void ProcessReadBytes(ISocketBuffer buffer) { if (!_isWebSocket) { _httpMessageDecoder.ProcessReadBytes(buffer); } else { var receiveBufferOffset = buffer.Offset; var bytesLeftInReceiveBuffer = buffer.BytesTransferred; while (true) { if (bytesLeftInReceiveBuffer <= 0) { break; } if (_frame == null) { var first = buffer.Buffer[receiveBufferOffset + 0]; var second = buffer.Buffer[receiveBufferOffset + 1]; var fin = (first & 0x80) == 0x80 ? WebSocketFin.Final : WebSocketFin.More; var rsv1 = (first & 0x40) == 0x40 ? WebSocketRsv.On : WebSocketRsv.Off; var rsv2 = (first & 0x20) == 0x20 ? WebSocketRsv.On : WebSocketRsv.Off; var rsv3 = (first & 0x10) == 0x10 ? WebSocketRsv.On : WebSocketRsv.Off; var opcode = (WebSocketOpcode)(first & 0x0f); var mask = (second & 0x80) == 0x80 ? WebSocketMask.Mask : WebSocketMask.Unmask; var payloadLen = (byte)(second & 0x7f); receiveBufferOffset += 2; bytesLeftInReceiveBuffer -= 2; // TODO: // check if valid headers // control frame && payloadLen > 125 // control frame && more // not data && compressed var size = payloadLen < 126 ? 0 : payloadLen == 126 ? 2 : 8; var extPayloadLen = new byte[size]; for (var i = 0; i < size; i++) { extPayloadLen[i] = buffer.Buffer[receiveBufferOffset + i]; } receiveBufferOffset += size; bytesLeftInReceiveBuffer -= size; var maskingKey = new byte[0]; if (mask == WebSocketMask.Mask) { maskingKey = new byte[] { buffer.Buffer[receiveBufferOffset + 0], buffer.Buffer[receiveBufferOffset + 1], buffer.Buffer[receiveBufferOffset + 2], buffer.Buffer[receiveBufferOffset + 3], }; receiveBufferOffset += 4; bytesLeftInReceiveBuffer -= 4; } ulong len = payloadLen < 126 ? payloadLen : payloadLen == 126 ? WebSocketUtils.ToBigEndianUInt16(extPayloadLen) : WebSocketUtils.ToBigEndianUInt64(extPayloadLen); _frameContentBytesLeft = (int)len; _frame = new WebSocketFrame(fin, rsv1, rsv2, rsv3, opcode, mask, maskingKey, payloadLen, extPayloadLen, new MemoryStream(_frameContentBytesLeft)); if (_frame.Fin == WebSocketFin.More || _frame.Opcode == WebSocketOpcode.Continuation) { _frames.Add(_frame); } } if (_frameContentBytesLeft > 0) { var bytesRead = BytesProcessed(buffer.Offset, receiveBufferOffset); var bytesToWrite = Math.Min(_frameContentBytesLeft, buffer.BytesTransferred - bytesRead); _frame.Payload.Write(buffer.Buffer, receiveBufferOffset, bytesToWrite); _frameContentBytesLeft -= bytesToWrite; receiveBufferOffset += bytesToWrite; bytesLeftInReceiveBuffer -= bytesToWrite; } if (_frameContentBytesLeft == 0) { _frame.Payload.Position = 0; if (_frame.Fin == WebSocketFin.Final) { if (_frame.Opcode == WebSocketOpcode.Continuation) { TriggerMessageReceived(_frames); _frames = new List <WebSocketFrame>(); } else { TriggerMessageReceived(new[] { _frame }); } } _frame = null; } } } }
private static WebSocketResponse CreateWebSocketResponse(string json) { var ms = new MemoryStream(Encoding.UTF8.GetBytes(json)) {Position = 0}; var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketOpcode.Text, WebSocketMask.Unmask, ms); return new WebSocketResponse(frame); }
public void masked_frame() { var buffer = new byte[8]; var maskingKey = new byte[4]; new Random().NextBytes(buffer); new Random().NextBytes(maskingKey); var frame = new WebSocketFrame(WebSocketFin.Final, WebSocketRsv.Off, WebSocketRsv.Off, WebSocketRsv.Off, WebSocketOpcode.Binary, WebSocketMask.Mask, maskingKey, (byte)4, new byte[0], new MemoryStream(buffer)); frame.Mask.Should().Be(WebSocketMask.Mask); frame.MaskingKey.Should().Equal(maskingKey); frame.PayloadLength.Should().Be(4); frame.Unmask(); frame.Mask.Should().Be(WebSocketMask.Unmask); frame.MaskingKey.Should().BeNullOrEmpty(); frame.Payload.Position.Should().Be(0); frame.Payload.ReadByte().Should().Be(buffer[0] ^ maskingKey[0]); frame.Payload.ReadByte().Should().Be(buffer[1] ^ maskingKey[1]); frame.Payload.ReadByte().Should().Be(buffer[2] ^ maskingKey[2]); frame.Payload.ReadByte().Should().Be(buffer[3] ^ maskingKey[3]); frame.Payload.ReadByte().Should().Be(buffer[4] ^ maskingKey[0]); frame.Payload.ReadByte().Should().Be(buffer[5] ^ maskingKey[1]); frame.Payload.ReadByte().Should().Be(buffer[6] ^ maskingKey[2]); frame.Payload.ReadByte().Should().Be(buffer[7] ^ maskingKey[3]); Assert.DoesNotThrow(() => frame.Unmask()); }
internal WebSocketResponse(WebSocketFrame frame) : base(frame.Opcode, frame.Payload) { }
/// <summary> /// We've received bytes from the socket. Build a message out of them. /// </summary> /// <param name="buffer">Buffer</param> public void ProcessReadBytes(ISocketBuffer buffer) { if (!_isWebSocket) { _httpMessageDecoder.ProcessReadBytes(buffer); } else { var receiveBufferOffset = buffer.Offset; var bytesLeftInReceiveBuffer = buffer.BytesTransferred; while (true) { if (bytesLeftInReceiveBuffer <= 0) break; if (_frame == null) { var first = buffer.Buffer[receiveBufferOffset + 0]; var second = buffer.Buffer[receiveBufferOffset + 1]; var fin = (first & 0x80) == 0x80 ? WebSocketFin.Final : WebSocketFin.More; var rsv1 = (first & 0x40) == 0x40 ? WebSocketRsv.On : WebSocketRsv.Off; var rsv2 = (first & 0x20) == 0x20 ? WebSocketRsv.On : WebSocketRsv.Off; var rsv3 = (first & 0x10) == 0x10 ? WebSocketRsv.On : WebSocketRsv.Off; var opcode = (WebSocketOpcode)(first & 0x0f); var mask = (second & 0x80) == 0x80 ? WebSocketMask.Mask : WebSocketMask.Unmask; var payloadLen = (byte)(second & 0x7f); receiveBufferOffset += 2; bytesLeftInReceiveBuffer -= 2; // TODO: // check if valid headers // control frame && payloadLen > 125 // control frame && more // not data && compressed var size = payloadLen < 126 ? 0 : payloadLen == 126 ? 2 : 8; var extPayloadLen = new byte[size]; for (var i = 0; i < size; i++) { extPayloadLen[i] = buffer.Buffer[receiveBufferOffset + i]; } receiveBufferOffset += size; bytesLeftInReceiveBuffer -= size; var maskingKey = new byte[0]; if (mask == WebSocketMask.Mask) { maskingKey = new byte[] { buffer.Buffer[receiveBufferOffset + 0], buffer.Buffer[receiveBufferOffset + 1], buffer.Buffer[receiveBufferOffset + 2], buffer.Buffer[receiveBufferOffset + 3], }; receiveBufferOffset += 4; bytesLeftInReceiveBuffer -= 4; } ulong len = payloadLen < 126 ? payloadLen : payloadLen == 126 ? WebSocketUtils.ToBigEndianUInt16(extPayloadLen) : WebSocketUtils.ToBigEndianUInt64(extPayloadLen); _frameContentBytesLeft = (int)len; _frame = new WebSocketFrame(fin, rsv1, rsv2, rsv3, opcode, mask, maskingKey, payloadLen, extPayloadLen, new MemoryStream(_frameContentBytesLeft)); if (_frame.Fin == WebSocketFin.More || _frame.Opcode == WebSocketOpcode.Continuation) { _frames.Add(_frame); } } if (_frameContentBytesLeft > 0) { var bytesRead = BytesProcessed(buffer.Offset, receiveBufferOffset); var bytesToWrite = Math.Min(_frameContentBytesLeft, buffer.BytesTransferred - bytesRead); _frame.Payload.Write(buffer.Buffer, receiveBufferOffset, bytesToWrite); _frameContentBytesLeft -= bytesToWrite; receiveBufferOffset += bytesToWrite; bytesLeftInReceiveBuffer -= bytesToWrite; } if (_frameContentBytesLeft == 0) { _frame.Payload.Position = 0; if (_frame.Fin == WebSocketFin.Final) { if (_frame.Opcode == WebSocketOpcode.Continuation) { TriggerMessageReceived(_frames); _frames = new List<WebSocketFrame>(); } else { TriggerMessageReceived(new[] { _frame }); } } _frame = null; } } } }
/// <summary> /// Reset decoder state so that we can decode a new message /// </summary> public void Clear() { _httpMessageDecoder.Clear(); _handshake = null; _frame = null; _frames = new List<WebSocketFrame>(); _frameContentBytesLeft = 0; _isWebSocket = false; }