From f0137b7b9ea25ee4769931da1e8d255a47605e85 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 25 Sep 2015 15:53:30 -0700 Subject: [PATCH] Bind to specific IP addresses if provided with any This still only applies to IPv4. #98 --- .../Http/TcpListener.cs | 2 +- .../Http/TcpListenerPrimary.cs | 2 +- .../Networking/UvTcpHandle.cs | 28 ++++++++++++++++++- .../CreateIPEndpointTests.cs | 25 +++++++++++++++++ .../MultipleLoopTests.cs | 2 +- .../NetworkingTests.cs | 8 +++--- 6 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 test/Microsoft.AspNet.Server.KestrelTests/CreateIPEndpointTests.cs diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs index 2b8e4ea527..ba920f34aa 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListener.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { var socket = new UvTcpHandle(Log); socket.Init(Thread.Loop, Thread.QueueCloseHandle); - socket.Bind(new IPEndPoint(IPAddress.Any, port)); + socket.Bind(host, port); socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); return socket; } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs index af4495784d..cc4bb451f8 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/TcpListenerPrimary.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { var socket = new UvTcpHandle(Log); socket.Init(Thread.Loop, Thread.QueueCloseHandle); - socket.Bind(new IPEndPoint(IPAddress.Any, port)); + socket.Bind(host, port); socket.Listen(Constants.ListenBacklog, ConnectionCallback, this); return socket; } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs index d99f225bd1..55681bfbe5 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvTcpHandle.cs @@ -33,8 +33,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking _uv.tcp_init(loop, this); } - public void Bind(IPEndPoint endpoint) + public void Bind(string host, int port) { + var endpoint = CreateIPEndpoint(host, port); + Libuv.sockaddr addr; var addressText = endpoint.Address.ToString(); @@ -58,5 +60,29 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking { _uv.tcp_open(this, hSocket); } + + /// + /// Returns an for the given host an port. + /// If the host parameter isn't "localhost" or an IP address, use IPAddress.Any. + /// + public static IPEndPoint CreateIPEndpoint(string host, int port) + { + // TODO: IPv6 support + IPAddress ip; + + if (!IPAddress.TryParse(host, out ip)) + { + if (string.Equals(host, "localhost", StringComparison.OrdinalIgnoreCase)) + { + ip = IPAddress.Loopback; + } + else + { + ip = IPAddress.Any; + } + } + + return new IPEndPoint(ip, port); + } } } diff --git a/test/Microsoft.AspNet.Server.KestrelTests/CreateIPEndpointTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/CreateIPEndpointTests.cs new file mode 100644 index 0000000000..716a528721 --- /dev/null +++ b/test/Microsoft.AspNet.Server.KestrelTests/CreateIPEndpointTests.cs @@ -0,0 +1,25 @@ +// 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.Networking; +using Xunit; + +namespace Microsoft.AspNet.Server.KestrelTests +{ + public class CreateIPEndpointTests + { + [Theory] + [InlineData("localhost", "127.0.0.1")] + [InlineData("10.10.10.10", "10.10.10.10")] + [InlineData("randomhost", "0.0.0.0")] + public void CorrectIPEndpointsAreCreated(string host, string expectedAddress) + { + // "0.0.0.0" is IPAddress.Any + var endpoint = UvTcpHandle.CreateIPEndpoint(host, 5000); + Assert.NotNull(endpoint); + Assert.Equal(IPAddress.Parse(expectedAddress), endpoint.Address); + Assert.Equal(5000, endpoint.Port); + } + } +} diff --git a/test/Microsoft.AspNet.Server.KestrelTests/MultipleLoopTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/MultipleLoopTests.cs index 3da9c93f4a..4e8c0fddd6 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/MultipleLoopTests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/MultipleLoopTests.cs @@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Server.KestrelTests var serverListenTcp = new UvTcpHandle(_logger); serverListenTcp.Init(loop); - serverListenTcp.Bind(new IPEndPoint(0, 54321)); + serverListenTcp.Bind("0.0.0.0", 54321); serverListenTcp.Listen(128, (_1, status, error, _2) => { var serverConnectionTcp = new UvTcpHandle(_logger); diff --git a/test/Microsoft.AspNet.Server.KestrelTests/NetworkingTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/NetworkingTests.cs index 5c4a47f9c0..8d9eab7df7 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/NetworkingTests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/NetworkingTests.cs @@ -81,7 +81,7 @@ namespace Microsoft.AspNet.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop); - tcp.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + tcp.Bind("localhost", 0); tcp.Dispose(); loop.Run(); loop.Dispose(); @@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop); - tcp.Bind(new IPEndPoint(IPAddress.Loopback, 54321)); + tcp.Bind("localhost", 54321); tcp.Listen(10, (stream, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); @@ -132,7 +132,7 @@ namespace Microsoft.AspNet.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop); - tcp.Bind(new IPEndPoint(IPAddress.Loopback, 54321)); + tcp.Bind("localhost", 54321); tcp.Listen(10, (_, status, error, state) => { Console.WriteLine("Connected"); @@ -188,7 +188,7 @@ namespace Microsoft.AspNet.Server.KestrelTests loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop); - tcp.Bind(new IPEndPoint(IPAddress.Loopback, 54321)); + tcp.Bind("localhost", 54321); tcp.Listen(10, (_, status, error, state) => { Console.WriteLine("Connected");