internal virtual async Task BindAsync(AddressBindContext context) { await AddressBinder.BindEndpointAsync(this, context).ConfigureAwait(false); context.Addresses.Add(GetDisplayName()); }
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 options) { // INVESTIGATE: For some reason, MsQuic needs to bind before // sockets for it to successfully listen. It also seems racy. if ((options.Protocols & HttpProtocols.Http3) == HttpProtocols.Http3) { if (_multiplexedTransportFactory is null) { throw new InvalidOperationException($"Cannot start HTTP/3 server if no {nameof(IMultiplexedConnectionListenerFactory)} is registered."); } options.UseHttp3Server(ServiceContext, application, options.Protocols); var multiplexedConnectionDelegate = ((IMultiplexedConnectionBuilder)options).Build(); // Add the connection limit middleware multiplexedConnectionDelegate = EnforceConnectionLimit(multiplexedConnectionDelegate, Options.Limits.MaxConcurrentConnections, Trace); options.EndPoint = await _transportManager.BindAsync(options.EndPoint, multiplexedConnectionDelegate, options.EndpointConfig).ConfigureAwait(false); } // Add the HTTP middleware as the terminal connection middleware if ((options.Protocols & HttpProtocols.Http1) == HttpProtocols.Http1 || (options.Protocols & HttpProtocols.Http2) == HttpProtocols.Http2 || options.Protocols == HttpProtocols.None) // TODO a test fails because it doesn't throw an exception in the right place // when there is no HttpProtocols in KestrelServer, can we remove/change the test? { if (_transportFactory is null) { throw new InvalidOperationException($"Cannot start HTTP/1.x or HTTP/2 server if no {nameof(IConnectionListenerFactory)} is registered."); } options.UseHttpServer(ServiceContext, application, options.Protocols); var connectionDelegate = options.Build(); // Add the connection limit middleware connectionDelegate = EnforceConnectionLimit(connectionDelegate, Options.Limits.MaxConcurrentConnections, Trace); options.EndPoint = await _transportManager.BindAsync(options.EndPoint, connectionDelegate, options.EndpointConfig).ConfigureAwait(false); } } AddressBindContext = new AddressBindContext { ServerAddressesFeature = _serverAddresses, ServerOptions = Options, Logger = Trace, CreateBinding = OnBind, }; await BindAsync(cancellationToken).ConfigureAwait(false); } catch (Exception ex) { Trace.LogCritical(0, ex, "Unable to start Kestrel."); Dispose(); throw; } }