private void HandleAcceptedClient(SecureSocket incomingClient, ALPNExtensionMonitor monitor) { bool backToHttp11 = false; string selectedProtocol = Protocols.Http1; if (_useHandshake) { try { if (_options.Protocol != SecureProtocol.None) { incomingClient.MakeSecureHandshake(_options); selectedProtocol = incomingClient.SelectedProtocol; } } catch (SecureHandshakeException ex) { switch (ex.Reason) { case SecureHandshakeFailureReason.HandshakeInternalError: backToHttp11 = true; break; case SecureHandshakeFailureReason.HandshakeTimeout: incomingClient.Close(); Http2Logger.LogError("Handshake timeout. Client was disconnected."); return; default: incomingClient.Close(); Http2Logger.LogError("Unknown error occurred during secure handshake"); return; } } catch (Exception e) { Http2Logger.LogError("Exception occurred. Closing client's socket. " + e.Message); incomingClient.Close(); return; } } var clientStream = new DuplexStream(incomingClient, true); var transportInfo = GetTransportInfo(incomingClient); monitor.Dispose(); try { HandleRequest(clientStream, selectedProtocol, transportInfo, backToHttp11); } catch (Exception e) { Http2Logger.LogError("Exception occurred. Closing client's socket. " + e.Message); incomingClient.Close(); } }
public bool Connect(Uri connectUri) { _path = connectUri.PathAndQuery; _version = Protocols.Http2; _scheme = connectUri.Scheme; _host = connectUri.Host; _port = connectUri.Port; ServerUri = connectUri.Authority; if (_sessionAdapter != null) { return false; } try { int port = connectUri.Port; int securePort; if (!int.TryParse(ConfigurationManager.AppSettings["securePort"], out securePort)) { Http2Logger.LogError("Incorrect port in the config file!"); return false; } //Connect alpn extension, set known protocols var extensions = new[] {ExtensionType.Renegotiation, ExtensionType.ALPN}; Options = port == securePort ? new SecurityOptions(SecureProtocol.Tls1, extensions, new[] { Protocols.Http1, Protocols.Http2 }, ConnectionEnd.Client) : new SecurityOptions(SecureProtocol.None, extensions, new[] { Protocols.Http1, Protocols.Http2 }, ConnectionEnd.Client); Options.VerificationType = CredentialVerification.None; Options.Certificate = Org.Mentalis.Security.Certificates.Certificate.CreateFromCerFile(CertificatePath); Options.Flags = SecurityFlags.Default; Options.AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION; var socket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, Options); using (var monitor = new ALPNExtensionMonitor()) { monitor.OnProtocolSelected += (o, args) => { _selectedProtocol = args.SelectedProtocol; }; socket.Connect(new DnsEndPoint(connectUri.Host, connectUri.Port), monitor); _clientStream = new DuplexStream(socket, true); if (_useHandshake) { MakeHandshakeEnvironment(); //Handshake manager determines what handshake must be used: upgrade or secure if (socket.SecureProtocol != SecureProtocol.None) { socket.MakeSecureHandshake(Options); _selectedProtocol = socket.SelectedProtocol; } if (socket.SecureProtocol == SecureProtocol.None || _selectedProtocol == Protocols.Http1) { try { var handshakeResult = new UpgradeHandshaker(_environment).Handshake(); _environment.Add(HandshakeKeys.Result, handshakeResult); _useHttp20 = handshakeResult[HandshakeKeys.Successful] as string == HandshakeKeys.True; if (!_useHttp20) { Dispose(false); return true; } } catch (Http2HandshakeFailed ex) { if (ex.Reason == HandshakeFailureReason.InternalError) { _useHttp20 = false; } else { Http2Logger.LogError("Specified server did not respond"); Dispose(true); return false; } } } } } Http2Logger.LogDebug("Handshake finished"); if (_useHttp20) { //TODO provide transport info _sessionAdapter = new Http2ClientMessageHandler(_clientStream, ConnectionEnd.Client, default(TransportInformation), CancellationToken.None); } } catch (SocketException) { Http2Logger.LogError("Check if any server listens port " + connectUri.Port); Dispose(true); return false; } catch (Exception ex) { Http2Logger.LogError("Unknown connection exception was caught: " + ex.Message); Dispose(true); return false; } return true; }
public static DuplexStream GetHandshakedDuplexStream(string address, bool allowHttp2Communication = true, bool useMock = false) { string selectedProtocol = null; var extensions = new[] { ExtensionType.Renegotiation, ExtensionType.ALPN }; var useHandshake = ConfigurationManager.AppSettings["handshakeOptions"] != "no-handshake"; var protocols = new List<string> { Protocols.Http1 }; if (allowHttp2Communication) { protocols.Add(Protocols.Http2); } var options = UseSecurePort ? new SecurityOptions(SecureProtocol.Tls1, extensions, protocols, ConnectionEnd.Client) : new SecurityOptions(SecureProtocol.None, extensions, protocols, ConnectionEnd.Client); options.VerificationType = CredentialVerification.None; options.Certificate = Org.Mentalis.Security.Certificates.Certificate.CreateFromCerFile(@"certificate.pfx"); options.Flags = SecurityFlags.Default; options.AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION; var sessionSocket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, options); using (var monitor = new ALPNExtensionMonitor()) { monitor.OnProtocolSelected += (sender, args) => { selectedProtocol = args.SelectedProtocol; }; var uri = new Uri(GetAddress() + address); sessionSocket.Connect(new DnsEndPoint(uri.Host, uri.Port), monitor); if (useHandshake) { sessionSocket.MakeSecureHandshake(options); } } //SendSessionHeader(sessionSocket); return useMock ? new Mock<DuplexStream>(sessionSocket, true).Object : new DuplexStream(sessionSocket, true); }