public async Task OnConnectionAsync(ConnectionContext connectionContext)
        {
            // We need the transport feature so that we can cancel the output reader that the transport is using
            // This is a bit of a hack but it preserves the existing semantics
            var memoryPoolFeature = connectionContext.Features.Get <IMemoryPoolFeature>();

            var httpConnectionId = Interlocked.Increment(ref _lastHttpConnectionId);

            var httpConnectionContext = new HttpConnectionContext
            {
                ConnectionId       = connectionContext.ConnectionId,
                ConnectionContext  = connectionContext,
                HttpConnectionId   = httpConnectionId,
                Protocols          = _protocols,
                ServiceContext     = _serviceContext,
                ConnectionFeatures = connectionContext.Features,
                MemoryPool         = memoryPoolFeature.MemoryPool,
                ConnectionAdapters = _connectionAdapters,
                Transport          = connectionContext.Transport
            };

            var connectionFeature = connectionContext.Features.Get <IHttpConnectionFeature>();
            var lifetimeFeature   = connectionContext.Features.Get <IConnectionLifetimeFeature>();

            if (connectionFeature != null)
            {
                if (connectionFeature.LocalIpAddress != null)
                {
                    httpConnectionContext.LocalEndPoint = new IPEndPoint(connectionFeature.LocalIpAddress, connectionFeature.LocalPort);
                }

                if (connectionFeature.RemoteIpAddress != null)
                {
                    httpConnectionContext.RemoteEndPoint = new IPEndPoint(connectionFeature.RemoteIpAddress, connectionFeature.RemotePort);
                }
            }

            var connection = new HttpConnection(httpConnectionContext);

            _serviceContext.ConnectionManager.AddConnection(httpConnectionId, connection);

            try
            {
                var processingTask = connection.ProcessRequestsAsync(_application);

                connectionContext.Transport.Input.OnWriterCompleted(
                    (_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(),
                    connection);

                connectionContext.Transport.Output.OnReaderCompleted(
                    (_, state) => ((HttpConnection)state).OnInputOrOutputCompleted(),
                    connection);

                await CancellationTokenAsTask(lifetimeFeature.ConnectionClosed);

                connection.OnConnectionClosed();

                await processingTask;
            }
            finally
            {
                _serviceContext.ConnectionManager.RemoveConnection(httpConnectionId);
            }
        }
Ejemplo n.º 2
0
        public Task OnConnectionAsync(ConnectionContext connectionContext)
        {
            // We need the transport feature so that we can cancel the output reader that the transport is using
            // This is a bit of a hack but it preserves the existing semantics
            var transportFeature = connectionContext.Features.Get <IConnectionTransportFeature>();

            var httpConnectionId = Interlocked.Increment(ref _lastHttpConnectionId);

            var httpConnectionContext = new HttpConnectionContext
            {
                ConnectionId       = connectionContext.ConnectionId,
                HttpConnectionId   = httpConnectionId,
                Protocols          = _protocols,
                ServiceContext     = _serviceContext,
                ConnectionFeatures = connectionContext.Features,
                MemoryPool         = connectionContext.MemoryPool,
                ConnectionAdapters = _connectionAdapters,
                Transport          = connectionContext.Transport,
                Application        = transportFeature.Application
            };

            var connectionFeature = connectionContext.Features.Get <IHttpConnectionFeature>();

            if (connectionFeature != null)
            {
                if (connectionFeature.LocalIpAddress != null)
                {
                    httpConnectionContext.LocalEndPoint = new IPEndPoint(connectionFeature.LocalIpAddress, connectionFeature.LocalPort);
                }

                if (connectionFeature.RemoteIpAddress != null)
                {
                    httpConnectionContext.RemoteEndPoint = new IPEndPoint(connectionFeature.RemoteIpAddress, connectionFeature.RemotePort);
                }
            }

            var connection = new HttpConnection(httpConnectionContext);

            var processingTask = connection.StartRequestProcessing(_application);

            var inputTcs  = new TaskCompletionSource <object>();
            var outputTcs = new TaskCompletionSource <object>();

            // The reason we don't fire events directly from these callbacks is because it seems
            // like the transport callbacks root the state object (even after it fires)
            connectionContext.Transport.Input.OnWriterCompleted(_completeTcs, inputTcs);
            connectionContext.Transport.Output.OnReaderCompleted(_completeTcs, outputTcs);

            inputTcs.Task.ContinueWith((task, state) =>
            {
                ((HttpConnection)state).Abort(task.Exception?.InnerException);
            },
                                       connection, TaskContinuationOptions.ExecuteSynchronously);

            outputTcs.Task.ContinueWith((task, state) =>
            {
                ((HttpConnection)state).OnConnectionClosed(task.Exception?.InnerException);
            },
                                        connection, TaskContinuationOptions.ExecuteSynchronously);

            return(processingTask);
        }
Ejemplo n.º 3
0
 public HttpConnection(HttpConnectionContext context)
 {
     _context = context;
 }
 public HttpConnection(HttpConnectionContext context)
 {
     _context     = context;
     _systemClock = _context.ServiceContext.SystemClock;
 }