Exemplo n.º 1
0
 /// <summary>
 /// Called when a Pong frame is received
 /// </summary>
 /// <param name="e"></param>
 protected virtual void OnPong(PongEventArgs e)
 {
     Pong?.Invoke(this, e);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Receive web socket result
        /// </summary>
        /// <param name="buffer">The buffer to copy data into</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The web socket result details</returns>
        public override async Task <WebSocketReceiveResult> ReceiveAsync(ArraySegment <byte> buffer,
                                                                         CancellationToken cancellationToken)
        {
            try
            {
                // we may receive control frames so reading needs to happen in an infinite loop
                while (true)
                {
                    // allow this operation to be cancelled from iniside OR outside this instance
                    using (CancellationTokenSource linkedCts =
                               CancellationTokenSource.CreateLinkedTokenSource(_internalReadCts.Token, cancellationToken))
                    {
                        WebSocketFrame frame;

                        try
                        {
                            if (_readCursor.NumBytesLeftToRead > 0)
                            {
                                // If the buffer used to read the frame was too small to fit the whole frame then we need to "remember" this frame
                                // and return what we have. Subsequent calls to the read function will simply continue reading off the stream without
                                // decoding the first few bytes as a websocket header.
                                _readCursor =
                                    await WebSocketFrameReader.ReadFromCursorAsync(_stream, buffer, _readCursor,
                                                                                   linkedCts.Token);

                                frame = _readCursor.WebSocketFrame;
                            }
                            else
                            {
                                _readCursor = await WebSocketFrameReader.ReadAsync(_stream, buffer, linkedCts.Token);

                                frame = _readCursor.WebSocketFrame;
                            }
                        }
                        catch (InternalBufferOverflowException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.MessageTooBig,
                                                              "Frame too large to fit in buffer. Use message fragmentation", ex);

                            throw;
                        }
                        catch (ArgumentOutOfRangeException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.ProtocolError,
                                                              "Payload length out of range", ex);

                            throw;
                        }
                        catch (EndOfStreamException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InvalidPayloadData,
                                                              "Unexpected end of stream encountered", ex);

                            throw;
                        }
                        catch (OperationCanceledException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.EndpointUnavailable,
                                                              "Operation cancelled", ex);

                            throw;
                        }
                        catch (Exception ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InternalServerError,
                                                              "Error reading WebSocket frame", ex);

                            throw;
                        }

                        var endOfMessage = frame.IsFinBitSet && _readCursor.NumBytesLeftToRead == 0;
                        switch (frame.OpCode)
                        {
                        case WebSocketOpCode.ConnectionClose:
                            return(await RespondToCloseFrame(frame, buffer, linkedCts.Token));

                        case WebSocketOpCode.Ping:
                            ArraySegment <byte> pingPayload = new ArraySegment <byte>(buffer.Array, buffer.Offset,
                                                                                      _readCursor.NumBytesRead);
                            await SendPongAsync(pingPayload, linkedCts.Token);

                            break;

                        case WebSocketOpCode.Pong:
                            ArraySegment <byte> pongBuffer = new ArraySegment <byte>(buffer.Array,
                                                                                     _readCursor.NumBytesRead, buffer.Offset);
                            Pong?.Invoke(this, new PongEventArgs(pongBuffer));
                            break;

                        case WebSocketOpCode.TextFrame:
                            if (!frame.IsFinBitSet)
                            {
                                // continuation frames will follow, record the message type Text
                                _continuationFrameMessageType = WebSocketMessageType.Text;
                            }

                            return(new WebSocketReceiveResult(_readCursor.NumBytesRead, WebSocketMessageType.Text,
                                                              endOfMessage));

                        case WebSocketOpCode.BinaryFrame:
                            if (!frame.IsFinBitSet)
                            {
                                // continuation frames will follow, record the message type Binary
                                _continuationFrameMessageType = WebSocketMessageType.Binary;
                            }

                            return(new WebSocketReceiveResult(_readCursor.NumBytesRead, WebSocketMessageType.Binary,
                                                              endOfMessage));

                        case WebSocketOpCode.ContinuationFrame:
                            return(new WebSocketReceiveResult(_readCursor.NumBytesRead,
                                                              _continuationFrameMessageType, endOfMessage));

                        default:
                            Exception ex = new NotSupportedException($"Unknown WebSocket opcode {frame.OpCode}");
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.ProtocolError, ex.Message, ex);

                            throw ex;
                        }
                    }
                }
            }
            catch (Exception catchAll)
            {
                // Most exceptions will be caught closer to their source to send an appropriate close message (and set the WebSocketState)
                // However, if an unhandled exception is encountered and a close message not sent then send one here
                if (_state == WebSocketState.Open)
                {
                    await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InternalServerError,
                                                      "Unexpected error reading from WebSocket", catchAll);
                }

                throw;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Receive web socket result
        /// </summary>
        /// <param name="buffer">The buffer to copy data into</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The web socket result details</returns>
        public override async Task <WebSocketReceiveResult> ReceiveAsync(ArraySegment <byte> buffer, CancellationToken cancellationToken)
        {
            try
            {
                // we may receive control frames so reading needs to happen in an infinite loop
                while (true)
                {
                    // allow this operation to be cancelled from iniside OR outside this instance
                    using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_internalReadCts.Token, cancellationToken))
                    {
                        WebSocketFrame frame = null;
                        try
                        {
                            frame = await WebSocketFrameReader.ReadAsync(_stream, buffer, linkedCts.Token);

                            Events.Log.ReceivedFrame(_guid, frame.OpCode, frame.IsFinBitSet, frame.Count);
                        }
                        catch (InternalBufferOverflowException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.MessageTooBig, "Frame too large to fit in buffer. Use message fragmentation", ex);

                            throw;
                        }
                        catch (ArgumentOutOfRangeException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.ProtocolError, "Payload length out of range", ex);

                            throw;
                        }
                        catch (EndOfStreamException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InvalidPayloadData, "Unexpected end of stream encountered", ex);

                            throw;
                        }
                        catch (OperationCanceledException ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.EndpointUnavailable, "Operation cancelled", ex);

                            throw;
                        }
                        catch (Exception ex)
                        {
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InternalServerError, "Error reading WebSocket frame", ex);

                            throw;
                        }

                        switch (frame.OpCode)
                        {
                        case WebSocketOpCode.ConnectionClose:
                            return(await RespondToCloseFrame(frame, buffer, linkedCts.Token));

                        case WebSocketOpCode.Ping:
                            ArraySegment <byte> pingPayload = new ArraySegment <byte>(buffer.Array, buffer.Offset, frame.Count);
                            await SendPongAsync(pingPayload, linkedCts.Token);

                            break;

                        case WebSocketOpCode.Pong:
                            ArraySegment <byte> pongBuffer = new ArraySegment <byte>(buffer.Array, frame.Count, buffer.Offset);
                            Pong?.Invoke(this, new PongEventArgs(pongBuffer));
                            break;

                        case WebSocketOpCode.TextFrame:
                            if (!frame.IsFinBitSet)
                            {
                                // continuation frames will follow, record the message type Text
                                _continuationFrameMessageType = WebSocketMessageType.Text;
                            }
                            return(new WebSocketReceiveResult(frame.Count, WebSocketMessageType.Text, frame.IsFinBitSet));

                        case WebSocketOpCode.BinaryFrame:
                            if (!frame.IsFinBitSet)
                            {
                                // continuation frames will follow, record the message type Binary
                                _continuationFrameMessageType = WebSocketMessageType.Binary;
                            }
                            return(new WebSocketReceiveResult(frame.Count, WebSocketMessageType.Binary, frame.IsFinBitSet));

                        case WebSocketOpCode.ContinuationFrame:
                            return(new WebSocketReceiveResult(frame.Count, _continuationFrameMessageType, frame.IsFinBitSet));

                        default:
                            Exception ex = new NotSupportedException($"Unknown WebSocket opcode {frame.OpCode}");
                            await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.ProtocolError, ex.Message, ex);

                            throw ex;
                        }
                    }
                }
            }
            catch (Exception catchAll)
            {
                // Most exceptions will be caught closer to their source to send an appropriate close message (and set the WebSocketState)
                // However, if an unhandled exception is encountered and a close message not sent then send one here
                if (_state == WebSocketState.Open)
                {
                    await CloseOutputAutoTimeoutAsync(WebSocketCloseStatus.InternalServerError, "Unexpected error reading from WebSocket", catchAll);
                }

                throw;
            }
        }
Exemplo n.º 4
0
        private void ProcessReceive(SocketAsyncEventArgs ioEventArgs)
        {
            var dataToken = (WSDataToken)ioEventArgs.UserToken;
            var socket    = (WebSocket)dataToken.Socket;

            if (ioEventArgs.BytesTransferred == 0)
            {
                //对方主动关闭socket
                Closing(ioEventArgs, Opcode.Empty);
                return;
            }
            if (ioEventArgs.SocketError != SocketError.Success)
            {
                //Socket错误
                Closing(ioEventArgs);
                return;
            }

            bool needPostAnother = TryReceiveMessage(ioEventArgs, out List <DataMessage> messages, out bool hasHandshaked);

            if (hasHandshaked)
            {
                Connected?.Invoke(this, new WebSocketEventArgs(socket));
            }
            if (messages != null)
            {
                foreach (var message in messages)
                {
                    try
                    {
                        switch (message.Opcode)
                        {
                        case Opcode.Close:
                            Closing(ioEventArgs);
                            needPostAnother = false;
                            break;

                        case Opcode.Ping:
                            Ping?.Invoke(this, new WebSocketEventArgs(socket, message));
                            break;

                        case Opcode.Pong:
                            Pong?.Invoke(this, new WebSocketEventArgs(socket, message));
                            break;

                        default:
                            DataReceived?.Invoke(this, new WebSocketEventArgs(socket, message));
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.Error("OnDataReceived error:{0}", ex);
                    }
                }
            }
            if (needPostAnother)
            {
                if (socket.IsClosed)
                {
                    ResetSAEAObject(ioEventArgs);
                }
                else
                {
                    PostReceive(ioEventArgs);
                }
            }
        }