상속: TcpSessionBase
예제 #1
0
        void TrackSession(HttpSession session)
        {
            sessionTable[session.Id] = session;
            var sessionCount = sessionTable.Count;

            int currentMax;
            while ((currentMax = maxConnectedSessions) < sessionCount)
            {
                if (Interlocked.CompareExchange(ref maxConnectedSessions, sessionCount, currentMax) != currentMax)
                {
                    continue;
                }
            }
        }
예제 #2
0
        bool HandleWebsocketUpgrade(HttpSession session,
                                    int routeTableIndex,
                                    int endpointIndex,
                                    WebSocketUpgradeResponse response,
                                    out int responseBytesWritten)
        {
            responseBytesWritten = session.WriteWebSocketUpgradeResponse(response);

            var acceptUpgradeResponse = response as WebSocketUpgradeResponse.AcceptUpgradeResponse;
            if (acceptUpgradeResponse == null)
            {
                return false;
            }
            else
            {
                long id = Interlocked.Increment(ref acceptedWebSocketSessions);
                var webSocketSession = new WebSocketSession(id,
                                                            session.TcpClient,
                                                            session.Stream,
                                                            bytesReceived => router.Metrics.CountRequestBytesIn(routeTableIndex, endpointIndex, bytesReceived),
                                                            bytesSent => router.Metrics.CountResponseBytesOut(routeTableIndex, endpointIndex, bytesSent),
                                                            () => UntrackWebSocketSession(id));
                TrackWebSocketSession(webSocketSession);

                try
                {
                    acceptUpgradeResponse.OnAccepted(webSocketSession); //TODO: Task.Run this?
                    return true;
                }
                catch (Exception e)
                {
                    UntrackWebSocketSession(id);
                    logger.Error("Error calling WebSocketUpgradeResponse.OnAccepted callback - {0}", e.ToString());
                    return false;
                }
            }
        }
예제 #3
0
        async Task<int> AcceptWebSocketUpgrade(HttpSession session,
                                               int routeTableIndex,
                                               int endpointIndex,
                                               WebSocketUpgradeResponse.AcceptUpgradeResponse response)
        {
            var bytesWritten = await response.WriteToAsync(session.Stream, 0, sessionReadTimeout).ConfigureAwait(false);

            var id = Interlocked.Increment(ref acceptedWebSocketSessions);
            var webSocketSession = new WebSocketSession(id,
                                                        session.TcpClient,
                                                        session.Stream,
                                                        bytesReceived => router.Metrics.CountRequestBytesIn(routeTableIndex, endpointIndex, bytesReceived),
                                                        bytesSent => router.Metrics.CountResponseBytesOut(routeTableIndex, endpointIndex, bytesSent),
                                                        () => UntrackWebSocketSession(id),
                                                        sessionReadBufferSize,
                                                        (int)sessionReadTimeout.TotalMilliseconds,
                                                        (int)sessionWriteTimeout.TotalMilliseconds);
            TrackWebSocketSession(webSocketSession);

            try
            {
                response.OnAccepted(webSocketSession); //TODO: Task.Run this?
                return bytesWritten;
            }
            catch (Exception)
            {
                UntrackWebSocketSession(id);
                throw;
            }
        }
예제 #4
0
        async Task HandleSession(HttpSession session)
        {
            var closeSessionOnReturn = true;

            try
            {
                var continueSession = true;

                while (continueSession && !session.IsDisconnected())
                {
                    try
                    {
                        TrackSessionRead(session.Id);
                        if (await session.ReadToBufferAsync().ConfigureAwait(false) == 0) // 0 => client clean disconnect
                        {
                            break;
                        }
                    }
                    finally
                    {
                        UntrackSessionRead(session.Id);
                    }

                    int requestBytesParsed, responseBytesWritten;
                    HttpRequest request;
                    while (continueSession && session.TryParseNextRequestFromBuffer(out requestBytesParsed, out request))
                    {
                        Router.HandleResult result = await router.HandleRequest(request, DateTime.UtcNow).ConfigureAwait(false);
                        HttpResponse response = result.HttpResponse;

                        var webSocketUpgradeResponse = response as WebSocketUpgradeResponse;
                        if (webSocketUpgradeResponse == null)
                        {
                            responseBytesWritten = session.WriteResponse(response, request.IsKeepAlive);
                            continueSession = request.IsKeepAlive && session.KeepAlivesRemaining > 0;
                        }
                        else
                        {
                            var isUpgraded = HandleWebsocketUpgrade(session,
                                                                    result.MatchedRouteTableIndex,
                                                                    result.MatchedEndpointIndex,
                                                                    webSocketUpgradeResponse,
                                                                    out responseBytesWritten);
                            continueSession = false;
                            closeSessionOnReturn = !isUpgraded;
                        }

                        if (result.MatchedRouteTableIndex >= 0 && result.MatchedEndpointIndex >= 0)
                        {
                            router.Metrics.CountBytes(result.MatchedRouteTableIndex, result.MatchedEndpointIndex, requestBytesParsed, responseBytesWritten);
                        }
                    }
                }
            }
            catch (RequestException e)
            {
                logger.Warn("Error parsing or bad request - {0}", e.Message);
            }
            catch (SessionStreamException)
            {
                // forced disconnect, socket errors
            }
            catch (Exception e)
            {
                //TODO: count session-fatal errors (not captured as route table 500s)
                logger.Fatal("Internal server error handling session - {0}", e.ToString());
            }
            finally
            {
                UntrackSession(session.Id);
                if (closeSessionOnReturn)
                {
                    session.CloseQuiety();
                }
            }
        }
예제 #5
0
        async Task HandleSession(HttpSession session)
        {
            var closeSessionOnReturn = true;

            try
            {
                var continueRequestLoop = true;

                while (continueRequestLoop && !session.IsDisconnected()) // request loop
                {
                    try
                    {
                        TrackSessionRead(session.Id);
                        if (await session.ReadToBufferAsync().ConfigureAwait(false) == 0) // 0 => client clean disconnect
                        {
                            break;
                        }
                    }
                    finally
                    {
                        UntrackSessionRead(session.Id);
                    }

                    int requestBytesParsed, responseBytesWritten;
                    HttpRequest request;

                    while (continueRequestLoop && session.TryParseNextRequestFromBuffer(out requestBytesParsed, out request))
                    {
                        Router.HandleResult result = await router.HandleRequest(request, DateTime.UtcNow).ConfigureAwait(false);
                        HttpResponse response = result.HttpResponse;

                        if (response is WebSocketUpgradeResponse)
                        {
                            continueRequestLoop = false;

                            var acceptUpgrade = response as WebSocketUpgradeResponse.AcceptUpgradeResponse;
                            if (acceptUpgrade == null)
                            {
                                var rejectUpgrade = (WebSocketUpgradeResponse.RejectUpgradeResponse)response;
                                responseBytesWritten = await rejectUpgrade.WriteToAsync(session.Stream, 0, sessionReadTimeout).ConfigureAwait(false);
                            }
                            else
                            {
                                responseBytesWritten = await AcceptWebSocketUpgrade(session, result.MatchedRouteTableIndex, result.MatchedEndpointIndex, acceptUpgrade).ConfigureAwait(false);
                                closeSessionOnReturn = false;
                            }
                        }
                        else
                        {
                            responseBytesWritten = await response.WriteToAsync(session.Stream, request.IsKeepAlive ? session.KeepAlivesRemaining : 0, sessionReadTimeout).ConfigureAwait(false);
                            continueRequestLoop = request.IsKeepAlive && session.KeepAlivesRemaining > 0;
                        }

                        if (result.MatchedRouteTableIndex >= 0 && result.MatchedEndpointIndex >= 0)
                        {
                            router.Metrics.CountBytes(result.MatchedRouteTableIndex, result.MatchedEndpointIndex, requestBytesParsed, responseBytesWritten);
                        }
                    }
                }
            }
            catch (RequestException e)
            {
                sessionExceptionCounters.Count(e.GetType());
                logger.Warn("Error parsing or bad request - {0}", e.Message);
            }
            catch (SessionStreamException e)
            {
                sessionExceptionCounters.Count(e.GetType());
            }
            catch (Exception e)
            {
                sessionExceptionCounters.Count(e.GetType());
                logger.Fatal("Error handling session - {0}", e.ToString());
            }
            finally
            {
                UntrackSession(session.Id);
                if (closeSessionOnReturn)
                {
                    session.CloseQuiety();
                }
            }
        }