public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null, IInvocationBinder invocationBinder = null, bool addClaimId = false) { var options = new ChannelOptimizations { AllowSynchronousContinuations = synchronousCallbacks }; var transportToApplication = Channel.CreateUnbounded <byte[]>(options); var applicationToTransport = Channel.CreateUnbounded <byte[]>(options); Application = ChannelConnection.Create <byte[]>(input: applicationToTransport, output: transportToApplication); _transport = ChannelConnection.Create <byte[]>(input: transportToApplication, output: applicationToTransport); Connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _transport, Application); var claimValue = Interlocked.Increment(ref _id).ToString(); var claims = new List <Claim> { new Claim(ClaimTypes.Name, claimValue) }; if (addClaimId) { claims.Add(new Claim(ClaimTypes.NameIdentifier, claimValue)); } Connection.User = new ClaimsPrincipal(new ClaimsIdentity(claims)); Connection.Metadata["ConnectedTask"] = new TaskCompletionSource <bool>(); protocol = protocol ?? new JsonHubProtocol(); _protocolReaderWriter = new HubProtocolReaderWriter(protocol, new PassThroughEncoder()); _invocationBinder = invocationBinder ?? new DefaultInvocationBinder(); _cts = new CancellationTokenSource(); using (var memoryStream = new MemoryStream()) { NegotiationProtocol.WriteMessage(new NegotiationMessage(protocol.Name), memoryStream); Application.Out.TryWrite(memoryStream.ToArray()); } }
public async Task ServerGracefullyClosesWhenApplicationEndsThenClientSendsCloseFrame() { var transportToApplication = Channel.CreateUnbounded <byte[]>(); var applicationToTransport = Channel.CreateUnbounded <byte[]>(); using (var transportSide = ChannelConnection.Create <byte[]>(applicationToTransport, transportToApplication)) using (var applicationSide = ChannelConnection.Create <byte[]>(transportToApplication, applicationToTransport)) using (var feature = new TestWebSocketConnectionFeature()) { var options = new WebSocketOptions { // We want to verify behavior without timeout affecting it CloseTimeout = TimeSpan.FromSeconds(20) }; var connectionContext = new DefaultConnectionContext(string.Empty, null, null); var ws = new WebSocketsTransport(options, transportSide, connectionContext, loggerFactory: new LoggerFactory()); var serverSocket = await feature.AcceptAsync(); // Give the server socket to the transport and run it var transport = ws.ProcessSocketAsync(serverSocket); // Run the client socket var client = feature.Client.ExecuteAndCaptureFramesAsync(); // close the client to server channel applicationToTransport.Out.TryComplete(); _ = await client.OrTimeout(); await feature.Client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None).OrTimeout(); await transport.OrTimeout(); Assert.Equal(WebSocketCloseStatus.NormalClosure, serverSocket.CloseStatus); } }
private async Task StartTransport(Uri connectUrl) { var applicationToTransport = Channel.CreateUnbounded <SendMessage>(); var transportToApplication = Channel.CreateUnbounded <byte[]>(); var applicationSide = ChannelConnection.Create(applicationToTransport, transportToApplication); _transportChannel = ChannelConnection.Create(transportToApplication, applicationToTransport); // Start the transport, giving it one end of the pipeline try { await _transport.StartAsync(connectUrl, applicationSide, requestedTransferMode : GetTransferMode(), connectionId : _connectionId); // actual transfer mode can differ from the one that was requested so set it on the feature Debug.Assert(_transport.Mode.HasValue, "transfer mode not set after transport started"); SetTransferMode(_transport.Mode.Value); } catch (Exception ex) { _logger.ErrorStartingTransport(_connectionId, _transport.GetType().Name, ex); throw; } }
public async Task TransportFailsOnTimeoutWithErrorWhenApplicationFailsAndClientDoesNotSendCloseFrame() { using (StartLog(out var loggerFactory)) { var transportToApplication = Channel.CreateUnbounded <byte[]>(); var applicationToTransport = Channel.CreateUnbounded <byte[]>(); using (var transportSide = ChannelConnection.Create <byte[]>(applicationToTransport, transportToApplication)) using (var applicationSide = ChannelConnection.Create <byte[]>(transportToApplication, applicationToTransport)) using (var feature = new TestWebSocketConnectionFeature()) { var options = new WebSocketOptions { CloseTimeout = TimeSpan.FromSeconds(1) }; var connectionContext = new DefaultConnectionContext(string.Empty, null, null); var ws = new WebSocketsTransport(options, transportSide, connectionContext, loggerFactory); var serverSocket = await feature.AcceptAsync(); // Give the server socket to the transport and run it var transport = ws.ProcessSocketAsync(serverSocket); // Run the client socket var client = feature.Client.ExecuteAndCaptureFramesAsync(); // fail the client to server channel applicationToTransport.Writer.TryComplete(new Exception()); await Assert.ThrowsAsync <Exception>(() => transport).OrTimeout(); Assert.Equal(WebSocketState.Aborted, serverSocket.State); } } }
public async Task TransportClosesOnCloseTimeoutIfClientDoesNotSendCloseFrame() { using (StartLog(out var loggerFactory)) { var transportToApplication = Channel.CreateUnbounded <byte[]>(); var applicationToTransport = Channel.CreateUnbounded <byte[]>(); using (var transportSide = ChannelConnection.Create <byte[]>(applicationToTransport, transportToApplication)) using (var applicationSide = ChannelConnection.Create <byte[]>(transportToApplication, applicationToTransport)) using (var feature = new TestWebSocketConnectionFeature()) { var options = new WebSocketOptions() { CloseTimeout = TimeSpan.FromSeconds(1) }; var connectionContext = new DefaultConnectionContext(string.Empty, null, null); var ws = new WebSocketsTransport(options, transportSide, connectionContext, loggerFactory); var serverSocket = await feature.AcceptAsync(); // Give the server socket to the transport and run it var transport = ws.ProcessSocketAsync(serverSocket); // End the app applicationSide.Dispose(); await transport.OrTimeout(TimeSpan.FromSeconds(10)); // Now we're closed Assert.Equal(WebSocketState.Aborted, serverSocket.State); serverSocket.Dispose(); } } }