internal async Task ProcessWebSocketRequestAsync(WebSocket webSocket, CancellationToken disconnectToken, Func <object, Task <WebSocketMessage> > messageRetriever, object state)
        {
            bool closedReceived = false;

            try
            {
                // first, set primitives and initialize the object
                WebSocket = webSocket;
                OnOpen();

                // dispatch incoming messages
                while (!disconnectToken.IsCancellationRequested && !closedReceived)
                {
                    WebSocketMessage incomingMessage = await messageRetriever(state).PreserveCulture();

                    switch (incomingMessage.MessageType)
                    {
                    case WebSocketMessageType.Binary:
                        OnMessage((byte[])incomingMessage.Data);
                        break;

                    case WebSocketMessageType.Text:
                        OnMessage((string)incomingMessage.Data);
                        break;

                    default:
                        closedReceived = true;

                        // If we received an incoming CLOSE message, we'll queue a CLOSE frame to be sent.
                        // We'll give the queued frame some amount of time to go out on the wire, and if a
                        // timeout occurs we'll give up and abort the connection.
                        await Task.WhenAny(CloseAsync(), Task.Delay(_closeTimeout)).PreserveCulture();

                        break;
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                // ex.CancellationToken never has the token that was actually cancelled
                if (!disconnectToken.IsCancellationRequested)
                {
                    Error = ex;
                    OnError();
                }
            }
            catch (ObjectDisposedException)
            {
                // If the websocket was disposed while we were reading then noop
            }
            catch (Exception ex)
            {
                if (IsFatalException(ex))
                {
                    Error = ex;
                    OnError();
                }
            }

            OnClose();
        }
        private static bool TryGetMessage(WebSocketReceiveResult receiveResult, byte[] buffer, out WebSocketMessage message)
        {
            message = null;

            if (receiveResult.MessageType == WebSocketMessageType.Close)
            {
                message = WebSocketMessage.CloseMessage;
            }
            else if (receiveResult.EndOfMessage)
            {
                // we anticipate that single-fragment messages will be common, so we optimize for them
                switch (receiveResult.MessageType)
                {
                    case WebSocketMessageType.Binary:
                        if (buffer == null)
                        {
                            message = WebSocketMessage.EmptyBinaryMessage;
                        }
                        else
                        {
                            message = new WebSocketMessage(BufferSliceToByteArray(buffer, receiveResult.Count), WebSocketMessageType.Binary);
                        }
                        break;
                    case WebSocketMessageType.Text:
                        if (buffer == null)
                        {
                            message = WebSocketMessage.EmptyTextMessage;
                        }
                        else
                        {
                            message = new WebSocketMessage(BufferSliceToString(buffer, receiveResult.Count), WebSocketMessageType.Text);
                        }
                        break;
                    default:
                        throw new InvalidOperationException("Unknown message type");
                }
            }

            return message != null;
        }
Beispiel #3
0
        internal async Task ProcessWebSocketRequestAsync(WebSocket webSocket, CancellationToken disconnectToken, Func <object, Task <WebSocketMessage> > messageRetriever, object state)
        {
            bool closedReceived = false;

            try
            {
                // first, set primitives and initialize the object
                WebSocket = webSocket;
                OnOpen();

                // dispatch incoming messages
                while (!disconnectToken.IsCancellationRequested && !closedReceived)
                {
                    WebSocketMessage incomingMessage = await messageRetriever(state).PreserveCulture();

                    switch (incomingMessage.MessageType)
                    {
                    case WebSocketMessageType.Binary:
                        OnMessage((byte[])incomingMessage.Data);
                        break;

                    case WebSocketMessageType.Text:
                        OnMessage((string)incomingMessage.Data);
                        break;

                    default:
                        closedReceived = true;

                        // If we received an incoming CLOSE message, we'll queue a CLOSE frame to be sent.
                        // We'll give the queued frame some amount of time to go out on the wire, and if a
                        // timeout occurs we'll give up and abort the connection.
                        await Task.WhenAny(CloseAsync(), Task.Delay(_closeTimeout)).PreserveCulture();

                        break;
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                // ex.CancellationToken never has the token that was actually cancelled
                if (!disconnectToken.IsCancellationRequested)
                {
                    Error = ex;
                    OnError();
                }
            }
            catch (ObjectDisposedException)
            {
                // If the websocket was disposed while we were reading then noop
            }
            catch (Exception ex)
            {
                if (IsFatalException(ex))
                {
                    Error = ex;
                    OnError();
                }
            }

            try
            {
#if NET_4_6 || UNITY_WSA
                var webSocketState = GetWebSocketState(WebSocket);
                if (webSocketState == WebSocketState.Closed ||
                    webSocketState == WebSocketState.Aborted)
                {
                    // No-op if the socket is already closed or aborted
                }
                else
                {
                    // Initiate the WebSocket closing handshake. Only the client should ever do this.
                    await WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).PreserveCulture();
                }
#endif
            }
            finally
            {
#if NET_4_6 || UNITY_WSA
                WebSocket.Dispose();
#endif
                OnClose();
            }
        }
        private static bool TryGetMessage(WebSocketReceiveResult receiveResult, byte[] buffer, out WebSocketMessage message)
        {
            message = null;

            if (receiveResult.MessageType == WebSocketMessageType.Close)
            {
                message = WebSocketMessage.CloseMessage;
            }
            else if (receiveResult.EndOfMessage)
            {
                // we anticipate that single-fragment messages will be common, so we optimize for them
                switch (receiveResult.MessageType)
                {
                case WebSocketMessageType.Binary:
                    if (buffer == null)
                    {
                        message = WebSocketMessage.EmptyBinaryMessage;
                    }
                    else
                    {
                        message = new WebSocketMessage(BufferSliceToByteArray(buffer, receiveResult.Count), WebSocketMessageType.Binary);
                    }
                    break;

                case WebSocketMessageType.Text:
                    if (buffer == null)
                    {
                        message = WebSocketMessage.EmptyTextMessage;
                    }
                    else
                    {
                        message = new WebSocketMessage(BufferSliceToString(buffer, receiveResult.Count), WebSocketMessageType.Text);
                    }
                    break;

                default:
                    throw new InvalidOperationException("Unknown message type");
                }
            }

            return(message != null);
        }
Beispiel #5
0
        internal async Task ProcessWebSocketRequestAsync(WebSocketContext webSocketContext, Func <Task <WebSocketMessage> > messageRetriever)
        {
            bool cleanClose = true;

            try
            {
                // first, set primitives and initialize the object
                WebSocketContext = webSocketContext;
                OnOpen();

                // dispatch incoming messages
                while (true)
                {
                    WebSocketMessage incomingMessage = await messageRetriever();

                    switch (incomingMessage.MessageType)
                    {
                    case WebSocketMessageType.Binary:
                        OnMessage((byte[])incomingMessage.Data);
                        break;

                    case WebSocketMessageType.Text:
                        OnMessage((string)incomingMessage.Data);
                        break;

                    default:
                        // If we received an incoming CLOSE message, we'll queue a CLOSE frame to be sent.
                        // We'll give the queued frame some amount of time to go out on the wire, and if a
                        // timeout occurs we'll give up and abort the connection.
                        await Task.WhenAny(CloseAsync(), Task.Delay(_closeTimeout))
                        .ContinueWith(_ => { }, TaskContinuationOptions.ExecuteSynchronously);         // swallow exceptions occurring from sending the CLOSE

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                if (IsFatalException(ex))
                {
                    Error = ex;
                    OnError();
                    cleanClose = false;
                }
            }
            finally
            {
                try
                {
                    OnClose(cleanClose);
                }
                finally
                {
                    // call Dispose if it exists
                    IDisposable disposable = this as IDisposable;
                    if (disposable != null)
                    {
                        disposable.Dispose();
                    }
                }
            }
        }
Beispiel #6
0
        internal async Task ProcessWebSocketRequestAsync(WebSocket webSocket, CancellationToken disconnectToken, Func <object, Task <WebSocketMessage> > messageRetriever, object state)
        {
            bool cleanClose = true;

            try
            {
                _isClosed = false;

                // first, set primitives and initialize the object
                WebSocket = webSocket;
                OnOpen();

                // dispatch incoming messages
                while (!disconnectToken.IsCancellationRequested)
                {
                    WebSocketMessage incomingMessage = await messageRetriever(state);

                    switch (incomingMessage.MessageType)
                    {
                    case WebSocketMessageType.Binary:
                        OnMessage((byte[])incomingMessage.Data);
                        break;

                    case WebSocketMessageType.Text:
                        OnMessage((string)incomingMessage.Data);
                        break;

                    default:
                        // If we received an incoming CLOSE message, we'll queue a CLOSE frame to be sent.
                        // We'll give the queued frame some amount of time to go out on the wire, and if a
                        // timeout occurs we'll give up and abort the connection.
                        await Task.WhenAny(CloseAsync(), Task.Delay(_closeTimeout))
                        .ContinueWith(_ => { }, TaskContinuationOptions.ExecuteSynchronously);         // swallow exceptions occurring from sending the CLOSE

                        return;
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                // ex.CancellationToken never has the token that was actually cancelled
                if (!disconnectToken.IsCancellationRequested)
                {
                    Error = ex;
                    OnError();
                    cleanClose = false;
                }
            }
            catch (Exception ex)
            {
                if (IsFatalException(ex))
                {
                    Error = ex;
                    OnError();
                    cleanClose = false;
                }
            }
            finally
            {
                try
                {
                    Close();
                }
                finally
                {
                    OnClose(cleanClose);
                }
            }
        }