public void ParseAddressIP(string address, string ip, int port, bool isHttps) { var listenOptions = AddressBinder.ParseAddress(address, out var https); Assert.IsType <IPEndPoint>(listenOptions.EndPoint); Assert.Equal(IPAddress.Parse(ip), listenOptions.IPEndPoint.Address); Assert.Equal(port, listenOptions.IPEndPoint.Port); Assert.Equal(isHttps, https); }
public void ParseAddressUnixPipe() { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress("http://unix:/tmp/kestrel-test.sock", out var https); Assert.Equal(ListenType.SocketPath, listenOptions.Type); Assert.Equal("/tmp/kestrel-test.sock", listenOptions.SocketPath); Assert.False(https); }
public void ParseAddressIP(string address, string ip, int port) { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress(address, options, Mock.Of <IDefaultHttpsProvider>()); Assert.Equal(ListenType.IPEndPoint, listenOptions.Type); Assert.Equal(IPAddress.Parse(ip), listenOptions.IPEndPoint.Address); Assert.Equal(port, listenOptions.IPEndPoint.Port); }
public void ParseAddressIP(string address, string ip, int port, bool isHttps) { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress(address, out var https); Assert.Equal(ListenType.IPEndPoint, listenOptions.Type); Assert.Equal(IPAddress.Parse(ip), listenOptions.IPEndPoint.Address); Assert.Equal(port, listenOptions.IPEndPoint.Port); Assert.Equal(isHttps, https); }
public void ParseAddressDefaultsToAnyIPOnInvalidIPAddress(string host) { var listenOptions = AddressBinder.ParseAddress($"http://{host}", out var https); Assert.IsType <AnyIPListenOptions>(listenOptions); Assert.IsType <IPEndPoint>(listenOptions.EndPoint); Assert.Equal(IPAddress.IPv6Any, listenOptions.IPEndPoint.Address); Assert.Equal(80, listenOptions.IPEndPoint.Port); Assert.False(https); }
public void ParseAddressLocalhost() { var listenOptions = AddressBinder.ParseAddress("http://localhost", out var https); Assert.IsType <LocalhostListenOptions>(listenOptions); Assert.IsType <IPEndPoint>(listenOptions.EndPoint); Assert.Equal(IPAddress.Loopback, listenOptions.IPEndPoint.Address); Assert.Equal(80, listenOptions.IPEndPoint.Port); Assert.False(https); }
public void ParseAddressLocalhost() { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress("http://localhost", options, Mock.Of <IDefaultHttpsProvider>()); Assert.IsType <LocalhostListenOptions>(listenOptions); Assert.Equal(ListenType.IPEndPoint, listenOptions.Type); Assert.Equal(IPAddress.Loopback, listenOptions.IPEndPoint.Address); Assert.Equal(80, listenOptions.IPEndPoint.Port); }
public void ParseAddressDefaultsToAnyIPOnInvalidIPAddress(string host) { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress($"http://{host}", options, Mock.Of <IDefaultHttpsProvider>()); Assert.IsType <AnyIPListenOptions>(listenOptions); Assert.Equal(ListenType.IPEndPoint, listenOptions.Type); Assert.Equal(IPAddress.IPv6Any, listenOptions.IPEndPoint.Address); Assert.Equal(80, listenOptions.IPEndPoint.Port); }
public void Load() { if (Options.ConfigurationLoader == null) { // The loader has already been run. return; } Options.ConfigurationLoader = null; var configReader = new ConfigurationReader(Configuration); LoadDefaultCert(configReader); foreach (var endpoint in configReader.Endpoints) { var listenOptions = AddressBinder.ParseAddress(endpoint.Url, out var https); Options.ApplyEndpointDefaults(listenOptions); // Compare to UseHttps(httpsOptions => { }) var httpsOptions = new HttpsConnectionAdapterOptions(); if (https) { // Defaults Options.ApplyHttpsDefaults(httpsOptions); // Specified httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name) ?? httpsOptions.ServerCertificate; } if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint)) { var endpointConfig = new EndpointConfiguration(https, listenOptions, httpsOptions, endpoint.ConfigSection); configureEndpoint(endpointConfig); } // EndpointDefaults or configureEndpoint may have added an https adapter. if (https && !listenOptions.ConnectionAdapters.Any(f => f.IsHttps)) { if (httpsOptions.ServerCertificate == null) { throw new InvalidOperationException(CoreStrings.NoCertSpecifiedNoDevelopmentCertificateFound); } listenOptions.UseHttps(httpsOptions); } Options.ListenOptions.Add(listenOptions); } foreach (var action in EndpointsToAdd) { action(); } }
public void ParseAddressLocalhost() { var options = new KestrelServerOptions(); var listenOptions = AddressBinder.ParseAddress("http://localhost", out var https); Assert.IsType <LocalhostListenOptions>(listenOptions); Assert.Equal(ListenType.IPEndPoint, listenOptions.Type); Assert.Equal(IPAddress.Loopback, listenOptions.IPEndPoint.Address); Assert.Equal(80, listenOptions.IPEndPoint.Port); Assert.False(https); }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.Addresses.Add("http://localhost:5000"); var options = new KestrelServerOptions(); await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(addresses, options, NullLogger.Instance, endpoint => throw new AddressInUseException("already in use"))); }
public async Task StartAsync <TContext>(IHttpApplication <TContext> application, CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException(CoreStrings.BigEndianNotSupported); } ValidateOptions(); if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException(CoreStrings.ServerAlreadyStarted); } _hasStarted = true; ServiceContext.Heartbeat?.Start(); async Task OnBind(ListenOptions endpoint) { // Add the HTTP middleware as the terminal connection middleware endpoint.UseHttpServer(endpoint.ConnectionAdapters, ServiceContext, application, endpoint.Protocols); var connectionDelegate = endpoint.Build(); // Add the connection limit middleware if (Options.Limits.MaxConcurrentConnections.HasValue) { connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync; } var connectionDispatcher = new ConnectionDispatcher(ServiceContext, connectionDelegate); var transport = _transportFactory.Create(endpoint, connectionDispatcher); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }
public void Load() { if (_loaded) { return; } _loaded = true; LoadDefaultCert(ConfigurationReader); foreach (var endpoint in ConfigurationReader.Endpoints) { var listenOptions = AddressBinder.ParseAddress(endpoint.Url, out var https); Options.ApplyEndpointDefaults(listenOptions); if (endpoint.Protocols.HasValue) { listenOptions.Protocols = endpoint.Protocols.Value; } var httpsOptions = new HttpsConnectionAdapterOptions(); if (https) { Options.ApplyHttpsDefaults(httpsOptions); httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name) ?? httpsOptions.ServerCertificate; Options.ApplyDefaultCert(httpsOptions); } if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint)) { var endpointConfig = new EndpointConfiguration(https, listenOptions, httpsOptions); configureEndpoint(endpointConfig); } if (https && !listenOptions.IsTls) { if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { throw new InvalidOperationException("Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.\nTo generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.\nFor more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054."); } listenOptions.UseHttps(httpsOptions); } Options.ListenOptions.Add(listenOptions); } foreach (var action in EndpointsToAdd) { action(); } }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, NullLogger.Instance, endpoint => throw new AddressInUseException("already in use")); await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None)); }
public async Task WrapsAddressInUseExceptionAsIOException() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = new AddressBindContext { ServerAddressesFeature = addresses, ServerOptions = options, Logger = NullLogger.Instance, CreateBinding = endpoint => throw new AddressInUseException("already in use"), }; await Assert.ThrowsAsync <IOException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext)); }
public async Task DefaultAddressBinderWithoutDevCertButHttpsConfiguredBindsToHttpsPorts() { var x509Certificate2 = TestResources.GetTestCertificate(); var logger = new MockLogger(); var addresses = new ServerAddressesFeature(); var services = new ServiceCollection(); services.AddLogging(); var options = new KestrelServerOptions() { // This stops the dev cert from being loaded IsDevCertLoaded = true, ApplicationServices = services.BuildServiceProvider() }; options.ConfigureEndpointDefaults(e => { if (e.IPEndPoint.Port == 5001) { e.UseHttps(new HttpsConnectionAdapterOptions { ServerCertificate = x509Certificate2 }); } }); var endpoints = new List <ListenOptions>(); var addressBindContext = new AddressBindContext { ServerAddressesFeature = addresses, ServerOptions = options, Logger = logger, CreateBinding = listenOptions => { endpoints.Add(listenOptions); return(Task.CompletedTask); }, }; await AddressBinder.BindAsync(options.ListenOptions, addressBindContext); Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5000 && !e.IsTls); Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5001 && e.IsTls); }
public async Task StartAsync(CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException("Does not support big-endian architectures."); } if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException("Server has already started."); } _hasStarted = true; _heartbeat.Start(); async Task OnBind(ListenOptions endpoint) { var connectionDelegate = endpoint.Build(); // Add the connection limit middleware if (Options.Limits.MaxConcurrentConnections.HasValue) { connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync; } var connectionDispatcher = new ConnectionDispatcher(ServiceContext, connectionDelegate); var transport = _transportFactory.Create(endpoint, connectionDispatcher); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }
public async Task FlowsCancellationTokenToCreateBinddingCallback() { var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add("http://localhost:5000"); var options = new KestrelServerOptions(); var addressBindContext = TestContextFactory.CreateAddressBindContext( addresses, options, NullLogger.Instance, (endpoint, cancellationToken) => { cancellationToken.ThrowIfCancellationRequested(); return(Task.CompletedTask); }); await Assert.ThrowsAsync <OperationCanceledException>(() => AddressBinder.BindAsync(options.ListenOptions, addressBindContext, new CancellationToken(true))); }
public async Task DefaultsToIPv6AnyOnInvalidIPAddress(string host) { var addresses = new ServerAddressesFeature(); addresses.Addresses.Add($"http://{host}"); var options = new List <ListenOptions>(); var tcs = new TaskCompletionSource <ListenOptions>(); await AddressBinder.BindAsync(addresses, options, NullLogger.Instance, endpoint => { tcs.TrySetResult(endpoint); return(Task.CompletedTask); }); var result = await tcs.Task; Assert.Equal(IPAddress.IPv6Any, result.IPEndPoint.Address); }
public async Task FallbackToIPv4WhenIPv6AnyBindFails(string address) { var logger = new MockLogger(); var addresses = new ServerAddressesFeature(); addresses.InternalCollection.Add(address); var options = new KestrelServerOptions(); var ipV6Attempt = false; var ipV4Attempt = false; var addressBindContext = new AddressBindContext { ServerAddressesFeature = addresses, ServerOptions = options, Logger = logger, CreateBinding = endpoint => { if (endpoint.IPEndPoint.Address == IPAddress.IPv6Any) { ipV6Attempt = true; throw new InvalidOperationException("EAFNOSUPPORT"); } if (endpoint.IPEndPoint.Address == IPAddress.Any) { ipV4Attempt = true; } return(Task.CompletedTask); }, }; await AddressBinder.BindAsync(options.ListenOptions, addressBindContext); Assert.True(ipV4Attempt, "Should have attempted to bind to IPAddress.Any"); Assert.True(ipV6Attempt, "Should have attempted to bind to IPAddress.IPv6Any"); Assert.Contains(logger.Messages, f => f.Equals(CoreStrings.FormatFallbackToIPv4Any(80))); }
public async Task StartAsync <TContext>(IHttpApplication <TContext> application, CancellationToken cancellationToken) { try { if (!BitConverter.IsLittleEndian) { throw new PlatformNotSupportedException(CoreStrings.BigEndianNotSupported); } ValidateOptions(); if (_hasStarted) { // The server has already started and/or has not been cleaned up yet throw new InvalidOperationException(CoreStrings.ServerAlreadyStarted); } _hasStarted = true; _heartbeat.Start(); async Task OnBind(ListenOptions endpoint) { var connectionHandler = new ConnectionHandler <TContext>(endpoint, ServiceContext, application); var transport = _transportFactory.Create(endpoint, connectionHandler); _transports.Add(transport); await transport.BindAsync().ConfigureAwait(false); } await AddressBinder.BindAsync(_serverAddresses, Options.ListenOptions, Trace, OnBind).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }
internal virtual async Task BindAsync(AddressBindContext context) { await AddressBinder.BindEndpointAsync(this, context).ConfigureAwait(false); context.Addresses.Add(GetDisplayName()); }
public void DoesNotCreateIPEndPointOnInvalidIPAddress(string address) { Assert.False(AddressBinder.TryCreateIPEndPoint( BindingAddress.Parse(address), out var endpoint)); }
public void Load() { if (_loaded) { // The loader has already been run. return; } _loaded = true; Options.Latin1RequestHeaders = ConfigurationReader.Latin1RequestHeaders; LoadDefaultCert(ConfigurationReader); foreach (var endpoint in ConfigurationReader.Endpoints) { var listenOptions = AddressBinder.ParseAddress(endpoint.Url, out var https); Options.ApplyEndpointDefaults(listenOptions); if (endpoint.Protocols.HasValue) { listenOptions.Protocols = endpoint.Protocols.Value; } // Compare to UseHttps(httpsOptions => { }) var httpsOptions = new HttpsConnectionAdapterOptions(); if (https) { // Defaults Options.ApplyHttpsDefaults(httpsOptions); // Specified httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name) ?? httpsOptions.ServerCertificate; // Fallback Options.ApplyDefaultCert(httpsOptions); } if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint)) { var endpointConfig = new EndpointConfiguration(https, listenOptions, httpsOptions, endpoint.ConfigSection); configureEndpoint(endpointConfig); } // EndpointDefaults or configureEndpoint may have added an https adapter. if (https && !listenOptions.IsTls) { if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { throw new InvalidOperationException(CoreStrings.NoCertSpecifiedNoDevelopmentCertificateFound); } listenOptions.UseHttps(httpsOptions); } Options.ListenOptions.Add(listenOptions); } foreach (var action in EndpointsToAdd) { action(); } }
public void DoesNotCreateIPEndPointOnInvalidIPAddress(string address) { Assert.False(AddressBinder.TryCreateIPEndPoint( ServerAddress.FromUrl(address), out var endpoint)); }
// Adds endpoints from config to KestrelServerOptions.ConfigurationBackedListenOptions and configures some other options. // Any endpoints that were removed from the last time endpoints were loaded are returned. internal (List <ListenOptions>, List <ListenOptions>) Reload() { var endpointsToStop = Options.ConfigurationBackedListenOptions.ToList(); var endpointsToStart = new List <ListenOptions>(); Options.ConfigurationBackedListenOptions.Clear(); DefaultCertificateConfig = null; ConfigurationReader = new ConfigurationReader(Configuration); Options.Latin1RequestHeaders = ConfigurationReader.Latin1RequestHeaders; LoadDefaultCert(ConfigurationReader); foreach (var endpoint in ConfigurationReader.Endpoints) { var listenOptions = AddressBinder.ParseAddress(endpoint.Url, out var https); Options.ApplyEndpointDefaults(listenOptions); if (endpoint.Protocols.HasValue) { listenOptions.Protocols = endpoint.Protocols.Value; } else { // Ensure endpoint is reloaded if it used the default protocol and the protocol changed. // listenOptions.Protocols should already be set to this by ApplyEndpointDefaults. endpoint.Protocols = ConfigurationReader.EndpointDefaults.Protocols; } // Compare to UseHttps(httpsOptions => { }) var httpsOptions = new HttpsConnectionAdapterOptions(); if (https) { // Defaults Options.ApplyHttpsDefaults(httpsOptions); // Specified httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name) ?? httpsOptions.ServerCertificate; if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { // Fallback Options.ApplyDefaultCert(httpsOptions); // Ensure endpoint is reloaded if it used the default certificate and the certificate changed. endpoint.Certificate = DefaultCertificateConfig; } } // Now that defaults have been loaded, we can compare to the currently bound endpoints to see if the config changed. // There's no reason to rerun an EndpointConfigurations callback if nothing changed. var matchingBoundEndpoints = endpointsToStop.Where(o => o.EndpointConfig == endpoint).ToList(); if (matchingBoundEndpoints.Count > 0) { endpointsToStop.RemoveAll(o => o.EndpointConfig == endpoint); Options.ConfigurationBackedListenOptions.AddRange(matchingBoundEndpoints); continue; } if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint)) { var endpointConfig = new EndpointConfiguration(https, listenOptions, httpsOptions, endpoint.ConfigSection); configureEndpoint(endpointConfig); } // EndpointDefaults or configureEndpoint may have added an https adapter. if (https && !listenOptions.IsTls) { if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { throw new InvalidOperationException(CoreStrings.NoCertSpecifiedNoDevelopmentCertificateFound); } listenOptions.UseHttps(httpsOptions); } listenOptions.EndpointConfig = endpoint; endpointsToStart.Add(listenOptions); Options.ConfigurationBackedListenOptions.Add(listenOptions); } return(endpointsToStop, endpointsToStart); }
// Adds endpoints from config to KestrelServerOptions.ConfigurationBackedListenOptions and configures some other options. // Any endpoints that were removed from the last time endpoints were loaded are returned. internal (List <ListenOptions>, List <ListenOptions>) Reload() { var endpointsToStop = Options.ConfigurationBackedListenOptions.ToList(); var endpointsToStart = new List <ListenOptions>(); Options.ConfigurationBackedListenOptions.Clear(); DefaultCertificateConfig = null; ConfigurationReader = new ConfigurationReader(Configuration); LoadDefaultCert(); foreach (var endpoint in ConfigurationReader.Endpoints) { var listenOptions = AddressBinder.ParseAddress(endpoint.Url, out var https); if (!https) { ConfigurationReader.ThrowIfContainsHttpsOnlyConfiguration(endpoint); } Options.ApplyEndpointDefaults(listenOptions); if (endpoint.Protocols.HasValue) { listenOptions.Protocols = endpoint.Protocols.Value; } else { // Ensure endpoint is reloaded if it used the default protocol and the protocol changed. // listenOptions.Protocols should already be set to this by ApplyEndpointDefaults. endpoint.Protocols = ConfigurationReader.EndpointDefaults.Protocols; } // Compare to UseHttps(httpsOptions => { }) var httpsOptions = new HttpsConnectionAdapterOptions(); if (https) { // Defaults Options.ApplyHttpsDefaults(httpsOptions); if (endpoint.SslProtocols.HasValue) { httpsOptions.SslProtocols = endpoint.SslProtocols.Value; } else { // Ensure endpoint is reloaded if it used the default protocol and the SslProtocols changed. endpoint.SslProtocols = ConfigurationReader.EndpointDefaults.SslProtocols; } if (endpoint.ClientCertificateMode.HasValue) { httpsOptions.ClientCertificateMode = endpoint.ClientCertificateMode.Value; } else { // Ensure endpoint is reloaded if it used the default mode and the ClientCertificateMode changed. endpoint.ClientCertificateMode = ConfigurationReader.EndpointDefaults.ClientCertificateMode; } // A cert specified directly on the endpoint overrides any defaults. httpsOptions.ServerCertificate = CertificateConfigLoader.LoadCertificate(endpoint.Certificate, endpoint.Name) ?? httpsOptions.ServerCertificate; if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { // Fallback Options.ApplyDefaultCert(httpsOptions); // Ensure endpoint is reloaded if it used the default certificate and the certificate changed. endpoint.Certificate = DefaultCertificateConfig; } } // Now that defaults have been loaded, we can compare to the currently bound endpoints to see if the config changed. // There's no reason to rerun an EndpointConfigurations callback if nothing changed. var matchingBoundEndpoints = endpointsToStop.Where(o => o.EndpointConfig == endpoint).ToList(); if (matchingBoundEndpoints.Count > 0) { endpointsToStop.RemoveAll(o => o.EndpointConfig == endpoint); Options.ConfigurationBackedListenOptions.AddRange(matchingBoundEndpoints); continue; } if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint)) { var endpointConfig = new EndpointConfiguration(https, listenOptions, httpsOptions, endpoint.ConfigSection); configureEndpoint(endpointConfig); } // EndpointDefaults or configureEndpoint may have added an https adapter. if (https && !listenOptions.IsTls) { if (endpoint.Sni.Count == 0) { if (httpsOptions.ServerCertificate == null && httpsOptions.ServerCertificateSelector == null) { throw new InvalidOperationException(CoreStrings.NoCertSpecifiedNoDevelopmentCertificateFound); } listenOptions.UseHttps(httpsOptions); } else { var sniOptionsSelector = new SniOptionsSelector(endpoint.Name, endpoint.Sni, CertificateConfigLoader, httpsOptions, listenOptions.Protocols, HttpsLogger); var tlsCallbackOptions = new TlsHandshakeCallbackOptions() { OnConnection = SniOptionsSelector.OptionsCallback, HandshakeTimeout = httpsOptions.HandshakeTimeout, OnConnectionState = sniOptionsSelector, }; listenOptions.UseHttps(tlsCallbackOptions); } } listenOptions.EndpointConfig = endpoint; endpointsToStart.Add(listenOptions); Options.ConfigurationBackedListenOptions.Add(listenOptions); } return(endpointsToStop, endpointsToStart); }