Exemplo n.º 1
0
        public void DecodePayload(byte[] buffer, int offset, Header frameHeader, out byte[] payload, out int payloadOffset, out int payloadCount)
        {
            payload = buffer;
            payloadOffset = offset + frameHeader.Length;
            payloadCount = frameHeader.PayloadLength;

            if (frameHeader.IsMasked)
            {
                payload = new byte[payloadCount];

                for (var i = 0; i < payloadCount; i++)
                {
                    payload[i] = (byte)(buffer[payloadOffset + i] ^ buffer[offset + frameHeader.MaskingKeyOffset + i % MaskingKeyLength]);
                }

                payloadOffset = 0;
                payloadCount = payload.Length;
            }

            // Payload data:  (x+y) bytes
            // Extension data:  x bytes
            // Application data:  y bytes
            // The "Extension data" is 0 bytes unless an extension has been
            // negotiated.  Any extension MUST specify the length of the
            // "Extension data", or how that length may be calculated, and how
            // the extension use MUST be negotiated during the opening handshake.
            // If present, the "Extension data" is included in the total payload length.
            if (this.NegotiatedExtensions != null)
            {
                byte[] bakedBuffer = null;
                foreach (var extension in this.NegotiatedExtensions.Reverse().Select(e => e.Value))
                {
                    if (bakedBuffer == null)
                    {
                        bakedBuffer = extension.ProcessIncomingMessagePayload(payload, payloadOffset, payloadCount);
                    }
                    else
                    {
                        bakedBuffer = extension.ProcessIncomingMessagePayload(bakedBuffer, 0, bakedBuffer.Length);
                    }
                }

                payload = bakedBuffer;
                payloadOffset = 0;
                payloadCount = payload.Length;
            }
        }
Exemplo n.º 2
0
 public bool TryDecodeFrameHeader(byte[] buffer, int offset, int count, out Header frameHeader)
 {
     frameHeader = DecodeFrameHeader(buffer, offset, count);
     return frameHeader != null;
 }
Exemplo n.º 3
0
        private Header DecodeFrameHeader(byte[] buffer, int offset, int count)
        {
            if (count < 2)
                return null;

            // parse fixed header
            var header = new Header()
            {
                IsFIN = ((buffer[offset + 0] & 0x80) == 0x80),
                IsRSV1 = ((buffer[offset + 0] & 0x40) == 0x40),
                IsRSV2 = ((buffer[offset + 0] & 0x20) == 0x20),
                IsRSV3 = ((buffer[offset + 0] & 0x10) == 0x10),
                OpCode = (OpCode)(buffer[offset + 0] & 0x0f),
                IsMasked = ((buffer[offset + 1] & 0x80) == 0x80),
                PayloadLength = (buffer[offset + 1] & 0x7f),
                Length = 2,
            };

            // parse extended payload length
            if (header.PayloadLength >= 126)
            {
                if (header.PayloadLength == 126)
                    header.Length += 2;
                else
                    header.Length += 8;

                if (count < header.Length)
                    return null;

                if (header.PayloadLength == 126)
                {
                    header.PayloadLength = buffer[offset + 2] * 256 + buffer[offset + 3];
                }
                else
                {
                    int totalLength = 0;
                    int level = 1;

                    for (int i = 7; i >= 0; i--)
                    {
                        totalLength += buffer[offset + i + 2] * level;
                        level *= 256;
                    }

                    header.PayloadLength = totalLength;
                }
            }

            // parse masking key
            if (header.IsMasked)
            {
                if (count < header.Length + MaskingKeyLength)
                    return null;

                header.MaskingKeyOffset = header.Length;
                header.Length += MaskingKeyLength;
            }

            return header;
        }
Exemplo n.º 4
0
        private async Task HandlePingFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
        {
            if (!frameHeader.IsFIN)
            {
                throw new WebSocketException(string.Format(
                    "Server received unfinished frame [{0}] from remote [{1}].", frameHeader.OpCode, RemoteEndPoint));
            }

            // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in
            // response, unless it already received a Close frame.  It SHOULD
            // respond with Pong frame as soon as is practical.  Pong frames are
            // discussed in Section 5.5.3.
            // 
            // An endpoint MAY send a Ping frame any time after the connection is
            // established and before the connection is closed.
            // 
            // A Ping frame may serve either as a keep-alive or as a means to
            // verify that the remote endpoint is still responsive.
            var ping = Encoding.UTF8.GetString(payload, payloadOffset, payloadCount);
#if DEBUG
            _log.DebugFormat("Session [{0}] received client side ping frame [{1}].", this, ping);
#endif
            if (State == WebSocketState.Open)
            {
                // A Pong frame sent in response to a Ping frame must have identical
                // "Application data" as found in the message body of the Ping frame being replied to.
                var pong = new PongFrame(ping, false).ToArray(_frameBuilder);
                await SendFrame(pong);
#if DEBUG
                _log.DebugFormat("Session [{0}] sends server side pong frame [{1}].", this, ping);
#endif
            }
        }
Exemplo n.º 5
0
        private async Task HandlePongFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
        {
            if (!frameHeader.IsFIN)
            {
                throw new WebSocketException(string.Format(
                    "Server received unfinished frame [{0}] from remote [{1}].", frameHeader.OpCode, RemoteEndPoint));
            }

            // If an endpoint receives a Ping frame and has not yet sent Pong
            // frame(s) in response to previous Ping frame(s), the endpoint MAY
            // elect to send a Pong frame for only the most recently processed Ping frame.
            // 
            // A Pong frame MAY be sent unsolicited.  This serves as a
            // unidirectional heartbeat.  A response to an unsolicited Pong frame is not expected.
            var pong = Encoding.UTF8.GetString(payload, payloadOffset, payloadCount);
            StopKeepAliveTimeoutTimer();
#if DEBUG
            _log.DebugFormat("Session [{0}] received client side pong frame [{1}].", this, pong);
#endif
            await Task.CompletedTask;
        }
Exemplo n.º 6
0
 private async Task HandleBinaryFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
 {
     if (frameHeader.IsFIN)
     {
         try
         {
             await _module.OnSessionBinaryReceived(this, payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
     else
     {
         try
         {
             await _module.OnSessionFragmentationStreamOpened(this, payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
 }
Exemplo n.º 7
0
        private async Task HandleCloseFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
        {
            if (!frameHeader.IsFIN)
            {
                throw new WebSocketException(string.Format(
                    "Server received unfinished frame [{0}] from remote [{1}].", frameHeader.OpCode, RemoteEndPoint));
            }

            if (payloadCount > 1)
            {
                var statusCode = payload[payloadOffset + 0] * 256 + payload[payloadOffset + 1];
                var closeCode = (WebSocketCloseCode)statusCode;
                var closeReason = string.Empty;

                if (payloadCount > 2)
                {
                    closeReason = Encoding.UTF8.GetString(payload, payloadOffset + 2, payloadCount - 2);
                }
#if DEBUG
                _log.DebugFormat("Session [{0}] received client side close frame [{1}] [{2}].", this, closeCode, closeReason);
#endif
                // If an endpoint receives a Close frame and did not previously send a
                // Close frame, the endpoint MUST send a Close frame in response.  (When
                // sending a Close frame in response, the endpoint typically echos the
                // status code it received.)  It SHOULD do so as soon as practical.
                await Close(closeCode, closeReason);
            }
            else
            {
#if DEBUG
                _log.DebugFormat("Session [{0}] received client side close frame but no status code.", this);
#endif
                await Close(WebSocketCloseCode.InvalidPayloadData);
            }
        }
Exemplo n.º 8
0
 private async Task HandleTextFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
 {
     if (frameHeader.IsFIN)
     {
         try
         {
             var text = Encoding.UTF8.GetString(payload, payloadOffset, payloadCount);
             await _module.OnSessionTextReceived(this, text);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
     else
     {
         try
         {
             await _module.OnSessionFragmentationStreamOpened(this, payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
 }
Exemplo n.º 9
0
 private async Task HandleContinuationFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
 {
     if (!frameHeader.IsFIN)
     {
         try
         {
             await _module.OnSessionFragmentationStreamContinued(this, payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
     else
     {
         try
         {
             await _module.OnSessionFragmentationStreamClosed(this, payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
 }
Exemplo n.º 10
0
        public void DecodePayload(byte[] buffer, int offset, Header frameHeader, out byte[] payload, out int payloadOffset, out int payloadCount)
        {
            payload = buffer;
            payloadOffset = offset + frameHeader.Length;
            payloadCount = frameHeader.PayloadLength;

            if (frameHeader.IsMasked)
            {
                payload = new byte[payloadCount];

                for (var i = 0; i < payloadCount; i++)
                {
                    payload[i] = (byte)(buffer[payloadOffset + i] ^ buffer[offset + frameHeader.MaskingKeyOffset + i % MaskingKeyLength]);
                }

                payloadOffset = 0;
                payloadCount = payload.Length;
            }
        }
Exemplo n.º 11
0
 private void HandleBinaryFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
 {
     if (frameHeader.IsFIN)
     {
         try
         {
             RaiseServerBinaryReceived(payload, payloadOffset, payloadCount);
         }
         catch (Exception ex)
         {
             HandleUserSideError(ex);
         }
     }
     else
     {
         throw new WebSocketException(string.Format(
             "Client received continuation opcode [{0}] from remote [{1}] but not supported.", frameHeader.OpCode, RemoteEndPoint));
     }
 }
Exemplo n.º 12
0
 private void HandleContinuationFrame(Header frameHeader, byte[] payload, int payloadOffset, int payloadCount)
 {
     throw new WebSocketException(string.Format(
         "Client received continuation opcode [{0}] from remote [{1}] but not supported.", frameHeader.OpCode, RemoteEndPoint));
 }