Пример #1
0
        public async Task ServiceConnectionWithOfflinePingWillTriggerDisconnectClients()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug))
            {
                var hubConfig = Utility.GetActualHubConfig(loggerFactory);
                var appName   = "app1";
                var hub       = "chat";
                var scm       = new TestServiceConnectionHandler();
                hubConfig.Resolver.Register(typeof(IServiceConnectionManager), () => scm);
                var ccm = new ClientConnectionManager(hubConfig, loggerFactory);
                hubConfig.Resolver.Register(typeof(IClientConnectionManager), () => ccm);
                DispatcherHelper.PrepareAndGetDispatcher(new TestAppBuilder(), hubConfig, new ServiceOptions {
                    ConnectionString = ConnectionString
                }, appName, loggerFactory);
                using (var proxy = new TestServiceConnectionProxy(ccm, loggerFactory: loggerFactory))
                {
                    // prepare 2 clients with different instancesId connected
                    var instanceId1   = Guid.NewGuid().ToString();
                    var connectionId1 = Guid.NewGuid().ToString("N");
                    var header1       = new Dictionary <string, StringValues>()
                    {
                        { Constants.AsrsInstanceId, instanceId1 }
                    };
                    var instanceId2   = Guid.NewGuid().ToString();
                    var connectionId2 = Guid.NewGuid().ToString("N");
                    var header2       = new Dictionary <string, StringValues>()
                    {
                        { Constants.AsrsInstanceId, instanceId2 }
                    };

                    // start the server connection
                    await proxy.StartServiceAsync().OrTimeout();

                    // Application layer sends OpenConnectionMessage for client1
                    var connectTask           = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage)).OrTimeout();
                    var openConnectionMessage = new OpenConnectionMessage(connectionId1, new Claim[0], header1, $"?transport=webSockets&connectionToken=conn1&connectionData=%5B%7B%22name%22%3A%22{hub}%22%7D%5D");
                    await proxy.WriteMessageAsync(openConnectionMessage);

                    // client1 is connected
                    var connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);
                    var message = connectMessage.Payloads["json"].GetJsonMessageFromSingleFramePayload <HubResponseItem>();
                    Assert.Equal("Connected", message.A[0]);

                    ccm.ClientConnections.TryGetValue(connectionId1, out var transport1);
                    Assert.NotNull(transport1);

                    // Application layer sends OpenConnectionMessage for client2
                    connectTask           = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage)).OrTimeout();
                    openConnectionMessage = new OpenConnectionMessage(connectionId2, new Claim[0], header2, $"?transport=webSockets&connectionToken=conn2&connectionData=%5B%7B%22name%22%3A%22{hub}%22%7D%5D");
                    await proxy.WriteMessageAsync(openConnectionMessage);

                    // client2 is connected
                    connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);
                    message = connectMessage.Payloads["json"].GetJsonMessageFromSingleFramePayload <HubResponseItem>();
                    Assert.Equal("Connected", message.A[0]);
                    ccm.ClientConnections.TryGetValue(connectionId2, out var transport2);
                    Assert.NotNull(transport2);

                    // Send ServerOfflinePing on instance1 and will trigger cleanup related client1
                    connectTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage)).OrTimeout();
                    await proxy.WriteMessageAsync(new PingMessage()
                    {
                        Messages = new[] { "offline", instanceId1 }
                    });

                    // Validate client1 disconnect
                    connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);
                    message = connectMessage.Payloads["json"]
                              .GetJsonMessageFromSingleFramePayload <HubResponseItem>();
                    Assert.Equal("Disconnected", message.A[0]);

                    // Validate client2 is still connected
                    Assert.Single(ccm.ClientConnections);
                    Assert.Equal(connectionId2, ccm.ClientConnections.FirstOrDefault().Key);
                }
            }
        }
Пример #2
0
        public async Task ServiceConnectionWithTransportLayerClosedShouldCleanupEndlessInvokeClientConnections()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug, expectedErrors: c => true))
            {
                var hubConfig = Utility.GetActualHubConfig(loggerFactory);
                var appName   = "app1";
                var hub       = "EndlessInvoke";
                var scm       = new TestServiceConnectionHandler();
                hubConfig.Resolver.Register(typeof(IServiceConnectionManager), () => scm);
                var ccm = new ClientConnectionManager(hubConfig, loggerFactory);
                hubConfig.Resolver.Register(typeof(IClientConnectionManager), () => ccm);
                DispatcherHelper.PrepareAndGetDispatcher(new TestAppBuilder(), hubConfig,
                                                         new ServiceOptions {
                    ConnectionString = ConnectionString
                }, appName, loggerFactory);
                using (var proxy = new TestServiceConnectionProxy(ccm, loggerFactory))
                {
                    // start the server connection
                    var connectionTask = proxy.StartAsync();
                    await proxy.ConnectionInitializedTask.OrTimeout();

                    var clientConnection = Guid.NewGuid().ToString("N");

                    var connectTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage))
                                      .OrTimeout();
                    // Application layer sends OpenConnectionMessage
                    var openConnectionMessage = new OpenConnectionMessage(clientConnection, new Claim[0], null,
                                                                          $"?transport=webSockets&connectionToken=conn1&connectionData=%5B%7B%22name%22%3A%22{hub}%22%7D%5D");
                    await proxy.WriteMessageAsync(openConnectionMessage);

                    var connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);

                    var message = connectMessage.Payloads["json"]
                                  .GetJsonMessageFromSingleFramePayload <HubResponseItem>();

                    Assert.Equal("Connected", message.A[0]);

                    // group message goes into the manager
                    // make sure the tcs is called before writing message
                    var gbTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage)).OrTimeout();

                    await proxy.WriteMessageAsync(new ConnectionDataMessage(clientConnection, Encoding.UTF8.GetBytes($"{{\"H\":\"{hub}\",\"M\":\"JoinGroup\",\"A\":[\"user1\",\"group1\"],\"I\":1}}")));

                    var broadcastMessage = (await gbTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(broadcastMessage);
                    Assert.Equal($"hg-{hub}.group1", broadcastMessage.GroupName);

                    // close transport layer
                    proxy.TestConnectionContext.Application.Output.Complete();

                    await connectionTask.OrTimeout();

                    await proxy.WaitForConnectionClose.OrTimeout();

                    Assert.Equal(ServiceConnectionStatus.Disconnected, proxy.Status);

                    // cleaned up clearly
                    Assert.Empty(ccm.ClientConnections);
                }
            }
        }