public static async Task RunSessionAsync(AppFunc app, Func<Http2ClientSession, Http2ServerSession, Task> sessionOperations) { DuplexStream clientStream = new DuplexStream(); DuplexStream serverStream = clientStream.GetOpositeStream(); Task clientTask, serverTask; using (Http2ClientSession clientSession = new Http2ClientSession(clientStream, false, CancellationToken.None, CancellationToken.None)) { using (Http2ServerSession serverSession = new Http2ServerSession(app, new TransportInformation())) { clientTask = clientSession.Start(); serverTask = serverSession.Start(serverStream, CancellationToken.None); await sessionOperations(clientSession, serverSession); } } await clientTask; await serverTask; }
public void ConnectionReset_StreamsAborted() { DuplexStream clientStream = new DuplexStream(); DuplexStream serverStream = clientStream.GetOpositeStream(); ManualResetEvent waitForRequest = new ManualResetEvent(false); ManualResetEvent waitForCancel = new ManualResetEvent(false); AppFunc app = environment => { OwinResponse response = new OwinResponse(environment); TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); response.CallCancelled.Register(() => { waitForCancel.Set(); tcs.TrySetCanceled(); }); waitForRequest.Set(); return tcs.Task; }; Task clientTask, serverTask; using (Http2ClientSession clientSession = new Http2ClientSession(clientStream, false, CancellationToken.None, CancellationToken.None)) { using (Http2ServerSession serverSession = new Http2ServerSession(app, CreateTransportInfo())) { clientTask = clientSession.Start(); serverTask = serverSession.Start(serverStream, CancellationToken.None); IList<KeyValuePair<string, string>> requestPairs = GenerateHeaders("GET"); Http2ClientStream clientProtocolStream = clientSession.SendRequest(requestPairs, null, 3, false, CancellationToken.None); Task<IList<KeyValuePair<string, string>>> responseTask = clientProtocolStream.GetResponseAsync(); waitForRequest.WaitOne(); clientStream.Abort(); Assert.Throws<AggregateException>(() => responseTask.Result); Assert.Throws<AggregateException>(() => clientTask.Wait(1000)); Assert.True(serverTask.Wait(1000)); Assert.True(waitForCancel.WaitOne(1000)); } } }
private async void Listen() { _socket.Listen(backlog: 2); while (!_disposed) { Http2ServerSession session = null; Socket clientSocket = null; Stream stream = null; try { clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, (Func<IAsyncResult, Socket>)_socket.EndAccept, null); stream = new NetworkStream(clientSocket, ownsSocket: true); X509Certificate clientCert = null; if (_enableSsl) { SslStream sslStream = new SslStream(stream); await sslStream.AuthenticateAsServerAsync(_serverCert, clientCertificateRequired: false, enabledSslProtocols: _sslProtocols, checkCertificateRevocation: false); clientCert = sslStream.RemoteCertificate; stream = sslStream; } // TODO: At this point we could read the first bit of the first byte received on this connection to determine if it is a HTTP/1.1 or 2.0 request. IPEndPoint localEndPoint = (IPEndPoint)clientSocket.LocalEndPoint; IPEndPoint remoteEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint; TransportInformation transportInfo = new TransportInformation() { ClientCertificate = clientCert, LocalPort = localEndPoint.Port.ToString(CultureInfo.InvariantCulture), RemotePort = remoteEndPoint.Port.ToString(CultureInfo.InvariantCulture), }; // Side effect of using dual mode sockets, the IPv4 addresses look like 0::ffff:127.0.0.1. if (localEndPoint.Address.IsIPv4MappedToIPv6) { transportInfo.LocalIpAddress = localEndPoint.Address.MapToIPv4().ToString(); } else { transportInfo.LocalIpAddress = localEndPoint.Address.ToString(); } if (remoteEndPoint.Address.IsIPv4MappedToIPv6) { transportInfo.RemoteIpAddress = remoteEndPoint.Address.MapToIPv4().ToString(); } else { transportInfo.RemoteIpAddress = remoteEndPoint.Address.ToString(); } session = new Http2ServerSession(_next, transportInfo); // TODO: awaiting here will only let us accept the next connection/session after the current one finishes. await session.Start(stream, CancellationToken.None); } catch (ProtocolViolationException) { // Handshake failure, most likely do to receiving a HTTP/1.1 text request. } catch (SocketException) { // Disconnect? } catch (ObjectDisposedException) { Dispose(); } catch (Exception) { Dispose(); throw; } finally { if (session != null) { session.Dispose(); } if (stream != null) { stream.Dispose(); } if (clientSocket != null) { clientSocket.Dispose(); } } } }