/// <summary>
        /// Process the HTTP message
        /// </summary>
        private async Task <HandleStatus> ProcessMessage(IConnectionInfo info, HttpWriter writer, HttpMessage message, int contentLength)
        {
            if (message.Request == null)
            {
                return(HandleStatus.Close);
            }

            message.Request.ContentLength = contentLength;
            message.Response.Request      = message.Request;

            if (message.Response.StatusCode > 0)
            {
                await writer.Write(message.Response);

                return(HandleStatus.Close);
            }

            if (!string.IsNullOrEmpty(message.Request.Upgrade))
            {
                ConnectionData data = new ConnectionData();
                data.Path   = message.Request.Path;
                data.Method = message.Request.Method;
                data.SetProperties(message.Request.Headers);

                if (!string.IsNullOrEmpty(message.Request.QueryStringData))
                {
                    data.Path += "?" + message.Request.QueryStringData;
                }

                await _server.SwitchProtocol(info, message.Request.Upgrade, data);

                return(HandleStatus.ExitWithoutClosing);
            }

            HttpReader.ReadContent(message.Request);

            //if user makes a mistake in received method, we should not interrupt connection handling
            try
            {
                await _handler.Received(_server, info, null, message);
            }
            catch (Exception ex)
            {
                if (_server.Logger != null)
                {
                    _server.Logger.LogException("Unhandled Exception", ex);
                }
            }

            await writer.Write(message.Response);

            //stay alive, if keep alive active and response has stream
            bool keep = Options.HttpConnectionTimeMax > 0 && message.Response.HasStream();

            return(keep ? HandleStatus.ReadAgain : HandleStatus.Close);
        }
        /// <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();
            }
        }