/// <summary>
        ///     Are about to send a new message
        /// </summary>
        /// <param name="message">Message to send</param>
        /// <remarks>
        ///     Can be used to prepare the next message. for instance serialize it etc.
        /// </remarks>
        /// <exception cref="NotSupportedException">Message is of a type that the encoder cannot handle.</exception>
        public void Prepare(object message)
        {
            if (message is IWebSocketMessage)
            {
                _message = (IWebSocketMessage)message;
                _message.Payload.Position = 0;
                _totalAmountToSend        = (int)_message.Payload.Length;
            }
            else
            {
                try
                {
                    _httpMessageEncoder.Prepare(message);

                    var httpMessage = message as IHttpMessage;
                    if (WebSocketUtils.IsWebSocketUpgrade(httpMessage))
                    {
                        _handshake = httpMessage;
                    }
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("This encoder only supports messages deriving from 'HttpMessage' or 'WebSocketMessage'", e);
                }
            }
        }
        /// <summary>
        /// Intercept http messages and look for websocket upgrade requests
        /// </summary>
        /// <param name="message">message from http decoder</param>
        private void OnHttpMessage(object message)
        {
            var httpMessage = message as IHttpMessage;

            // TODO: is there a better way to detect WebSocket upgrade?
            if (WebSocketUtils.IsWebSocketUpgrade(httpMessage))
            {
                _handshake   = httpMessage;
                _isWebSocket = true;
            }

            _messageReceived(message);
        }
Exemple #3
0
        /// <summary>
        /// Handles the upgrade
        /// </summary>
        /// <param name="source">Channel that we've received a request from</param>
        /// <param name="msg">Message received.</param>
        protected override void OnMessage(ITcpChannel source, object msg)
        {
            var httpMessage = msg as IHttpMessage;

            if (WebSocketUtils.IsWebSocketUpgrade(httpMessage))
            {
                if (httpMessage is IHttpRequest) // server mode
                {
                    var args = new WebSocketClientConnectEventArgs(source, (IHttpRequest)httpMessage);
                    WebSocketClientConnect(this, args);

                    if (args.MayConnect)
                    {
                        var webSocketKey = httpMessage.Headers["Sec-WebSocket-Key"];

                        // TODO: why not provide the response in the WebSocketClientConnectEventArgs event?
                        var response = new WebSocketUpgradeResponse(webSocketKey);

                        source.Send(response);

                        WebSocketClientConnected(this,
                                                 new WebSocketClientConnectedEventArgs(source, (IHttpRequest)httpMessage, response));
                    }
                    else
                    {
                        var response = new HttpResponseBase(HttpStatusCode.NotImplemented, "Not Implemented", "HTTP/1.1");
                        if (args.Response != null)
                        {
                            response.Body = args.Response;
                        }

                        source.Send(response);
                    }
                    return;
                }

                if (httpMessage is IHttpResponse) // client mode
                {
                    WebSocketClientConnected(this,
                                             new WebSocketClientConnectedEventArgs(source, null, (IHttpResponse)httpMessage));
                }
            }

            var webSocketMessage = msg as IWebSocketMessage;

            if (webSocketMessage != null)
            {
                // standard message responses handled by listener
                switch (webSocketMessage.Opcode)
                {
                case WebSocketOpcode.Ping:
                    source.Send(new WebSocketMessage(WebSocketOpcode.Pong, webSocketMessage.Payload));
                    return;

                case WebSocketOpcode.Close:
                    source.Send(new WebSocketMessage(WebSocketOpcode.Close));
                    source.Close();

                    WebSocketClientDisconnected(this,
                                                new ClientDisconnectedEventArgs(source, new Exception("WebSocket closed")));
                    return;
                }

                _webSocketMessageReceived(source, webSocketMessage);
                return;
            }

            base.OnMessage(source, msg);
        }