Ejemplo n.º 1
0
        private async Task ListenClient <TContext>(ConnectedSocket connectedSocket, IHttpApplication <TContext> application)
        {
            try
            {
                var client        = connectedSocket.Socket;
                var networkStream = new NetworkStream(client, false);
                while (true)
                {
                    using (var disposables = new     CompositeDisposable())
                    {
                        var stream = new TCPStream(networkStream)
                        {
                            ArrayPool      = Options.ArrayPool,
                            Cancellation   = _Stopped.Token,
                            MaxArrayLength = Options.MaxBytesArrayLength,
                            MaxMessageSize = Options.MaxMessageSize
                        };
                        disposables.Children.Add(stream);
                        var idleTimeout = new CancellationTokenSource();
                        idleTimeout.CancelAfter(Options.IdleTimeout);
                        disposables.Children.Add(idleTimeout);
                        var linked = CancellationTokenSource.CreateLinkedTokenSource(stream.Cancellation, idleTimeout.Token);
                        disposables.Children.Add(linked);
                        stream.Cancellation = linked.Token;
                        var request = await TCPRequest.Parse(stream, Options.IncludeHeaders).ConfigureAwait(false);

                        disposables.Children.Add(connectedSocket.MarkProcessingRequest());

                        var context = (HostingApplication.Context)(object) application.CreateContext(Features);

                        context.HttpContext = new TCPContext(request, Features, new TCPConnectionInfo(client, _ListeningEndPoint));
                        await application.ProcessRequestAsync((TContext)(object)context);

                        CancellationTokenSource sendTimeout = new CancellationTokenSource();
                        sendTimeout.CancelAfter(Options.SendTimeout);
                        disposables.Children.Add(sendTimeout);
                        linked = CancellationTokenSource.CreateLinkedTokenSource(stream.Cancellation, sendTimeout.Token);
                        disposables.Children.Add(linked);
                        stream.Cancellation = linked.Token;
                        var response = (TCPResponse)context.HttpContext.Response;
                        try
                        {
                            response.OnStarting();
                            await stream.WriteVarIntAsync((ulong)response.StatusCode).ConfigureAwait(false);

                            if (Options.IncludeHeaders)
                            {
                                await stream.WriteVarIntAsync((ulong)response.Headers.Count).ConfigureAwait(false);

                                foreach (var header in response.Headers)
                                {
                                    await stream.WriteStringAsync(header.Key).ConfigureAwait(false);

                                    await stream.WriteStringAsync(header.Value).ConfigureAwait(false);
                                }
                            }

                            await stream.WriteVarIntAsync((ulong)response.Body.Length);

                            response.Body.Position = 0;
                            await response.Body.CopyToAsync(networkStream, 81920, stream.Cancellation).ConfigureAwait(false);

                            await networkStream.FlushAsync(stream.Cancellation).ConfigureAwait(false);
                        }
                        finally
                        {
                            response.OnCompleted();
                            connectedSocket.LastReceivedMessage = DateTimeOffset.UtcNow;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                if (!_Stopped.IsCancellationRequested)
                {
                    throw;
                }
            }
            finally
            {
                DisconnectClient(connectedSocket);
            }
        }
Ejemplo n.º 2
0
        private async Task ListenClient <TContext>(ConnectedSocket connectedSocket, IHttpApplication <TContext> application)
        {
            bool exceptionHandled = false;
            CancellationTokenSource idleTimeout = null;
            CancellationTokenSource sendTimeout = null;

            try
            {
                var client        = connectedSocket.Socket;
                var networkStream = new NetworkStream(client, false);
                while (true)
                {
                    using (var disposables = new CompositeDisposable())
                    {
                        var stream = new TCPStream(networkStream)
                        {
                            ArrayPool      = Options.ArrayPool,
                            Cancellation   = _Stopped.Token,
                            MaxArrayLength = Options.MaxBytesArrayLength,
                            MaxMessageSize = Options.MaxMessageSize
                        };
                        disposables.Children.Add(stream);
                        idleTimeout = new CancellationTokenSource();
                        idleTimeout.CancelAfter(Options.IdleTimeout);
                        disposables.Children.Add(idleTimeout);
                        var linked = CancellationTokenSource.CreateLinkedTokenSource(stream.Cancellation, idleTimeout.Token);
                        disposables.Children.Add(linked);
                        stream.Cancellation = linked.Token;
                        TCPRequest request = null;
                        try
                        {
                            request = await TCPRequest.Parse(stream, Options.IncludeHeaders).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            _Logger.LogWarning(new EventId(), ex, $"Error while parsing the request of {EndpointString(connectedSocket)}");
                            exceptionHandled = true;
                            throw;
                        }

                        disposables.Children.Add(connectedSocket.MarkProcessingRequest());

                        var context = (HostingApplication.Context)(object) application.CreateContext(Features);

                        context.HttpContext = new TCPContext(request, Features, new TCPConnectionInfo(client, _ListeningEndPoint));
                        try
                        {
                            await application.ProcessRequestAsync((TContext)(object)context);
                        }
                        catch (Exception ex)
                        {
                            _Logger.LogError(new EventId(), ex, "Error during request processing");
                            exceptionHandled = true;
                            throw;
                        }

                        sendTimeout = new CancellationTokenSource();
                        sendTimeout.CancelAfter(Options.SendTimeout);
                        disposables.Children.Add(sendTimeout);
                        linked = CancellationTokenSource.CreateLinkedTokenSource(stream.Cancellation, sendTimeout.Token);
                        disposables.Children.Add(linked);
                        stream.Cancellation = linked.Token;
                        var response = (TCPResponse)context.HttpContext.Response;
                        try
                        {
                            response.OnStarting();
                            await stream.WriteVarIntAsync((ulong)response.StatusCode).ConfigureAwait(false);

                            if (Options.IncludeHeaders)
                            {
                                await stream.WriteVarIntAsync((ulong)response.Headers.Count).ConfigureAwait(false);

                                foreach (var header in response.Headers)
                                {
                                    await stream.WriteStringAsync(header.Key).ConfigureAwait(false);

                                    await stream.WriteStringAsync(header.Value).ConfigureAwait(false);
                                }
                            }

                            await stream.WriteVarIntAsync((ulong)response.Body.Length);

                            response.Body.Position = 0;
                            await response.Body.CopyToAsync(networkStream, 81920, stream.Cancellation).ConfigureAwait(false);

                            await networkStream.FlushAsync(stream.Cancellation).ConfigureAwait(false);
                        }
                        finally
                        {
                            response.OnCompleted();
                            connectedSocket.LastReceivedMessage = DateTimeOffset.UtcNow;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                if (connectedSocket.Socket.Connected)
                {
                    if (_Stopped.Token.IsCancellationRequested)
                    {
                        _Logger.LogInformation($"Connection to {EndpointString(connectedSocket)} stopped");
                    }
                    else if (idleTimeout != null && idleTimeout.IsCancellationRequested)
                    {
                        _Logger.LogWarning($"Connection idle detected, kicking {EndpointString(connectedSocket)}");
                    }
                    else if (sendTimeout != null && sendTimeout.IsCancellationRequested)
                    {
                        _Logger.LogWarning($"Send timeout detected, kicking {EndpointString(connectedSocket)}");
                    }
                }
            }
            catch (Exception ex)
            {
                if (connectedSocket.Socket.Connected && !exceptionHandled)
                {
                    _Logger.LogCritical(new EventId(), ex, "TCPServer internal error");
                }
            }
            finally
            {
                if (!connectedSocket.Socket.Connected)
                {
                    _Logger.LogInformation($"{EndpointString(connectedSocket)} dropped connection");
                }
                DisconnectClient(connectedSocket);
            }
        }