Exemple #1
0
        void TestNetwork()
        {
            var url = NSUrl.FromString ("http://www.heise.de/");
            var request = NSUrlRequest.FromUrl (url);
            var dlg = new ConnectionDelegate ();

            NSError error;
            NSUrlResponse response;

            NSUrlConnection.SendSynchronousRequest (request, out response, out error);

            Console.WriteLine ("GOT RESPONSE: {0} {1}", response, error);
        }
Exemple #2
0
 public IoTransport(String host, int port, ConnectionDelegate conndel)
 {
     CreateSocket(host, port);
     Sender = new IoSender(this, QUEUE_SIZE, TIMEOUT);
     Receiver = new IoReceiver(Stream, Socket.ReceiveBufferSize * 2, TIMEOUT);
     Assembler assembler = new Assembler();                 
     InputHandler inputHandler = new InputHandler(InputHandler.State.PROTO_HDR);
     Connection = new Connection(assembler, new Disassembler(Sender, 64 * 1024 - 1), conndel);
     // Input handler listen to Receiver events
     Receiver.Received += inputHandler.On_ReceivedBuffer;
     // Assembler listen to inputhandler events       
     inputHandler.ReceivedEvent += assembler.On_ReceivedEvent;            
     // Connection listen to asembler protocol event 
     Receiver.Closed += Connection.On_ReceivedClosed;
     assembler.Closed += Connection.On_ReceivedClosed;
     Receiver.Exception += Connection.On_ReceivedException;            
     inputHandler.ExceptionProcessing += Connection.On_ReceivedException;
     assembler.ReceivedEvent += Connection.On_ReceivedEvent;
  }
        public async Task ExecuteAsync(HttpContext context, HttpConnectionDispatcherOptions options, ConnectionDelegate connectionDelegate)
        {
            // Create the log scope and attempt to pass the Connection ID to it so as many logs as possible contain
            // the Connection ID metadata. If this is the negotiate request then the Connection ID for the scope will
            // be set a little later.
            var logScope = new ConnectionLogScope(GetConnectionId(context));

            using (_logger.BeginScope(logScope))
            {
                if (!await AuthorizeHelper.AuthorizeAsync(context, options.AuthorizationData))
                {
                    return;
                }

                if (HttpMethods.IsPost(context.Request.Method))
                {
                    // POST /{path}
                    await ProcessSend(context, options);
                }
                else if (HttpMethods.IsGet(context.Request.Method))
                {
                    // GET /{path}
                    await ExecuteAsync(context, connectionDelegate, options, logScope);
                }
                else if (HttpMethods.IsDelete(context.Request.Method))
                {
                    // DELETE /{path}
                    await ProcessDeleteAsync(context);
                }
                else
                {
                    context.Response.ContentType = "text/plain";
                    context.Response.StatusCode  = StatusCodes.Status405MethodNotAllowed;
                }
            }
        }
Exemple #4
0
 public EndPointBinding(EndPoint endPoint, ConnectionDelegate application, IConnectionListenerFactory connectionListenerFactory)
 {
     EndPoint     = endPoint;
     _application = application;
     ConnectionListenerFactory = connectionListenerFactory;
 }
 public ConnectionDispatcher(ServiceContext serviceContext, ConnectionDelegate connectionDelegate)
 {
     _serviceContext     = serviceContext;
     _connectionDelegate = connectionDelegate;
 }
        private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connectionDelegate, HttpConnectionDispatcherOptions options, ConnectionLogScope logScope)
        {
            var supportedTransports = options.Transports;

            // Server sent events transport
            // GET /{path}
            // Accept: text/event-stream
            var headers = context.Request.GetTypedHeaders();

            if (headers.Accept?.Contains(new Net.Http.Headers.MediaTypeHeaderValue("text/event-stream")) == true)
            {
                // Connection must already exist
                var connection = await GetConnectionAsync(context);

                if (connection == null)
                {
                    // No such connection, GetConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.ServerSentEvents, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                Log.EstablishedConnection(_logger);

                // ServerSentEvents is a text protocol only
                connection.SupportedFormats = TransferFormat.Text;

                // We only need to provide the Input channel since writing to the application is handled through /send.
                var sse = new ServerSentEventsServerTransport(connection.Application.Input, connection.ConnectionId, connection, _loggerFactory);

                await DoPersistentConnection(connectionDelegate, sse, context, connection);
            }
            else if (context.WebSockets.IsWebSocketRequest)
            {
                // Connection can be established lazily
                var connection = await GetOrCreateConnectionAsync(context, options);

                if (connection == null)
                {
                    // No such connection, GetOrCreateConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.WebSockets, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                Log.EstablishedConnection(_logger);

                // Allow the reads to be canceled
                connection.Cancellation = new CancellationTokenSource();

                var ws = new WebSocketsServerTransport(options.WebSockets, connection.Application, connection, _loggerFactory);

                await DoPersistentConnection(connectionDelegate, ws, context, connection);
            }
            else
            {
                // GET /{path} maps to long polling

                // Connection must already exist
                var connection = await GetConnectionAsync(context);

                if (connection == null)
                {
                    // No such connection, GetConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.LongPolling, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                if (!await connection.CancelPreviousPoll(context))
                {
                    // Connection closed. It's already set the response status code.
                    return;
                }

                // Create a new Tcs every poll to keep track of the poll finishing, so we can properly wait on previous polls
                var currentRequestTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

                if (!connection.TryActivateLongPollingConnection(
                        connectionDelegate, context, options.LongPolling.PollTimeout,
                        currentRequestTcs.Task, _loggerFactory, _logger))
                {
                    return;
                }

                var resultTask = await Task.WhenAny(connection.ApplicationTask, connection.TransportTask);

                try
                {
                    // If the application ended before the transport task then we potentially need to end the connection
                    if (resultTask == connection.ApplicationTask)
                    {
                        // Complete the transport (notifying it of the application error if there is one)
                        connection.Transport.Output.Complete(connection.ApplicationTask.Exception);

                        // Wait for the transport to run
                        // Ignore exceptions, it has been logged if there is one and the application has finished
                        // So there is no one to give the exception to
                        await connection.TransportTask.NoThrow();

                        // If the status code is a 204 it means the connection is done
                        if (context.Response.StatusCode == StatusCodes.Status204NoContent)
                        {
                            // Cancel current request to release any waiting poll and let dispose acquire the lock
                            currentRequestTcs.TrySetCanceled();

                            // We should be able to safely dispose because there's no more data being written
                            // We don't need to wait for close here since we've already waited for both sides
                            await _manager.DisposeAndRemoveAsync(connection, closeGracefully : false);
                        }
                        else
                        {
                            // Only allow repoll if we aren't removing the connection.
                            connection.MarkInactive();
                        }
                    }
                    else if (resultTask.IsFaulted || resultTask.IsCanceled)
                    {
                        // Cancel current request to release any waiting poll and let dispose acquire the lock
                        currentRequestTcs.TrySetCanceled();
                        // We should be able to safely dispose because there's no more data being written
                        // We don't need to wait for close here since we've already waited for both sides
                        await _manager.DisposeAndRemoveAsync(connection, closeGracefully : false);
                    }
                    else
                    {
                        // Only allow repoll if we aren't removing the connection.
                        connection.MarkInactive();
                    }
                }
                finally
                {
                    // Artificial task queue
                    // This will cause incoming polls to wait until the previous poll has finished updating internal state info
                    currentRequestTcs.TrySetResult();
                }
            }
        }
        public async Task <IServiceHubContext> CreateHubContextAsync(string hubName, ILoggerFactory loggerFactory = null, CancellationToken cancellationToken = default)
        {
            loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
            switch (_serviceManagerOptions.ServiceTransportType)
            {
            case ServiceTransportType.Persistent:
            {
                var connectionFactory                 = new ManagementConnectionFactory(_productInfo, new ConnectionFactory(_serverNameProvider, loggerFactory));
                var serviceProtocol                   = new ServiceProtocol();
                var clientConnectionManager           = new ClientConnectionManager();
                var clientConnectionFactory           = new ClientConnectionFactory();
                ConnectionDelegate connectionDelegate = connectionContext => Task.CompletedTask;
                var serviceConnectionFactory          = new ServiceConnectionFactory(
                    serviceProtocol,
                    clientConnectionManager,
                    connectionFactory,
                    loggerFactory,
                    connectionDelegate,
                    clientConnectionFactory,
                    new DefaultServerNameProvider()
                    );
                var weakConnectionContainer = new WeakServiceConnectionContainer(
                    serviceConnectionFactory,
                    _serviceManagerOptions.ConnectionCount,
                    new HubServiceEndpoint(hubName, _endpointProvider, _endpoint),
                    loggerFactory?.CreateLogger(nameof(WeakServiceConnectionContainer)) ?? NullLogger.Instance);

                var serviceCollection = new ServiceCollection();
                serviceCollection.AddSignalRCore();
                serviceCollection.AddSingleton <IConfigureOptions <HubOptions>, ManagementHubOptionsSetup>();

                if (loggerFactory != null)
                {
                    serviceCollection.AddSingleton(typeof(ILoggerFactory), loggerFactory);
                }

                serviceCollection
                .AddLogging()
                .AddSingleton(typeof(IConnectionFactory), sp => connectionFactory)
                .AddSingleton(typeof(HubLifetimeManager <>), typeof(WebSocketsHubLifetimeManager <>))
                .AddSingleton(typeof(IServiceConnectionManager <>), typeof(ServiceConnectionManager <>))
                .AddSingleton(typeof(IServiceConnectionContainer), sp => weakConnectionContainer);

                var             success         = false;
                ServiceProvider serviceProvider = null;
                try
                {
                    serviceProvider = serviceCollection.BuildServiceProvider();

                    var serviceConnectionManager = serviceProvider.GetRequiredService <IServiceConnectionManager <Hub> >();
                    serviceConnectionManager.SetServiceConnection(weakConnectionContainer);
                    _ = serviceConnectionManager.StartAsync();

                    // wait until service connection established
                    await weakConnectionContainer.ConnectionInitializedTask.OrTimeout(cancellationToken);

                    var webSocketsHubLifetimeManager = (WebSocketsHubLifetimeManager <Hub>)serviceProvider.GetRequiredService <HubLifetimeManager <Hub> >();

                    var hubContext        = serviceProvider.GetRequiredService <IHubContext <Hub> >();
                    var serviceHubContext = new ServiceHubContext(hubContext, webSocketsHubLifetimeManager, serviceProvider);
                    success = true;
                    return(serviceHubContext);
                }
                finally
                {
                    if (!success)
                    {
                        serviceProvider?.Dispose();
                    }
                }
            }

            case ServiceTransportType.Transient:
            {
                var serviceCollection = new ServiceCollection();
                serviceCollection.AddSignalRCore();

                // remove default hub lifetime manager
                var serviceDescriptor = serviceCollection.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(HubLifetimeManager <>));
                serviceCollection.Remove(serviceDescriptor);

                // add rest hub lifetime manager
                var restHubLifetimeManager = new RestHubLifetimeManager(_serviceManagerOptions, hubName, _productInfo);
                serviceCollection.AddSingleton(typeof(HubLifetimeManager <Hub>), sp => restHubLifetimeManager);

                var serviceProvider = serviceCollection.BuildServiceProvider();
                var hubContext      = serviceProvider.GetRequiredService <IHubContext <Hub> >();
                return(new ServiceHubContext(hubContext, restHubLifetimeManager, serviceProvider));
            }

            default:
                throw new ArgumentException("Not supported service transport type.");
            }
        }
Exemple #8
0
 public async Task Connect(ConnectionDelegate <TIncoming, TOutcoming> onConnection)
 {
     await Socket.Connect(Endpoint, () => OnConnect(onConnection), e => Logger.Log("Listener socket is closed " + e));
 }
Exemple #9
0
        public void accept(ConnectionDelegate handler)
        {
            Connection connection = new Connection(_listener.AcceptTcpClient());

            new Thread( () => handler(connection) ).Start();
        }
Exemple #10
0
        public async Task RunListenerAsync(IConnectionListener listener, ConnectionDelegate connectionDelegate, CancellationToken cancellationToken = default)
        {
            var unbindTask  = new TaskCompletionSource <object>();
            var connections = new ConcurrentDictionary <string, (ConnectionContext Connection, Task ExecutionTask)>();

            cancellationToken.Register(async() =>
            {
                try
                {
                    await listener.UnbindAsync();
                }
                finally
                {
                    unbindTask.TrySetResult(null);
                }
            });

            async Task ExecuteConnectionAsync(ConnectionContext connection)
            {
                await Task.Yield();

                try
                {
                    await connectionDelegate(connection);
                }
                catch (ConnectionAbortedException)
                {
                    // Don't let connection aborted exceptions out
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Unexpected exception from connection {ConnectionId}", connection.ConnectionId);
                }
                finally
                {
                    await connection.DisposeAsync();

                    // Remove the connection from tracking
                    connections.TryRemove(connection.ConnectionId, out _);
                }
            }

            while (true)
            {
                try
                {
                    var connection = await listener.AcceptAsync(cancellationToken);

                    if (connection == null)
                    {
                        // Null means we don't have anymore connections
                        break;
                    }

                    connections[connection.ConnectionId] = (connection, ExecuteConnectionAsync(connection));
                }
                catch (OperationCanceledException)
                {
                    // The accept loop was cancelled
                    break;
                }
            }

            // Wait for the listener to close, no new connections will be established
            await unbindTask.Task;

            // TODO: Give connections a chance to close gracefully

            var tasks = new List <Task>(connections.Count);

            // Abort all connections still in flight
            foreach (var pair in connections)
            {
                pair.Value.Connection.Abort();
                tasks.Add(pair.Value.ExecutionTask);
            }

            await Task.WhenAll(tasks);

            await listener.DisposeAsync();
        }
 // For Testing
 internal ConnectionLimitMiddleware(ConnectionDelegate next, ResourceCounter concurrentConnectionCounter, IKestrelTrace trace)
 {
     _next = next;
     _concurrentConnectionCounter = concurrentConnectionCounter;
     _trace = trace;
 }
 public ConnectionLimitMiddleware(ConnectionDelegate next, long connectionLimit, IKestrelTrace trace)
     : this(next, ResourceCounter.Quota(connectionLimit), trace)
 {
 }
 public PassThroughConnectionMiddleware(ConnectionDelegate next)
 {
     _next = next;
 }
Exemple #14
0
        public void accept(ConnectionDelegate handler)
        {
            Connection connection = new Connection(_listener.AcceptTcpClient());

            new Thread(() => handler(connection)).Start();
        }
        private IMultiEndpointServiceConnectionContainer GetMultiEndpointServiceConnectionContainer(string hub, ConnectionDelegate connectionDelegate, Action <HttpContext> contextConfig = null)
        {
            var connectionFactory = new ConnectionFactory(_nameProvider, _loggerFactory);

            var serviceConnectionFactory = GetServiceConnectionFactory(connectionFactory, connectionDelegate, contextConfig);

            var factory = new ServiceConnectionContainerFactory(
                serviceConnectionFactory,
                _serviceEndpointManager,
                _router,
                _options,
                _loggerFactory,
                _options.ServiceScaleTimeout
                );

            return(factory.Create(hub));
        }
 public ConnectionContextWithDelegate(ConnectionContext connection, ConnectionDelegate connectionDelegate)
 {
     _connectionDelegate = connectionDelegate;
     _connection         = connection;
 }
 /* Starts the flight searching thread
  *
  * This is the function the main window has to call.
  * It starts the thread searching for connections and
  * returns, so that the operation is asynchronous.
  */
 public void FindConnections(String departure, String arrival, 
 				bool? oneway, DateTime? leave, DateTime? back)
 {
     ConnectionDelegate searcher = new ConnectionDelegate(this.ThreadConnectionFind);
     searcher.BeginInvoke(departure, arrival, oneway, leave, back, null, null);
 }
Exemple #18
0
 public RewritingConnectionMiddleware(ConnectionDelegate next)
 {
     _next = next;
 }
        public async Task ClientConnectionContextAbortCanSendOutCloseMessage()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Trace, expectedErrors: c => true,
                                      logChecker: logs =>
            {
                return(true);
            }))
            {
                var            ccm                 = new TestClientConnectionManager();
                var            ccf                 = new ClientConnectionFactory();
                var            protocol            = new ServiceProtocol();
                TestConnection transportConnection = null;
                var            connectionFactory   = new TestConnectionFactory(conn =>
                {
                    transportConnection = conn;
                    return(Task.CompletedTask);
                });

                var services          = new ServiceCollection();
                var lastWill          = "This is the last will";
                var connectionHandler = new LastWillConnectionHandler(lastWill);
                services.AddSingleton(connectionHandler);
                var builder = new ConnectionBuilder(services.BuildServiceProvider());
                builder.UseConnectionHandler <LastWillConnectionHandler>();
                ConnectionDelegate handler = builder.Build();

                var connection = new ServiceConnection(protocol, ccm, connectionFactory, loggerFactory, handler, ccf,
                                                       "serverId", Guid.NewGuid().ToString("N"), null, null, closeTimeOutMilliseconds: 500);

                var connectionTask = connection.StartAsync();

                // completed handshake
                await connection.ConnectionInitializedTask.OrTimeout();

                Assert.Equal(ServiceConnectionStatus.Connected, connection.Status);
                var clientConnectionId = Guid.NewGuid().ToString();

                await transportConnection.Application.Output.WriteAsync(
                    protocol.GetMessageBytes(new OpenConnectionMessage(clientConnectionId, new Claim[] { })));

                var clientConnection = await ccm.WaitForClientConnectionAsync(clientConnectionId).OrTimeout();

                await clientConnection.LifetimeTask.OrTimeout();

                transportConnection.Transport.Output.Complete();
                var input = await transportConnection.Application.Input.ReadAsync();

                var buffer   = input.Buffer;
                var canParse = protocol.TryParseMessage(ref buffer, out var msg);
                Assert.True(canParse);
                var message = msg as ConnectionDataMessage;
                Assert.NotNull(message);

                Assert.Equal(clientConnectionId, message.ConnectionId);
                Assert.Equal(lastWill, Encoding.UTF8.GetString(message.Payload.First.ToArray()));

                // complete reading to end the connection
                transportConnection.Application.Output.Complete();

                // 1s for application task to timeout
                await connectionTask.OrTimeout(1000);

                Assert.Equal(ServiceConnectionStatus.Disconnected, connection.Status);
                Assert.Empty(ccm.ClientConnections);
            }
        }
Exemple #20
0
 public AsyncConnectionMiddleware(ConnectionDelegate next)
 {
     _next = next;
 }
Exemple #21
0
 private void OnConnect(ConnectionDelegate <TIncoming, TOutcoming> onConnection)
 {
     Logger.Log($"Connected to server on {Endpoint} (actual port {Port})");
     CreateConnection(Socket, onConnection);
 }
    public async Task ExecuteAsync(HttpContext context, HttpConnectionDispatcherOptions options, ConnectionDelegate connectionDelegate)
    {
        // Create the log scope and attempt to pass the Connection ID to it so as many logs as possible contain
        // the Connection ID metadata. If this is the negotiate request then the Connection ID for the scope will
        // be set a little later.

        HttpConnectionContext?connectionContext = null;
        var connectionToken = GetConnectionToken(context);

        if (!StringValues.IsNullOrEmpty(connectionToken))
        {
            // Use ToString; IsNullOrEmpty doesn't tell the compiler anything about implicit conversion to string.
            _manager.TryGetConnection(connectionToken.ToString(), out connectionContext);
        }

        var logScope = new ConnectionLogScope(connectionContext?.ConnectionId);

        using (_logger.BeginScope(logScope))
        {
            if (HttpMethods.IsPost(context.Request.Method))
            {
                // POST /{path}
                await ProcessSend(context, options);
            }
            else if (HttpMethods.IsGet(context.Request.Method))
            {
                // GET /{path}
                await ExecuteAsync(context, connectionDelegate, options, logScope);
            }
            else if (HttpMethods.IsDelete(context.Request.Method))
            {
                // DELETE /{path}
                await ProcessDeleteAsync(context);
            }
            else
            {
                context.Response.ContentType = "text/plain";
                context.Response.StatusCode  = StatusCodes.Status405MethodNotAllowed;
            }
        }
    }
Exemple #23
0
 public LocalHostBinding(int port, ConnectionDelegate application, IConnectionListenerFactory connectionListenerFactory)
 {
     Port         = port;
     _application = application;
     ConnectionListenerFactory = connectionListenerFactory;
 }
Exemple #24
0
 internal override ServiceConnectionFactory GetServiceConnectionFactory(
     ConnectionFactory connectionFactory, ConnectionDelegate connectionDelegate, Action <HttpContext> contextConfig
     ) => new MockServiceConnectionFactory(MockService, _serviceProtocol, _clientConnectionManager, connectionFactory, _loggerFactory, connectionDelegate, _clientConnectionFactory, _nameProvider);
 public LoggingConnectionMiddleware(ConnectionDelegate next, ILogger logger)
 {
     _next   = next ?? throw new ArgumentNullException(nameof(next));
     _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 }
Exemple #26
0
 public TestConnectionFactory(ConnectionDelegate connectCallback = null)
 {
     _connectCallback = connectCallback ?? OnConnectionAsync;
 }
Exemple #27
0
 public Connection(IReceiver<ReceivedPayload<IProtocolEvent>> receiver, ISender<IProtocolEvent> sender, ConnectionDelegate connDdelegate)
 {
     _receiver = receiver;
     _sender = sender;
     _connDdelegate = connDdelegate;
 }
Exemple #28
0
 public Client(IConnectionFactory connectionFactory, ConnectionDelegate application)
 {
     _connectionFactory = connectionFactory;
     _application       = application;
 }
        private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connectionDelegate, HttpConnectionDispatcherOptions options, ConnectionLogScope logScope)
        {
            var supportedTransports = options.Transports;

            // Server sent events transport
            // GET /{path}
            // Accept: text/event-stream
            var headers = context.Request.GetTypedHeaders();

            if (headers.Accept?.Contains(new Net.Http.Headers.MediaTypeHeaderValue("text/event-stream")) == true)
            {
                // Connection must already exist
                var connection = await GetConnectionAsync(context);

                if (connection == null)
                {
                    // No such connection, GetConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.ServerSentEvents, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                Log.EstablishedConnection(_logger);

                // ServerSentEvents is a text protocol only
                connection.SupportedFormats = TransferFormat.Text;

                // We only need to provide the Input channel since writing to the application is handled through /send.
                var sse = new ServerSentEventsTransport(connection.Application.Input, connection.ConnectionId, _loggerFactory);

                await DoPersistentConnection(connectionDelegate, sse, context, connection);
            }
            else if (context.WebSockets.IsWebSocketRequest)
            {
                // Connection can be established lazily
                var connection = await GetOrCreateConnectionAsync(context, options);

                if (connection == null)
                {
                    // No such connection, GetOrCreateConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.WebSockets, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                Log.EstablishedConnection(_logger);

                var ws = new WebSocketsTransport(options.WebSockets, connection.Application, connection, _loggerFactory);

                await DoPersistentConnection(connectionDelegate, ws, context, connection);
            }
            else
            {
                // GET /{path} maps to long polling

                // Connection must already exist
                var connection = await GetConnectionAsync(context);

                if (connection == null)
                {
                    // No such connection, GetConnection already set the response status code
                    return;
                }

                if (!await EnsureConnectionStateAsync(connection, context, HttpTransportType.LongPolling, supportedTransports, logScope, options))
                {
                    // Bad connection state. It's already set the response status code.
                    return;
                }

                await connection.StateLock.WaitAsync();

                try
                {
                    if (connection.Status == HttpConnectionStatus.Disposed)
                    {
                        Log.ConnectionDisposed(_logger, connection.ConnectionId);

                        // The connection was disposed
                        context.Response.StatusCode  = StatusCodes.Status404NotFound;
                        context.Response.ContentType = "text/plain";
                        return;
                    }

                    if (connection.Status == HttpConnectionStatus.Active)
                    {
                        var existing = connection.GetHttpContext();
                        Log.ConnectionAlreadyActive(_logger, connection.ConnectionId, existing.TraceIdentifier);

                        using (connection.Cancellation)
                        {
                            // Cancel the previous request
                            connection.Cancellation?.Cancel();

                            // Wait for the previous request to drain
                            await connection.TransportTask;

                            Log.PollCanceled(_logger, connection.ConnectionId, existing.TraceIdentifier);
                        }
                    }

                    // Mark the connection as active
                    connection.Status = HttpConnectionStatus.Active;

                    // Raise OnConnected for new connections only since polls happen all the time
                    if (connection.ApplicationTask == null)
                    {
                        Log.EstablishedConnection(_logger);

                        connection.ApplicationTask = ExecuteApplication(connectionDelegate, connection);

                        context.Response.ContentType = "application/octet-stream";

                        // This request has no content
                        context.Response.ContentLength = 0;

                        // On the first poll, we flush the response immediately to mark the poll as "initialized" so future
                        // requests can be made safely
                        connection.TransportTask = context.Response.Body.FlushAsync();
                    }
                    else
                    {
                        Log.ResumingConnection(_logger);

                        // REVIEW: Performance of this isn't great as this does a bunch of per request allocations
                        connection.Cancellation = new CancellationTokenSource();

                        var timeoutSource = new CancellationTokenSource();
                        var tokenSource   = CancellationTokenSource.CreateLinkedTokenSource(connection.Cancellation.Token, context.RequestAborted, timeoutSource.Token);

                        // Dispose these tokens when the request is over
                        context.Response.RegisterForDispose(timeoutSource);
                        context.Response.RegisterForDispose(tokenSource);

                        var longPolling = new LongPollingTransport(timeoutSource.Token, connection.Application.Input, _loggerFactory);

                        // Start the transport
                        connection.TransportTask = longPolling.ProcessRequestAsync(context, tokenSource.Token);

                        // Start the timeout after we return from creating the transport task
                        timeoutSource.CancelAfter(options.LongPolling.PollTimeout);
                    }
                }
                finally
                {
                    connection.StateLock.Release();
                }

                var resultTask = await Task.WhenAny(connection.ApplicationTask, connection.TransportTask);

                var pollAgain = true;

                // If the application ended before the transport task then we potentially need to end the connection
                if (resultTask == connection.ApplicationTask)
                {
                    // Complete the transport (notifying it of the application error if there is one)
                    connection.Transport.Output.Complete(connection.ApplicationTask.Exception);

                    // Wait for the transport to run
                    await connection.TransportTask;

                    // If the status code is a 204 it means the connection is done
                    if (context.Response.StatusCode == StatusCodes.Status204NoContent)
                    {
                        // We should be able to safely dispose because there's no more data being written
                        // We don't need to wait for close here since we've already waited for both sides
                        await _manager.DisposeAndRemoveAsync(connection, closeGracefully : false);

                        // Don't poll again if we've removed the connection completely
                        pollAgain = false;
                    }
                }
                else if (context.Response.StatusCode == StatusCodes.Status204NoContent)
                {
                    // Don't poll if the transport task was canceled
                    pollAgain = false;
                }

                if (pollAgain)
                {
                    // Otherwise, we update the state to inactive again and wait for the next poll
                    await connection.StateLock.WaitAsync();

                    try
                    {
                        if (connection.Status == HttpConnectionStatus.Active)
                        {
                            // Mark the connection as inactive
                            connection.LastSeenUtc = DateTime.UtcNow;

                            connection.Status = HttpConnectionStatus.Inactive;

                            // Dispose the cancellation token
                            connection.Cancellation?.Dispose();

                            connection.Cancellation = null;
                        }
                    }
                    finally
                    {
                        connection.StateLock.Release();
                    }
                }
            }
        }
Exemple #30
0
 public ConnectionHandler(ServiceContext serviceContext, ConnectionDelegate connectionDelegate)
 {
     _serviceContext     = serviceContext;
     _connectionDelegate = connectionDelegate;
 }
Exemple #31
0
        private MultiEndpointServiceConnectionContainer GetMultiEndpointServiceConnectionContainer(string hub, ConnectionDelegate connectionDelegate, Action <HttpContext> contextConfig = null)
        {
            var connectionFactory        = new ConnectionFactory(_nameProvider, _loggerFactory);
            var serviceConnectionFactory = new ServiceConnectionFactory(_serviceProtocol, _clientConnectionManager, connectionFactory, _loggerFactory, connectionDelegate, _clientConnectionFactory);

            serviceConnectionFactory.ConfigureContext = contextConfig;
            return(new MultiEndpointServiceConnectionContainer(serviceConnectionFactory, hub, _options.ConnectionCount, _serviceEndpointManager, _router, _nameProvider, _loggerFactory));
        }
Exemple #32
0
 public StateListener()
 {
     OnDisconnect = new ConnectionDelegate(Func);
     OnConnect    = new ConnectionDelegate(Func);
     OnUpdate     = new ConnectionDelegate(Func);
 }
 public HttpsConnectionMiddleware(ConnectionDelegate next, HttpsConnectionAdapterOptions options)
     : this(next, options, loggerFactory : NullLoggerFactory.Instance)
 {
 }
Exemple #34
0
 public TestServiceConnectionProxy(IClientConnectionManager clientConnectionManager, ILoggerFactory loggerFactory, ConnectionDelegate callback = null, PipeOptions clientPipeOptions = null, IServiceMessageHandler serviceMessageHandler = null) :
     base(
         Guid.NewGuid().ToString("N"),
         null,
         SharedServiceProtocol,
         new TestConnectionFactory(),
         clientConnectionManager,
         loggerFactory,
         serviceMessageHandler ?? new TestServiceMessageHandler())
 {
 }
        public async Task TestServiceConnectionWithErrorApplicationTask()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Warning, expectedErrors: c => true,
                                      logChecker: logs =>
            {
                Assert.Equal(2, logs.Count);
                Assert.Equal("SendLoopStopped", logs[0].Write.EventId.Name);
                Assert.Equal("ApplicationTaskFailed", logs[1].Write.EventId.Name);
                return(true);
            }))
            {
                var            ccm                 = new TestClientConnectionManager();
                var            ccf                 = new ClientConnectionFactory();
                var            protocol            = new ServiceProtocol();
                TestConnection transportConnection = null;
                var            connectionFactory   = new TestConnectionFactory(conn =>
                {
                    transportConnection = conn;
                    return(Task.CompletedTask);
                });
                var services          = new ServiceCollection();
                var errorTcs          = new TaskCompletionSource <Exception>();
                var connectionHandler = new ErrorConnectionHandler(errorTcs);
                services.AddSingleton(connectionHandler);
                var builder = new ConnectionBuilder(services.BuildServiceProvider());

                builder.UseConnectionHandler <ErrorConnectionHandler>();
                ConnectionDelegate handler = builder.Build();

                var connection = new ServiceConnection(protocol, ccm, connectionFactory, loggerFactory, handler, ccf,
                                                       "serverId", Guid.NewGuid().ToString("N"), null, null);

                var connectionTask = connection.StartAsync();

                // completed handshake
                await connection.ConnectionInitializedTask.OrTimeout();

                Assert.Equal(ServiceConnectionStatus.Connected, connection.Status);
                var clientConnectionId = Guid.NewGuid().ToString();

                await transportConnection.Application.Output.WriteAsync(
                    protocol.GetMessageBytes(new OpenConnectionMessage(clientConnectionId, new Claim[] { })));

                var clientConnection = await ccm.WaitForClientConnectionAsync(clientConnectionId).OrTimeout();

                errorTcs.SetException(new InvalidOperationException("error operation"));

                await clientConnection.LifetimeTask.OrTimeout();

                // Should complete the connection when application throws
                await ccm.WaitForClientConnectionRemovalAsync(clientConnectionId).OrTimeout();

                // Application task should not affect the underlying service connection
                Assert.Equal(ServiceConnectionStatus.Connected, connection.Status);

                // complete reading to end the connection
                transportConnection.Application.Output.Complete();

                await connectionTask.OrTimeout();

                Assert.Equal(ServiceConnectionStatus.Disconnected, connection.Status);
                Assert.Empty(ccm.ClientConnections);
            }
        }
Exemple #36
0
 public static Connection Connect(String host, int port, ConnectionDelegate conndel)
 {
     IoTransport transport = new IoTransport(host, port, conndel);
     return transport.Connection;
 }