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);
                }
            }
        }
        /// <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);
                }
            }
        }
Exemplo n.º 7
0
 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;
                    }
                }
            }
        }
Exemplo n.º 9
0
 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;
 }
 internal WebSocketResponse(WebSocketFrame frame)
     : base(frame.Opcode, frame.Payload)
 {
 }