diff --git a/src/Kestrel/Kestrel.kproj b/src/Kestrel/Kestrel.kproj index 0626b83124..219d40d100 100644 --- a/src/Kestrel/Kestrel.kproj +++ b/src/Kestrel/Kestrel.kproj @@ -25,6 +25,7 @@ 2.0 + diff --git a/src/Kestrel/Program.cs b/src/Kestrel/Program.cs new file mode 100644 index 0000000000..7f877d9002 --- /dev/null +++ b/src/Kestrel/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Linq; + +namespace Kestrel +{ + public class Program + { + private readonly IServiceProvider _serviceProvider; + + public Program(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void Main(string[] args) + { + var program = new Microsoft.AspNet.Hosting.Program(_serviceProvider); + var mergedArgs = new[] { "--server", "Kestrel" }.Concat(args).ToArray(); + program.Main(mergedArgs); + } + } +} + diff --git a/src/Kestrel/ServerFactory.cs b/src/Kestrel/ServerFactory.cs index a84ad1ae6e..c683d63be6 100644 --- a/src/Kestrel/ServerFactory.cs +++ b/src/Kestrel/ServerFactory.cs @@ -5,6 +5,7 @@ using Microsoft.Framework.ConfigurationModel; using System.Threading.Tasks; using Microsoft.AspNet.Server.Kestrel; using System.Collections.Generic; +using Microsoft.Framework.Runtime; namespace Kestrel { @@ -13,6 +14,13 @@ namespace Kestrel /// public class ServerFactory : IServerFactory { + private readonly ILibraryManager _libraryManager; + + public ServerFactory(ILibraryManager libraryManager) + { + _libraryManager = libraryManager; + } + public IServerInformation Initialize(IConfiguration configuration) { var information = new ServerInformation(); @@ -24,7 +32,7 @@ namespace Kestrel { var disposables = new List(); var information = (ServerInformation)serverInformation; - var engine = new KestrelEngine(); + var engine = new KestrelEngine(_libraryManager); engine.Start(1); foreach (var address in information.Addresses) { diff --git a/src/Kestrel/project.json b/src/Kestrel/project.json index 75592a1e20..2781b38bb3 100644 --- a/src/Kestrel/project.json +++ b/src/Kestrel/project.json @@ -1,8 +1,8 @@ { - "version": "0.1-alpha-*", + "version": "1.0.0-*", "dependencies": { - "Microsoft.AspNet.Hosting": "0.1-*", - "Microsoft.AspNet.Server.Kestrel": "0.1-*" + "Microsoft.AspNet.Hosting": "1.0.0-*", + "Microsoft.AspNet.Server.Kestrel": "1.0.0-*" }, "configurations": { "net45": { diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs index 123336ee6c..111df0065b 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs @@ -62,7 +62,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { ListenSocket = new UvTcpHandle(); ListenSocket.Init(Thread.Loop); - ListenSocket.Bind(new IPEndPoint(IPAddress.Any, port)); + ListenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, port)); ListenSocket.Listen(10, _connectionCallback, this); tcs.SetResult(0); } diff --git a/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs b/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs index 78abaa224e..257c127f6a 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs @@ -6,19 +6,33 @@ using Microsoft.AspNet.Server.Kestrel.Networking; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNet.Server.Kestrel.Http; +using Microsoft.Framework.Runtime; +using System.IO; namespace Microsoft.AspNet.Server.Kestrel { public class KestrelEngine : IDisposable { - public KestrelEngine() + public KestrelEngine(ILibraryManager libraryManager) { Threads = new List(); Listeners = new List(); Memory = new MemoryPool(); Libuv = new Libuv(); - Libuv.Load("libuv.dll"); + + var library = libraryManager.GetLibraryInformation("Microsoft.AspNet.Server.Kestrel"); + var libraryPath = library.Path; + if (library.Type == "Project") + { + libraryPath = Path.GetDirectoryName(libraryPath); + } + var architecture = IntPtr.Size == 4 + ? "x86" + : "amd64"; + libraryPath = Path.Combine(libraryPath, architecture, "libuv.dll"); + + Libuv.Load(libraryPath); } public Libuv Libuv { get; private set; } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Microsoft.AspNet.Server.Kestrel.kproj b/src/Microsoft.AspNet.Server.Kestrel/Microsoft.AspNet.Server.Kestrel.kproj index 943ae5c366..f860285346 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Microsoft.AspNet.Server.Kestrel.kproj +++ b/src/Microsoft.AspNet.Server.Kestrel/Microsoft.AspNet.Server.Kestrel.kproj @@ -23,7 +23,9 @@ 2.0 + + diff --git a/src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs b/src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs index 7f4bf0eaf0..b326d101ad 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs @@ -4,6 +4,7 @@ using System; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; namespace Microsoft.AspNet.Server.Kestrel.Networking { @@ -37,10 +38,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking } public int Check(int statusCode) + { + Exception error; + var result = Check(statusCode, out error); + if (error != null) + { + throw error; + } + return statusCode; + } + + public int Check(int statusCode, out Exception error) { if (statusCode < 0) { - throw new Exception("Status code " + statusCode); + var errorName = err_name(statusCode); + var errorDescription = strerror(statusCode); + error = new Exception("Error " + statusCode + " " + errorName + " " + errorDescription); + } + else + { + error = null; } return statusCode; } @@ -234,6 +252,25 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking return _uv_handle_size(handleType); } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + delegate IntPtr uv_err_name(int err); + uv_err_name _uv_err_name; + public unsafe String err_name(int err) + { + IntPtr ptr = _uv_err_name(err); + return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr); + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + delegate IntPtr uv_strerror(int err); + uv_strerror _uv_strerror; + public unsafe String strerror(int err) + { + IntPtr ptr = _uv_strerror(err); + return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr); + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int uv_req_size(int handleType); uv_req_size _uv_req_size; @@ -246,18 +283,18 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking delegate int uv_ip4_addr(string ip, int port, out sockaddr addr); uv_ip4_addr _uv_ip4_addr; - public void ip4_addr(string ip, int port, out sockaddr addr) + public int ip4_addr(string ip, int port, out sockaddr addr, out Exception error) { - Check(_uv_ip4_addr(ip, port, out addr)); + return Check(_uv_ip4_addr(ip, port, out addr), out error); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int uv_ip6_addr(string ip, int port, out sockaddr addr); uv_ip6_addr _uv_ip6_addr; - public void ip6_addr(string ip, int port, out sockaddr addr) + public int ip6_addr(string ip, int port, out sockaddr addr, out Exception error) { - Check(_uv_ip6_addr(ip, port, out addr)); + return Check(_uv_ip6_addr(ip, port, out addr), out error); } public struct sockaddr diff --git a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs index 0962ff650c..187656647f 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Open Technologies, Inc. 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.Net; namespace Microsoft.AspNet.Server.Kestrel.Networking @@ -16,7 +17,21 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking public void Bind(IPEndPoint endpoint) { Libuv.sockaddr addr; - _uv.ip4_addr(endpoint.Address.ToString(), endpoint.Port, out addr); + var addressText = endpoint.Address.ToString(); + + Exception error1; + _uv.ip4_addr(addressText, endpoint.Port, out addr, out error1); + + if (error1 != null) + { + Exception error2; + _uv.ip6_addr(addressText, endpoint.Port, out addr, out error2); + if (error2 != null) + { + throw error1; + } + } + _uv.tcp_bind(this, ref addr, 0); } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/amd64/libuv.dll b/src/Microsoft.AspNet.Server.Kestrel/amd64/libuv.dll new file mode 100644 index 0000000000..436ee491a1 Binary files /dev/null and b/src/Microsoft.AspNet.Server.Kestrel/amd64/libuv.dll differ diff --git a/src/Microsoft.AspNet.Server.Kestrel/project.json b/src/Microsoft.AspNet.Server.Kestrel/project.json index c20f6afdc4..3435c86826 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/project.json +++ b/src/Microsoft.AspNet.Server.Kestrel/project.json @@ -1,6 +1,7 @@ { - "version": "0.1-alpha-*", + "version": "1.0.0-*", "dependencies": { + "Microsoft.Framework.Runtime.Interfaces": "1.0.0-*" }, "configurations": { "net45": { }, @@ -19,7 +20,8 @@ "System.Net.Primitives": "4.0.10.0", "System.Runtime.Extensions": "4.0.10.0", "System.Threading": "4.0.0.0", - "System.Globalization": "4.0.10.0" + "System.Globalization": "4.0.10.0", + "System.Runtime.InteropServices": "4.0.20.0" } } }, diff --git a/src/SampleApp/libuv.dll b/src/Microsoft.AspNet.Server.Kestrel/x86/libuv.dll similarity index 100% rename from src/SampleApp/libuv.dll rename to src/Microsoft.AspNet.Server.Kestrel/x86/libuv.dll diff --git a/src/SampleApp/Microsoft.AspNet.Hosting.ini b/src/SampleApp/Microsoft.AspNet.Hosting.ini index f0def9d26b..3992612903 100644 --- a/src/SampleApp/Microsoft.AspNet.Hosting.ini +++ b/src/SampleApp/Microsoft.AspNet.Hosting.ini @@ -1,4 +1,3 @@  -Server=Kestrel -; Server = Microsoft.AspNet.Server.WebListener +Server = Microsoft.AspNet.Server.WebListener Server.Urls = http://localhost:5000/ diff --git a/src/SampleApp/SampleApp.kproj b/src/SampleApp/SampleApp.kproj index 35a172e4e1..a49005a910 100644 --- a/src/SampleApp/SampleApp.kproj +++ b/src/SampleApp/SampleApp.kproj @@ -25,14 +25,14 @@ 2.0 - web + + - diff --git a/src/SampleApp/Startup.cs b/src/SampleApp/Startup.cs index acafabf447..9eba33a386 100644 --- a/src/SampleApp/Startup.cs +++ b/src/SampleApp/Startup.cs @@ -15,6 +15,7 @@ namespace SampleApp context.Request.Path, context.Request.QueryString); + context.Response.ContentLength = 11; context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("Hello world"); }); diff --git a/src/SampleApp/project.json b/src/SampleApp/project.json index 12bc80da47..19174804d7 100644 --- a/src/SampleApp/project.json +++ b/src/SampleApp/project.json @@ -1,7 +1,8 @@ { + "version": "1.0.0-*", "dependencies": { - "Kestrel": "0.1-alpha-*", - "Microsoft.AspNet.Server.WebListener": "0.1-alpha-*" + "Kestrel": "1.0.0-*", + "Microsoft.AspNet.Server.WebListener": "1.0.0-*" }, "configurations": { "net45": { }, @@ -12,7 +13,7 @@ } }, "commands": { - "run": "Microsoft.AspNet.Hosting", + "run": "Kestrel", "web": "Microsoft.AspNet.Hosting" } } diff --git a/test/Microsoft.AspNet.Server.KestralTests/EngineTests.cs b/test/Microsoft.AspNet.Server.KestralTests/EngineTests.cs index e92e2a9b70..8873de5041 100644 --- a/test/Microsoft.AspNet.Server.KestralTests/EngineTests.cs +++ b/test/Microsoft.AspNet.Server.KestralTests/EngineTests.cs @@ -1,5 +1,7 @@ using Microsoft.AspNet.Server.Kestrel; using Microsoft.AspNet.Server.Kestrel.Http; +using Microsoft.Framework.Runtime; +using Microsoft.Framework.Runtime.Infrastructure; using System; using System.IO; using System.Net; @@ -28,6 +30,17 @@ namespace Microsoft.AspNet.Server.KestralTests await frame.ResponseBody.WriteAsync(buffer, 0, count); } } + + ILibraryManager LibraryManager + { + get + { + var services = CallContextServiceLocator.Locator.ServiceProvider; + return (ILibraryManager)services.GetService(typeof(ILibraryManager)); + } + } + + private async Task AppChunked(Frame frame) { var data = new MemoryStream(); @@ -49,7 +62,7 @@ namespace Microsoft.AspNet.Server.KestralTests [Fact] public async Task EngineCanStartAndStop() { - var engine = new KestrelEngine(); + var engine = new KestrelEngine(LibraryManager); engine.Start(1); engine.Dispose(); } @@ -57,7 +70,7 @@ namespace Microsoft.AspNet.Server.KestralTests [Fact] public async Task ListenerCanCreateAndDispose() { - var engine = new KestrelEngine(); + var engine = new KestrelEngine(LibraryManager); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); started.Dispose(); @@ -68,7 +81,7 @@ namespace Microsoft.AspNet.Server.KestralTests [Fact] public async Task ConnectionCanReadAndWrite() { - var engine = new KestrelEngine(); + var engine = new KestrelEngine(LibraryManager); engine.Start(1); var started = engine.CreateServer("http", "localhost", 54321, App); diff --git a/test/Microsoft.AspNet.Server.KestralTests/Microsoft.AspNet.Server.KestralTests.kproj b/test/Microsoft.AspNet.Server.KestralTests/Microsoft.AspNet.Server.KestralTests.kproj index aecd9b6963..78011f5326 100644 --- a/test/Microsoft.AspNet.Server.KestralTests/Microsoft.AspNet.Server.KestralTests.kproj +++ b/test/Microsoft.AspNet.Server.KestralTests/Microsoft.AspNet.Server.KestralTests.kproj @@ -24,7 +24,6 @@ - diff --git a/test/Microsoft.AspNet.Server.KestralTests/NetworkingTests.cs b/test/Microsoft.AspNet.Server.KestralTests/NetworkingTests.cs index 90860a6a8b..f2994a1e85 100644 --- a/test/Microsoft.AspNet.Server.KestralTests/NetworkingTests.cs +++ b/test/Microsoft.AspNet.Server.KestralTests/NetworkingTests.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft Open Technologies, Inc. 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; using Microsoft.AspNet.Server.Kestrel.Networking; +using Microsoft.Framework.Runtime; +using Microsoft.Framework.Runtime.Infrastructure; using System; using System.Net; using System.Net.Sockets; @@ -19,8 +22,17 @@ namespace Microsoft.AspNet.Server.KestralTests Libuv _uv; public NetworkingTests() { - _uv = new Libuv(); - _uv.Load("libuv.dll"); + var engine = new KestrelEngine(LibraryManager); + _uv = engine.Libuv; + } + + ILibraryManager LibraryManager + { + get + { + var services = CallContextServiceLocator.Locator.ServiceProvider; + return (ILibraryManager)services.GetService(typeof(ILibraryManager)); + } } [Fact] diff --git a/test/Microsoft.AspNet.Server.KestralTests/TestServer.cs b/test/Microsoft.AspNet.Server.KestralTests/TestServer.cs index 4f8a2dd440..e947f6b866 100644 --- a/test/Microsoft.AspNet.Server.KestralTests/TestServer.cs +++ b/test/Microsoft.AspNet.Server.KestralTests/TestServer.cs @@ -1,5 +1,7 @@ using Microsoft.AspNet.Server.Kestrel; using Microsoft.AspNet.Server.Kestrel.Http; +using Microsoft.Framework.Runtime; +using Microsoft.Framework.Runtime.Infrastructure; using System; using System.Threading.Tasks; @@ -18,16 +20,24 @@ namespace Microsoft.AspNet.Server.KestralTests Create(app); } + ILibraryManager LibraryManager + { + get + { + var services = CallContextServiceLocator.Locator.ServiceProvider; + return (ILibraryManager)services.GetService(typeof(ILibraryManager)); + } + } + public void Create(Func app) { - _engine = new KestrelEngine(); + _engine = new KestrelEngine(LibraryManager); _engine.Start(1); _server = _engine.CreateServer( "http", "localhost", 54321, app); - } public void Dispose() diff --git a/test/Microsoft.AspNet.Server.KestralTests/libuv.dll b/test/Microsoft.AspNet.Server.KestralTests/libuv.dll deleted file mode 100644 index d3a5834718..0000000000 Binary files a/test/Microsoft.AspNet.Server.KestralTests/libuv.dll and /dev/null differ diff --git a/test/Microsoft.AspNet.Server.KestralTests/project.json b/test/Microsoft.AspNet.Server.KestralTests/project.json index 8cb87eaf48..c67b190301 100644 --- a/test/Microsoft.AspNet.Server.KestralTests/project.json +++ b/test/Microsoft.AspNet.Server.KestralTests/project.json @@ -1,10 +1,10 @@ { - "version": "0.1-alpha-*", + "version": "1.0.0-*", "dependencies": { - "Xunit.KRunner": "0.1-*", + "Xunit.KRunner": "1.0.0-*", "xunit.assert": "2.0.0-*", "xunit.abstractions": "2.0.0-*", - "Microsoft.AspNet.Server.Kestrel": "0.1-*" + "Microsoft.AspNet.Server.Kestrel": "1.0.0-*" }, "configurations": { "net45": { @@ -20,6 +20,7 @@ } }, "commands": { + "run": "Xunit.KRunner", "test": "Xunit.KRunner" } }