| File: Internal\NamedPipeTransportFactory.cs | Web Access |
| Project: src\aspnetcore\src\Servers\Kestrel\Transport.NamedPipes\src\Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes.csproj (Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Net; using Microsoft.AspNetCore.Connections; using Microsoft.Extensions.Logging; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes.Internal; internal sealed class NamedPipeTransportFactory : IConnectionListenerFactory, IConnectionListenerFactorySelector { private const string LocalComputerServerName = "."; private readonly ILoggerFactory _loggerFactory; private readonly ObjectPoolProvider _objectPoolProvider; private readonly NamedPipeTransportOptions _options; public NamedPipeTransportFactory( ILoggerFactory loggerFactory, IOptions<NamedPipeTransportOptions> options, ObjectPoolProvider objectPoolProvider) { ArgumentNullException.ThrowIfNull(loggerFactory); Debug.Assert(OperatingSystem.IsWindows(), "Named pipes transport requires a Windows operating system."); _loggerFactory = loggerFactory; _objectPoolProvider = objectPoolProvider; _options = options.Value; } public ValueTask<IConnectionListener> BindAsync(EndPoint endpoint, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(endpoint); if (endpoint is not NamedPipeEndPoint namedPipeEndPoint) { throw new NotSupportedException($"{endpoint.GetType()} is not supported."); } if (namedPipeEndPoint.ServerName != LocalComputerServerName) { throw new NotSupportedException($@"Server name '{namedPipeEndPoint.ServerName}' is invalid. The server name must be ""{LocalComputerServerName}""."); } var listener = new NamedPipeConnectionListener(namedPipeEndPoint, _options, _loggerFactory, _objectPoolProvider); // Start the listener and create NamedPipeServerStream instances immediately. // The first server stream is created with the FirstPipeInstance flag. The FirstPipeInstance flag ensures // that no other apps have a running pipe with the configured name. This check is important because: // 1. Some settings, such as ACL, are chosen by the first pipe to start with a given name. // 2. It's easy to run two Kestrel app instances. Want to avoid two apps listening on the same pipe and creating confusion. // The second launched app instance should immediately fail with an error message, just like port binding conflicts. try { listener.Start(); } catch (UnauthorizedAccessException ex) { throw new AddressInUseException($"Named pipe '{namedPipeEndPoint.PipeName}' is already in use.", ex); } return new ValueTask<IConnectionListener>(listener); } public bool CanBind(EndPoint endpoint) { ArgumentNullException.ThrowIfNull(endpoint); return endpoint is NamedPipeEndPoint; } }