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>();
            await AddressBinder.BindAsync(addresses, options, logger, listenOptions =>
            {
                endpoints.Add(listenOptions);
                return(Task.CompletedTask);
            });

            Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5000 && !e.IsTls);
            Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5001 && e.IsTls);
        }
示例#2
0
        private async Task BindAsync(CancellationToken cancellationToken)
        {
            await _bindSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                if (_stopping == 1)
                {
                    throw new InvalidOperationException("Kestrel has already been stopped.");
                }

                IChangeToken?reloadToken = null;

                _serverAddresses.InternalCollection.PreventPublicMutation();

                if (Options.ConfigurationLoader?.ReloadOnChange == true && (!_serverAddresses.PreferHostingUrls || _serverAddresses.InternalCollection.Count == 0))
                {
                    reloadToken = Options.ConfigurationLoader.Configuration.GetReloadToken();
                }

                Options.ConfigurationLoader?.Load();

                await AddressBinder.BindAsync(Options.ListenOptions, AddressBindContext !, cancellationToken).ConfigureAwait(false);

                _configChangedRegistration = reloadToken?.RegisterChangeCallback(TriggerRebind, this);
            }
            finally
            {
                _bindSemaphore.Release();
            }
        }
示例#3
0
    public void LogsInformationWhenKestrelAddressesAreOverridden()
    {
        var logger = new TestApplicationErrorLogger();

        var overriddenAddress = "http://localhost:5000";
        var addresses         = new ServerAddressesFeature();

        addresses.InternalCollection.Add(overriddenAddress);

        var options = new KestrelServerOptions();

        options.ListenAnyIP(8080);

        var addressBindContext = TestContextFactory.CreateAddressBindContext(
            addresses,
            options,
            logger,
            endpoint => Task.CompletedTask);

        addressBindContext.ServerAddressesFeature.PreferHostingUrls = true;

        var bindTask = AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None);

        Assert.True(bindTask.IsCompletedSuccessfully);

        var log = Assert.Single(logger.Messages);

        Assert.Equal(LogLevel.Information, log.LogLevel);
        Assert.Equal(CoreStrings.FormatOverridingWithPreferHostingUrls(nameof(addressBindContext.ServerAddressesFeature.PreferHostingUrls), overriddenAddress), log.Message);
    }
        public async Task FallbackToIPv4WhenIPv6AnyBindFails(string address)
        {
            var logger    = new MockLogger();
            var addresses = new ServerAddressesFeature();

            addresses.Addresses.Add(address);
            var options = new KestrelServerOptions();

            var ipV6Attempt = false;
            var ipV4Attempt = false;

            await AddressBinder.BindAsync(addresses,
                                          options,
                                          logger,
                                          endpoint =>
            {
                if (endpoint.IPEndPoint.Address == IPAddress.IPv6Any)
                {
                    ipV6Attempt = true;
                    throw new InvalidOperationException("EAFNOSUPPORT");
                }

                if (endpoint.IPEndPoint.Address == IPAddress.Any)
                {
                    ipV4Attempt = true;
                }

                return(Task.CompletedTask);
            });

            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)));
        }
示例#5
0
    public async Task DefaultAddressBinderBindsToHttpPort5000()
    {
        var logger    = new MockLogger();
        var addresses = new ServerAddressesFeature();
        var services  = new ServiceCollection();

        services.AddLogging();
        var options = new KestrelServerOptions()
        {
            ApplicationServices = services.BuildServiceProvider()
        };

        var endpoints = new List <ListenOptions>();

        var addressBindContext = TestContextFactory.CreateAddressBindContext(
            addresses,
            options,
            logger,
            listenOptions =>
        {
            endpoints.Add(listenOptions);
            return(Task.CompletedTask);
        });

        await AddressBinder.BindAsync(options.ListenOptions, addressBindContext, CancellationToken.None);

        Assert.Contains(endpoints, e => e.IPEndPoint.Port == 5000 && !e.IsTls);
    }
        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;
            }
        }
示例#8
0
    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));
    }
示例#9
0
        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));
        }
示例#10
0
        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;
            }
        }
示例#11
0
    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)));
    }
示例#12
0
        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);
        }
示例#13
0
        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;
            }
        }