Exemple #1
0
        /// <summary>
        /// Handles the connection and reads received HMQ messages
        /// </summary>
        public async Task HandleConnection(IConnectionInfo info, ProtocolHandshakeResult handshakeResult)
        {
            //if user makes a mistake in ready method, we should not interrupt connection handling
            try
            {
                await _handler.Ready(_server, (HorseServerSocket)handshakeResult.Socket);
            }
            catch (Exception e)
            {
                if (_server.Logger != null)
                {
                    _server.Logger.LogException("Unhandled Exception", e);
                }
            }

            HmqReader reader = new HmqReader();

            while (info.Client != null && info.Client.Connected)
            {
                HorseMessage message = await reader.Read(info.GetStream());

                if (message == null)
                {
                    info.Close();
                    return;
                }

                await ProcessMessage(info, message, (HorseServerSocket)handshakeResult.Socket);
            }
        }
Exemple #2
0
        /// <summary>
        /// Checks if received data is a TMQ protocol message
        /// </summary>
        public async Task <ProtocolHandshakeResult> Handshake(IConnectionInfo info, byte[] data)
        {
            ProtocolHandshakeResult result = new ProtocolHandshakeResult();

            if (data.Length < 8)
            {
                return(await Task.FromResult(result));
            }

            result.Accepted = CheckProtocol(data);
            if (!result.Accepted)
            {
                return(result);
            }

            TmqReader  reader  = new TmqReader();
            TmqMessage message = await reader.Read(info.GetStream());

            //sends protocol message
            await info.GetStream().WriteAsync(PredefinedMessages.PROTOCOL_BYTES);

            bool alive = await ProcessFirstMessage(message, info, result);

            if (!alive)
            {
                return(result);
            }

            result.PipeConnection = true;
            info.State            = ConnectionStates.Pipe;
            info.Protocol         = this;

            return(result);
        }
        /// <summary>
        /// After protocol handshake is completed, this method is called to handle events for the specified client
        /// </summary>
        public async Task HandleConnection(IConnectionInfo info, ProtocolHandshakeResult handshakeResult)
        {
            //if user makes a mistake in ready method, we should not interrupt connection handling
            try
            {
                await _handler.Ready(_server, (WsServerSocket)handshakeResult.Socket);
            }
            catch (Exception e)
            {
                if (_server.Logger != null)
                {
                    _server.Logger.LogException("Unhandled Exception", e);
                }
            }

            WebSocketReader reader = new WebSocketReader();
            Stream          stream = info.GetStream();

            while (info.Socket != null && info.Socket.IsConnected)
            {
                WebSocketMessage message = await reader.Read(stream);

                if (message == null)
                {
                    info.Close();
                    return;
                }

                handshakeResult.Socket.KeepAlive();
                await ProcessMessage(info, handshakeResult.Socket, message);
            }
        }
Exemple #4
0
        /// <summary>
        /// Checks if data is belong this protocol.
        /// </summary>
        /// <param name="info">Connection information</param>
        /// <param name="data">Data is first 8 bytes of the first received message from the client</param>
        /// <returns></returns>
        public async Task <ProtocolHandshakeResult> Handshake(IConnectionInfo info, byte[] data)
        {
            ProtocolHandshakeResult result = new ProtocolHandshakeResult();

            result.Accepted = CheckProtocol(data);
            if (result.Accepted)
            {
                result.ReadAfter = true;
            }

            info.State = ConnectionStates.Http;
            return(await Task.FromResult(result));
        }
Exemple #5
0
        /// <summary>
        /// After protocol handshake is completed, this method is called to handle events for the specified client
        /// </summary>
        public async Task HandleConnection(IConnectionInfo info, ProtocolHandshakeResult handshakeResult)
        {
            //if user makes a mistake in ready method, we should not interrupt connection handling
            try
            {
                await _handler.Ready(_server, handshakeResult.Socket);
            }
            catch (Exception e)
            {
                if (_server.Logger != null)
                {
                    _server.Logger.LogException("Unhandled Exception", e);
                }
            }

            HttpReader reader = new HttpReader(Options);
            HttpWriter writer = new HttpWriter(Options);

            reader.HandshakeResult = handshakeResult;

            HandleStatus status;

            do
            {
                HttpMessage message = await reader.Read(info.GetStream());

                if (message.Request != null)
                {
                    message.Request.IpAddress = FindIPAddress(info.Client);
                }

                status = await ProcessMessage(info, writer, message, reader.ContentLength);

                if (status == HandleStatus.ReadAgain)
                {
                    reader.Reset();
                }
            } while (status == HandleStatus.ReadAgain);

            if (status == HandleStatus.Close)
            {
                info.Close();
            }
        }
        /// <summary>
        /// When protocol is switched to this protocol from another protocol
        /// </summary>
        public async Task <ProtocolHandshakeResult> SwitchTo(IConnectionInfo info, ConnectionData data)
        {
            if (!info.Protocol.Name.Equals("http", StringComparison.InvariantCultureIgnoreCase))
            {
                return(await Task.FromResult(new ProtocolHandshakeResult()));
            }

            string key;
            bool   hasKey = data.Properties.TryGetValue(PredefinedMessages.WEBSOCKET_KEY, out key);

            if (!hasKey)
            {
                return(await Task.FromResult(new ProtocolHandshakeResult()));
            }

            ProtocolHandshakeResult result = new ProtocolHandshakeResult();

            result.PipeConnection = true;
            result.Accepted       = true;
            result.ReadAfter      = false;
            result.PreviouslyRead = null;
            result.Response       = await CreateWebSocketHandshakeResponse(key);

            WsServerSocket socket = await _handler.Connected(_server, info, data);

            if (socket == null)
            {
                return(await Task.FromResult(new ProtocolHandshakeResult()));
            }

            info.State    = ConnectionStates.Pipe;
            result.Socket = socket;
            _server.Pinger.Add(socket);

            socket.SetCleanupAction(s =>
            {
                _server.Pinger.Remove(socket);
                _handler.Disconnected(_server, s);
            });

            return(result);
        }
Exemple #7
0
        /// <summary>
        /// Switches client's protocol to new protocol (finds by name)
        /// </summary>
        public async Task SwitchProtocol(IConnectionInfo info, string newProtocolName, ConnectionData data)
        {
            foreach (ITwinoProtocol protocol in Protocols)
            {
                if (protocol.Name.Equals(newProtocolName, StringComparison.InvariantCultureIgnoreCase))
                {
                    ProtocolHandshakeResult hsresult = await protocol.SwitchTo(info, data);

                    if (!hsresult.Accepted)
                    {
                        info.Close();
                        return;
                    }

                    ITwinoProtocol previous = info.Protocol;
                    info.Protocol = protocol;
                    info.Socket   = hsresult.Socket;

                    if (info.Socket != null)
                    {
                        info.Socket.SetOnConnected();
                    }

                    if (hsresult.Response != null)
                    {
                        await info.GetStream().WriteAsync(hsresult.Response);
                    }

                    if (info.Socket != null)
                    {
                        info.Socket.SetOnProtocolSwitched(previous, info.Protocol);
                    }

                    await protocol.HandleConnection(info, hsresult);

                    return;
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Reads first Hello message from client
        /// </summary>
        private async Task <bool> ProcessFirstMessage(HorseMessage message, IConnectionInfo info, ProtocolHandshakeResult handshakeResult)
        {
            if (message.Type != MessageType.Server || message.ContentType != KnownContentTypes.Hello)
            {
                return(false);
            }

            ConnectionData connectionData = new ConnectionData();

            message.Content.Position = 0;
            await connectionData.ReadFromStream(message.Content);

            HorseServerSocket socket = await _handler.Connected(_server, info, connectionData);

            if (socket == null)
            {
                info.Close();
                return(false);
            }

            info.State             = ConnectionStates.Pipe;
            handshakeResult.Socket = socket;
            _server.HeartbeatManager.Add(socket);

            socket.SetCleanupAction(s =>
            {
                _server.HeartbeatManager.Remove(socket);
                _handler.Disconnected(_server, s);
            });

            return(true);
        }
        /// <summary>
        /// After the client connection request is accepted.
        /// Completes first operations for the client
        /// such as firewall authority, SSL authentication, WebSocket handshaking
        /// </summary>
        private async Task AcceptClient(TcpClient tcp)
        {
            ConnectionInfo info = null;

            try
            {
                if (_listener == null)
                {
                    return;
                }

                info = new ConnectionInfo(tcp, _listener)
                {
                    State    = ConnectionStates.Pending,
                    MaxAlive = DateTime.UtcNow + TimeSpan.FromSeconds(_server.Options.RequestTimeout)
                };

                _listener.KeepAliveManager.Add(info);

                //ssl handshaking
                if (_listener.Options.SslEnabled)
                {
                    SslStream sslStream = _listener.Options.BypassSslValidation
                                              ? new SslStream(tcp.GetStream(), true, (a, b, c, d) => true)
                                              : new SslStream(tcp.GetStream(), true);

                    info.SslStream = sslStream;
                    SslProtocols protocol = GetProtocol(_listener);
                    info.IsSsl = true;
                    await sslStream.AuthenticateAsServerAsync(_listener.Certificate, false, protocol, false);
                }

                //read one byte and recognize the protocol
                byte[] pbytes = new byte[8];
                int    rc     = await info.GetStream().ReadAsync(pbytes, 0, pbytes.Length);

                if (rc == 0)
                {
                    info.Close();
                    return;
                }

                //find matched protocol with client protocol
                foreach (IHorseProtocol protocol in _server.Protocols)
                {
                    ProtocolHandshakeResult hsresult = await protocol.Handshake(info, pbytes);

                    //matched
                    if (hsresult.Accepted)
                    {
                        hsresult.PreviouslyRead = pbytes;
                        info.Protocol           = protocol;
                        info.Socket             = hsresult.Socket;

                        if (info.Socket != null)
                        {
                            info.Socket.SetOnConnected();
                        }

                        //if protocol required to send protocol message from server to client, send it
                        if (hsresult.Response != null)
                        {
                            await info.GetStream().WriteAsync(hsresult.Response);
                        }

                        //handle connection events for the connection
                        await protocol.HandleConnection(info, hsresult);

                        return;
                    }
                }

                info.Close();
            }
            catch (Exception ex)
            {
                info?.Close();
                _server.RaiseException(ex);
            }
        }