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(); } } } }