From 9ade227abbba385bd42cbeb3b79ada721f40b7a3 Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 15 Aug 2015 15:50:34 -0700 Subject: [PATCH] Implement support for UNIX sockets. The common use-case for Kestrel in production will be behind a reverse proxy such as Nginx. In cases where the reverse proxy is located on the same machine as the application, connecting via a UNIX socket is more efficient than a TCP socket, as it avoids going through the network layer. Accessing 127.0.0.1 through TCP still needs to initiate a TCP connection and perform handshaking, checksumming, etc, all of which is avoided by using UNIX sockets. - Moved TCP-specific stuff from Listener into new TcpListener class (same with ListenerPrimary and ListenerSecondary) - Made Listener abstract - Created new PipeListener. Note that while the use case is for UNIX sockets, this is called "Pipe" in uv, so I've called this "PipeListener" so the terminology is consistant - Uses "unix" URL scheme to determine whether to use socket. "http://127.0.0.1:5000" is for listening via TCP while "unix:///var/run/kestrel-test.sock" is for listening via UNIX socket #156 --- samples/SampleApp/project.json | 1 + .../Http/IListener.cs | 21 +++++++++ .../Http/IListenerPrimary.cs | 23 ++++++++++ .../Http/IListenerSecondary.cs | 20 +++++++++ .../Http/Listener.cs | 41 ++++++++--------- .../Http/ListenerPrimary.cs | 12 +++-- .../Http/ListenerSecondary.cs | 16 +++++-- .../Http/PipeListener.cs | 44 ++++++++++++++++++ .../Http/PipeListenerPrimary.cs | 44 ++++++++++++++++++ .../Http/PipeListenerSecondary.cs | 27 +++++++++++ .../Http/TcpListener.cs | 45 +++++++++++++++++++ .../Http/TcpListenerPrimary.cs | 45 +++++++++++++++++++ .../Http/TcpListenerSecondary.cs | 27 +++++++++++ .../Infrastructure/Constants.cs | 11 +++-- .../KestrelEngine.cs | 17 ++++--- .../ServerFactory.cs | 5 ++- 16 files changed, 358 insertions(+), 41 deletions(-) create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/IListener.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/IListenerPrimary.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/IListenerSecondary.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/PipeListener.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerPrimary.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerSecondary.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs create mode 100644 src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerSecondary.cs diff --git a/samples/SampleApp/project.json b/samples/SampleApp/project.json index b7e9f3b993..7a325b00e7 100644 --- a/samples/SampleApp/project.json +++ b/samples/SampleApp/project.json @@ -13,6 +13,7 @@ }, "commands": { "run": "Microsoft.AspNet.Server.Kestrel", + "run-socket": "Microsoft.AspNet.Server.Kestrel --server.urls unix:///tmp/kestrel-test.sock", "kestrel": "Microsoft.AspNet.Server.Kestrel", "web": "Microsoft.AspNet.Hosting" } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/IListener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/IListener.cs new file mode 100644 index 0000000000..ccd6d104d4 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/IListener.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// A listener waits for incoming connections on a specified socket. + /// + public interface IListener : IDisposable + { + Task StartAsync( + string scheme, + string host, + int port, + KestrelThread thread, + Func application); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerPrimary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerPrimary.cs new file mode 100644 index 0000000000..7a42fe02ef --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerPrimary.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// A primary listener waits for incoming connections on a specified socket. Incoming + /// connections may be passed to a secondary listener to handle. + /// + public interface IListenerPrimary : IListener + { + Task StartAsync( + string pipeName, + string scheme, + string host, + int port, + KestrelThread thread, + Func application); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerSecondary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerSecondary.cs new file mode 100644 index 0000000000..3230a7e1bc --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/IListenerSecondary.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// A secondary listener is delegated requests from a primary listener via a named pipe or + /// UNIX domain socket. + /// + public interface IListenerSecondary : IDisposable + { + Task StartAsync( + string pipeName, + KestrelThread thread, + Func application); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs index 370c62ac0d..dd0d6f0228 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs @@ -1,25 +1,22 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.Server.Kestrel.Infrastructure; using Microsoft.AspNet.Server.Kestrel.Networking; using System; using System.Diagnostics; -using System.Net; using System.Threading.Tasks; namespace Microsoft.AspNet.Server.Kestrel.Http { /// - /// Summary description for Accept + /// Base class for listeners in Kestrel. Listens for incoming connections /// - public class Listener : ListenerContext, IDisposable + /// Type of socket used by this listener + public abstract class Listener : ListenerContext, IListener where T : UvStreamHandle { - private static readonly Action _connectionCallback = ConnectionCallback; + protected T ListenSocket { get; private set; } - UvTcpHandle ListenSocket { get; set; } - - private static void ConnectionCallback(UvStreamHandle stream, int status, Exception error, object state) + protected static void ConnectionCallback(UvStreamHandle stream, int status, Exception error, object state) { if (error != null) { @@ -27,11 +24,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } else { - ((Listener)state).OnConnection(stream, status); + ((Listener)state).OnConnection((T)stream, status); } } - public Listener(IMemoryPool memory) + protected Listener(IMemoryPool memory) { Memory = memory; } @@ -51,10 +48,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { try { - ListenSocket = new UvTcpHandle(); - ListenSocket.Init(Thread.Loop, Thread.QueueCloseHandle); - ListenSocket.Bind(new IPEndPoint(IPAddress.Any, port)); - ListenSocket.Listen(Constants.ListenBacklog, _connectionCallback, this); + ListenSocket = CreateListenSocket(host, port); tcs.SetResult(0); } catch (Exception ex) @@ -65,16 +59,19 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return tcs.Task; } - private void OnConnection(UvStreamHandle listenSocket, int status) - { - var acceptSocket = new UvTcpHandle(); - acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle); - listenSocket.Accept(acceptSocket); + /// + /// Creates the socket used to listen for incoming connections + /// + protected abstract T CreateListenSocket(string host, int port); - DispatchConnection(acceptSocket); - } + /// + /// Handles an incoming connection + /// + /// Socket being used to listen on + /// Connection status + protected abstract void OnConnection(T listenSocket, int status); - protected virtual void DispatchConnection(UvTcpHandle socket) + protected virtual void DispatchConnection(T socket) { var connection = new Connection(this, socket); connection.Start(); diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerPrimary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerPrimary.cs index f1299c073b..c534affe49 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerPrimary.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerPrimary.cs @@ -9,7 +9,11 @@ using System.Threading.Tasks; namespace Microsoft.AspNet.Server.Kestrel.Http { - public class ListenerPrimary : Listener + /// + /// A primary listener waits for incoming connections on a specified socket. Incoming + /// connections may be passed to a secondary listener to handle. + /// + abstract public class ListenerPrimary : Listener, IListenerPrimary where T : UvStreamHandle { UvPipeHandle ListenPipe { get; set; } @@ -17,7 +21,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http int _dispatchIndex; ArraySegment> _1234 = new ArraySegment>(new[] { new ArraySegment(new byte[] { 1, 2, 3, 4 }) }); - public ListenerPrimary(IMemoryPool memory) : base(memory) + protected ListenerPrimary(IMemoryPool memory) : base(memory) { } @@ -61,7 +65,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http _dispatchPipes.Add(dispatchPipe); } - protected override void DispatchConnection(UvTcpHandle socket) + protected override void DispatchConnection(T socket) { var index = _dispatchIndex++ % (_dispatchPipes.Count + 1); if (index == _dispatchPipes.Count) @@ -80,7 +84,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http (write2, status, error, state) => { write2.Dispose(); - ((UvTcpHandle)state).Dispose(); + ((T)state).Dispose(); }, socket); } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs index 99b21897be..32c7109553 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs @@ -9,11 +9,15 @@ using System.Threading.Tasks; namespace Microsoft.AspNet.Server.Kestrel.Http { - public class ListenerSecondary : ListenerContext, IDisposable + /// + /// A secondary listener is delegated requests from a primary listener via a named pipe or + /// UNIX domain socket. + /// + public abstract class ListenerSecondary : ListenerContext, IListenerSecondary where T : UvStreamHandle { UvPipeHandle DispatchPipe { get; set; } - public ListenerSecondary(IMemoryPool memory) + protected ListenerSecondary(IMemoryPool memory) { Memory = memory; } @@ -64,8 +68,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return; } - var acceptSocket = new UvTcpHandle(); - acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle); + var acceptSocket = CreateAcceptSocket(); try { @@ -102,6 +105,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return tcs.Task; } + /// + /// Creates a socket which can be used to accept an incoming connection + /// + protected abstract T CreateAcceptSocket(); + public void Dispose() { // Ensure the event loop is still running. diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListener.cs new file mode 100644 index 0000000000..64e732acaa --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListener.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Server.Kestrel.Infrastructure; +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// Implementation of that uses UNIX domain sockets as its transport. + /// + public class PipeListener : Listener + { + public PipeListener(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates the socket used to listen for incoming connections + /// + protected override UvPipeHandle CreateListenSocket(string host, int port) + { + var socket = new UvPipeHandle(); + socket.Init(Thread.Loop, false); + socket.Bind(host); + socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); + return socket; + } + + /// + /// Handles an incoming connection + /// + /// Socket being used to listen on + /// Connection status + protected override void OnConnection(UvPipeHandle listenSocket, int status) + { + var acceptSocket = new UvPipeHandle(); + acceptSocket.Init(Thread.Loop, false); + listenSocket.Accept(acceptSocket); + + DispatchConnection(acceptSocket); + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerPrimary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerPrimary.cs new file mode 100644 index 0000000000..bcfb705fef --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerPrimary.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Server.Kestrel.Infrastructure; +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// An implementation of using UNIX sockets. + /// + public class PipeListenerPrimary : ListenerPrimary + { + public PipeListenerPrimary(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates the socket used to listen for incoming connections + /// + protected override UvPipeHandle CreateListenSocket(string host, int port) + { + var socket = new UvPipeHandle(); + socket.Init(Thread.Loop, false); + socket.Bind(host); + socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); + return socket; + } + + /// + /// Handles an incoming connection + /// + /// Socket being used to listen on + /// Connection status + protected override void OnConnection(UvPipeHandle listenSocket, int status) + { + var acceptSocket = new UvPipeHandle(); + acceptSocket.Init(Thread.Loop, false); + listenSocket.Accept(acceptSocket); + + DispatchConnection(acceptSocket); + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerSecondary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerSecondary.cs new file mode 100644 index 0000000000..58f6d4d4b6 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/PipeListenerSecondary.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// An implementation of using UNIX sockets. + /// + public class PipeListenerSecondary : ListenerSecondary + { + public PipeListenerSecondary(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates a socket which can be used to accept an incoming connection + /// + protected override UvPipeHandle CreateAcceptSocket() + { + var acceptSocket = new UvPipeHandle(); + acceptSocket.Init(Thread.Loop, false); + return acceptSocket; + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs new file mode 100644 index 0000000000..294674b746 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Net; +using Microsoft.AspNet.Server.Kestrel.Infrastructure; +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// Implementation of that uses TCP sockets as its transport. + /// + public class TcpListener : Listener + { + public TcpListener(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates the socket used to listen for incoming connections + /// + protected override UvTcpHandle CreateListenSocket(string host, int port) + { + var socket = new UvTcpHandle(); + socket.Init(Thread.Loop, Thread.QueueCloseHandle); + socket.Bind(new IPEndPoint(IPAddress.Any, port)); + socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); + return socket; + } + + /// + /// Handle an incoming connection + /// + /// Socket being used to listen on + /// Connection status + protected override void OnConnection(UvTcpHandle listenSocket, int status) + { + var acceptSocket = new UvTcpHandle(); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle); + listenSocket.Accept(acceptSocket); + + DispatchConnection(acceptSocket); + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs new file mode 100644 index 0000000000..8242d7d403 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Net; +using Microsoft.AspNet.Server.Kestrel.Infrastructure; +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// An implementation of using TCP sockets. + /// + public class TcpListenerPrimary : ListenerPrimary + { + public TcpListenerPrimary(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates the socket used to listen for incoming connections + /// + protected override UvTcpHandle CreateListenSocket(string host, int port) + { + var socket = new UvTcpHandle(); + socket.Init(Thread.Loop, Thread.QueueCloseHandle); + socket.Bind(new IPEndPoint(IPAddress.Any, port)); + socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); + return socket; + } + + /// + /// Handles an incoming connection + /// + /// Socket being used to listen on + /// Connection status + protected override void OnConnection(UvTcpHandle listenSocket, int status) + { + var acceptSocket = new UvTcpHandle(); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle); + listenSocket.Accept(acceptSocket); + + DispatchConnection(acceptSocket); + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerSecondary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerSecondary.cs new file mode 100644 index 0000000000..c7ec374c64 --- /dev/null +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerSecondary.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Server.Kestrel.Networking; + +namespace Microsoft.AspNet.Server.Kestrel.Http +{ + /// + /// An implementation of using TCP sockets. + /// + public class TcpListenerSecondary : ListenerSecondary + { + public TcpListenerSecondary(IMemoryPool memory) : base(memory) + { + } + + /// + /// Creates a socket which can be used to accept an incoming connection + /// + protected override UvTcpHandle CreateAcceptSocket() + { + var acceptSocket = new UvTcpHandle(); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle); + return acceptSocket; + } + } +} diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/Constants.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/Constants.cs index 48d6dc93e9..76b5f1bd5d 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/Constants.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/Constants.cs @@ -1,12 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. namespace Microsoft.AspNet.Server.Kestrel.Infrastructure { internal class Constants { public const int ListenBacklog = 128; + + /// + /// URL scheme for specifying Unix sockets in the configuration. + /// + public const string UnixScheme = "unix"; } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs b/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs index 1f356d16d1..6d5782d54b 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Microsoft.AspNet.Server.Kestrel.Http; +using Microsoft.AspNet.Server.Kestrel.Infrastructure; using Microsoft.AspNet.Server.Kestrel.Networking; using Microsoft.Dnx.Runtime; @@ -69,7 +70,6 @@ namespace Microsoft.AspNet.Server.Kestrel { AppShutdown = appShutdownService; Threads = new List(); - Listeners = new List(); Memory = new MemoryPool(); } @@ -77,7 +77,6 @@ namespace Microsoft.AspNet.Server.Kestrel public IMemoryPool Memory { get; set; } public IApplicationShutdown AppShutdown { get; private set; } public List Threads { get; private set; } - public List Listeners { get; private set; } public void Start(int count) { @@ -104,6 +103,7 @@ namespace Microsoft.AspNet.Server.Kestrel public IDisposable CreateServer(string scheme, string host, int port, Func application) { var listeners = new List(); + var usingPipes = scheme == Constants.UnixScheme; try { @@ -116,19 +116,26 @@ namespace Microsoft.AspNet.Server.Kestrel { if (single) { - var listener = new Listener(Memory); + var listener = usingPipes ? + (IListener) new PipeListener(Memory) : + new TcpListener(Memory); listeners.Add(listener); listener.StartAsync(scheme, host, port, thread, application).Wait(); } else if (first) { - var listener = new ListenerPrimary(Memory); + var listener = usingPipes + ? (IListenerPrimary) new PipeListenerPrimary(Memory) + : new TcpListenerPrimary(Memory); + listeners.Add(listener); listener.StartAsync(pipeName, scheme, host, port, thread, application).Wait(); } else { - var listener = new ListenerSecondary(Memory); + var listener = usingPipes + ? (IListenerSecondary) new PipeListenerSecondary(Memory) + : new TcpListenerSecondary(Memory); listeners.Add(listener); listener.StartAsync(pipeName, thread, application).Wait(); } diff --git a/src/Microsoft.AspNet.Server.Kestrel/ServerFactory.cs b/src/Microsoft.AspNet.Server.Kestrel/ServerFactory.cs index e43e75aef0..0631303cac 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/ServerFactory.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/ServerFactory.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNet.Hosting.Server; using Microsoft.AspNet.Http.Features; -using Microsoft.AspNet.Server.Kestrel; using Microsoft.Dnx.Runtime; using Microsoft.Framework.Configuration; +using Constants = Microsoft.AspNet.Server.Kestrel.Infrastructure.Constants; namespace Microsoft.AspNet.Server.Kestrel { @@ -43,7 +43,8 @@ namespace Microsoft.AspNet.Server.Kestrel { disposables.Add(engine.CreateServer( address.Scheme, - address.Host, + // Unix sockets use a file path, not a hostname. + address.Scheme == Constants.UnixScheme ? address.Path : address.Host, address.Port, async frame => {