Exemplo n.º 1
0
 public async Task DisposeAndRemoveAsync(DefaultConnectionContext connection)
 {
     try
     {
         await connection.DisposeAsync();
     }
     catch (IOException ex)
     {
         _logger.ConnectionReset(connection.ConnectionId, ex);
     }
     catch (WebSocketException ex) when(ex.InnerException is IOException)
     {
         _logger.ConnectionReset(connection.ConnectionId, ex);
     }
     catch (Exception ex)
     {
         _logger.FailedDispose(connection.ConnectionId, ex);
     }
     finally
     {
         // Remove it from the list after disposal so that's it's easy to see
         // connections that might be in a hung state via the connections list
         RemoveConnection(connection.ConnectionId);
     }
 }
Exemplo n.º 2
0
 private void EnsureConnectionStateInternal(DefaultConnectionContext connection, HttpSocketOptions options)
 {
     // If the connection doesn't have a pipe yet then create one, we lazily create the pipe to save on allocations until the client actually connects
     if (connection.Transport == null)
     {
         var transportPipeOptions = new PipeOptions(pauseWriterThreshold: options.TransportMaxBufferSize, resumeWriterThreshold: options.TransportMaxBufferSize / 2, readerScheduler: PipeScheduler.ThreadPool, useSynchronizationContext: false);
         var appPipeOptions       = new PipeOptions(pauseWriterThreshold: options.ApplicationMaxBufferSize, resumeWriterThreshold: options.ApplicationMaxBufferSize / 2, readerScheduler: PipeScheduler.ThreadPool, useSynchronizationContext: false);
         var pair = DuplexPipe.CreateConnectionPair(transportPipeOptions, appPipeOptions);
         connection.Transport   = pair.Application;
         connection.Application = pair.Transport;
     }
 }
Exemplo n.º 3
0
        private async Task <bool> EnsureConnectionStateAsync(DefaultConnectionContext connection, HttpContext context, TransportType transportType, TransportType supportedTransports, ConnectionLogScope logScope, HttpSocketOptions options)
        {
            if ((supportedTransports & transportType) == 0)
            {
                context.Response.ContentType = "text/plain";
                context.Response.StatusCode  = StatusCodes.Status404NotFound;
                _logger.TransportNotSupported(transportType);
                await context.Response.WriteAsync($"{transportType} transport not supported by this end point type");

                return(false);
            }

            // Set the IHttpConnectionFeature now that we can access it.
            connection.Features.Set(context.Features.Get <IHttpConnectionFeature>());

            var transport = (TransportType?)connection.Metadata[ConnectionMetadataNames.Transport];

            if (transport == null)
            {
                connection.Metadata[ConnectionMetadataNames.Transport] = transportType;
            }
            else if (transport != transportType)
            {
                context.Response.ContentType = "text/plain";
                context.Response.StatusCode  = StatusCodes.Status400BadRequest;
                _logger.CannotChangeTransport(transport.Value, transportType);
                await context.Response.WriteAsync("Cannot change transports mid-connection");

                return(false);
            }

            // Configure transport-specific features.
            if (transportType == TransportType.LongPolling)
            {
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new ConnectionInherentKeepAliveFeature(options.LongPolling.PollTimeout));
            }

            // Setup the connection state from the http context
            connection.User = context.User;
            connection.SetHttpContext(context);

            // this is the default setting which should be overwritten by transports that have different capabilities (e.g. SSE)
            connection.TransportCapabilities = TransferMode.Binary | TransferMode.Text;

            // Set the Connection ID on the logging scope so that logs from now on will have the
            // Connection ID metadata set.
            logScope.ConnectionId = connection.ConnectionId;

            return(true);
        }
Exemplo n.º 4
0
        public DefaultConnectionContext CreateConnection(PipeOptions transportPipeOptions, PipeOptions appPipeOptions)
        {
            var id = MakeNewConnectionId();

            _logger.CreatedNewConnection(id);
            var connectionTimer = SocketEventSource.Log.ConnectionStart(id);
            var pair            = DuplexPipe.CreateConnectionPair(transportPipeOptions, appPipeOptions);

            var connection = new DefaultConnectionContext(id, pair.Application, pair.Transport);

            connection.ConnectionTimer = connectionTimer;

            _connections.TryAdd(id, connection);
            return(connection);
        }
Exemplo n.º 5
0
        private async Task DoPersistentConnection(ConnectionDelegate ConnectionDelegate,
                                                  IHttpTransport transport,
                                                  HttpContext context,
                                                  DefaultConnectionContext connection)
        {
            try
            {
                await connection.Lock.WaitAsync();

                if (connection.Status == DefaultConnectionContext.ConnectionStatus.Disposed)
                {
                    Log.ConnectionDisposed(_logger, connection.ConnectionId);

                    // Connection was disposed
                    context.Response.StatusCode = StatusCodes.Status404NotFound;
                    return;
                }

                // There's already an active request
                if (connection.Status == DefaultConnectionContext.ConnectionStatus.Active)
                {
                    Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, connection.GetHttpContext().TraceIdentifier);

                    // Reject the request with a 409 conflict
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    return;
                }

                // Mark the connection as active
                connection.Status = DefaultConnectionContext.ConnectionStatus.Active;

                // Call into the end point passing the connection
                connection.ApplicationTask = ExecuteApplication(ConnectionDelegate, connection);

                // Start the transport
                connection.TransportTask = transport.ProcessRequestAsync(context, context.RequestAborted);
            }
            finally
            {
                connection.Lock.Release();
            }

            // Wait for any of them to end
            await Task.WhenAny(connection.ApplicationTask, connection.TransportTask);

            await _manager.DisposeAndRemoveAsync(connection);
        }
Exemplo n.º 6
0
        public DefaultConnectionContext CreateConnection()
        {
            var id = MakeNewConnectionId();

            _logger.CreatedNewConnection(id);

            var transportToApplication = Channel.CreateUnbounded <byte[]>();
            var applicationToTransport = Channel.CreateUnbounded <byte[]>();

            var transportSide   = ChannelConnection.Create <byte[]>(applicationToTransport, transportToApplication);
            var applicationSide = ChannelConnection.Create <byte[]>(transportToApplication, applicationToTransport);

            var connection = new DefaultConnectionContext(id, applicationSide, transportSide);

            _connections.TryAdd(id, connection);
            return(connection);
        }
Exemplo n.º 7
0
        private async Task <bool> EnsureConnectionStateAsync(DefaultConnectionContext connection, HttpContext context, TransportType transportType, TransportType supportedTransports, ConnectionLogScope logScope)
        {
            if ((supportedTransports & transportType) == 0)
            {
                context.Response.StatusCode = StatusCodes.Status404NotFound;
                _logger.TransportNotSupported(connection.ConnectionId, transportType);
                await context.Response.WriteAsync($"{transportType} transport not supported by this end point type");

                return(false);
            }

            var transport = (TransportType?)connection.Metadata[ConnectionMetadataNames.Transport];

            if (transport == null)
            {
                connection.Metadata[ConnectionMetadataNames.Transport] = transportType;
            }
            else if (transport != transportType)
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                _logger.CannotChangeTransport(connection.ConnectionId, transport.Value, transportType);
                await context.Response.WriteAsync("Cannot change transports mid-connection");

                return(false);
            }

            // Setup the connection state from the http context
            connection.User = context.User;
            connection.SetHttpContext(context);

            // this is the default setting which should be overwritten by transports that have different capabilities (e.g. SSE)
            connection.TransportCapabilities = TransferMode.Binary | TransferMode.Text;

            // Set the Connection ID on the logging scope so that logs from now on will have the
            // Connection ID metadata set.
            logScope.ConnectionId = connection.ConnectionId;

            return(true);
        }
        public void GlobalSetup()
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSignalRCore();

            var provider = serviceCollection.BuildServiceProvider();

            var serviceScopeFactory = provider.GetService <IServiceScopeFactory>();

            _dispatcher = new DefaultHubDispatcher <TestHub>(
                serviceScopeFactory,
                new HubContext <TestHub>(new DefaultHubLifetimeManager <TestHub>()),
                new Logger <DefaultHubDispatcher <TestHub> >(NullLoggerFactory.Instance));

            var options    = new PipeOptions();
            var pair       = DuplexPipe.CreateConnectionPair(options, options);
            var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Transport, pair.Application);

            _connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);

            _connectionContext.Protocol = new FakeHubProtocol();
        }
Exemplo n.º 9
0
 public bool TryGetConnection(string id, out DefaultConnectionContext connection)
 {
     return(_connections.TryGetValue(id, out connection));
 }