public async Task CloseClientsWhenReceiveInstanceOfflinePing() { // Prepare clients var instanceId1 = Guid.NewGuid().ToString(); var connectionId1 = Guid.NewGuid().ToString("N"); var header1 = new HeaderDictionary() { { Constants.AsrsInstanceId, instanceId1 } }; var instanceId2 = Guid.NewGuid().ToString(); var connectionId2 = Guid.NewGuid().ToString("N"); var header2 = new HeaderDictionary() { { Constants.AsrsInstanceId, instanceId2 } }; var proxy = new ServiceConnectionProxy(); var connectionTask = proxy.WaitForServerConnectionAsync(1); _ = proxy.StartAsync(); await connectionTask.OrTimeout(); // 2 client connects with different instanceIds await proxy.WriteMessageAsync(new OpenConnectionMessage(connectionId1, null, header1, null)); connectionTask = proxy.WaitForConnectionAsync(connectionId1); await connectionTask.OrTimeout(); await proxy.WriteMessageAsync(new OpenConnectionMessage(connectionId2, null, header2, null)); connectionTask = proxy.WaitForConnectionAsync(connectionId2); await connectionTask.OrTimeout(); // Server received instance offline ping on instanceId1 and trigger cleanup related client1 await proxy.WriteMessageAsync(new PingMessage() { Messages = new[] { "offline", instanceId1 } }); // Validate client1 is closed and client2 is still connected var disconnectTask = proxy.WaitForConnectionCloseAsync(connectionId1); await disconnectTask.OrTimeout(); Assert.Single(proxy.ClientConnections); Assert.Equal(connectionId2, proxy.ClientConnections.FirstOrDefault().Key); }
public async Task ServiceConnectionStartsConnection() { var connectionId1 = Guid.NewGuid().ToString("N"); var connectionId2 = Guid.NewGuid().ToString("N"); var proxy = new ServiceConnectionProxy(); var serverTask = proxy.WaitForServerConnectionAsync(1); _ = proxy.StartAsync(); await serverTask.OrTimeout(); Assert.Empty(proxy.ClientConnectionManager.ClientConnections); // Wait for the connection to appear, we need to do this before // sending the message to avoid races var connection1Task = proxy.WaitForConnectionAsync(connectionId1); // Create a new client connection await proxy.WriteMessageAsync(new OpenConnectionMessage(connectionId1, null)); var connection1 = await connection1Task.OrTimeout(); Assert.Single(proxy.ClientConnectionManager.ClientConnections); var httpContext1 = connection1.GetHttpContext(); Assert.NotNull(httpContext1); Assert.Empty(httpContext1.Request.Headers); Assert.Empty(httpContext1.Request.Query); Assert.Equal(string.Empty, httpContext1.Request.Path); // Wait for the connection to appear var connectionTask2 = proxy.WaitForConnectionAsync(connectionId2); // Create another client connection const string headerKey1 = "custom-header-1"; const string headerValue1 = "custom-value-1"; const string headerKey2 = "custom-header-2"; var headerValue2 = new[] { "custom-value-2a", "custom-value-2b" }; const string headerKey3 = "custom-header-3"; var headerValue3 = new[] { "custom-value-3a", "custom-value-3b", "custom-value-3c" }; const string path = "/this/is/user/path"; await proxy.WriteMessageAsync(new OpenConnectionMessage(connectionId2, null, new Dictionary <string, StringValues> { { headerKey1, headerValue1 }, { headerKey2, headerValue2 }, { headerKey3, headerValue3 } }, $"?customQuery1=customValue1&customQuery2=customValue2&{Constants.QueryParameter.OriginalPath}={WebUtility.UrlEncode(path)}")); var connection2 = await connectionTask2.OrTimeout(); Assert.Equal(2, proxy.ClientConnectionManager.ClientConnections.Count); var httpContext2 = connection2.GetHttpContext(); Assert.NotNull(httpContext2); Assert.Equal(3, httpContext2.Request.Headers.Count); Assert.Equal(headerValue1, httpContext2.Request.Headers[headerKey1]); Assert.Equal(headerValue2, httpContext2.Request.Headers[headerKey2]); Assert.Equal(headerValue3, httpContext2.Request.Headers[headerKey3]); Assert.Equal(3, httpContext2.Request.Query.Count); Assert.Equal("customValue1", httpContext2.Request.Query["customQuery1"]); Assert.Equal("customValue2", httpContext2.Request.Query["customQuery2"]); Assert.Equal(path, httpContext2.Request.Query[Constants.QueryParameter.OriginalPath]); Assert.Equal(path, httpContext2.Request.Path); // Send a message to client 1 await proxy.WriteMessageAsync(new ConnectionDataMessage(connectionId1, Encoding.ASCII.GetBytes("Hello"))); var item = await connection1.Transport.Input.ReadSingleAsync().OrTimeout(); Assert.Equal("Hello", Encoding.ASCII.GetString(item)); var connection1CloseTask = proxy.WaitForConnectionCloseAsync(connectionId1); // Close client 1 await proxy.WriteMessageAsync(new CloseConnectionMessage(connectionId1, null)); await connection1CloseTask.OrTimeout(); Assert.Single(proxy.ClientConnectionManager.ClientConnections); // Close client 2 var connection2CloseTask = proxy.WaitForConnectionCloseAsync(connectionId2); await proxy.WriteMessageAsync(new CloseConnectionMessage(connectionId2, null)); await connection2CloseTask.OrTimeout(); Assert.Empty(proxy.ClientConnectionManager.ClientConnections); proxy.Stop(); }