diff options
6 files changed, 133 insertions, 26 deletions
diff --git a/MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs b/MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs index 3c42d340b..6db00064c 100644 --- a/MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs +++ b/MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs @@ -1,11 +1,11 @@ -using System.Globalization; -using System.Management; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net; using MediaBrowser.Model.Net; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; +using System.Management; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; @@ -21,18 +21,16 @@ namespace MediaBrowser.Common.Implementations.NetworkManagement /// Gets the machine's local ip address /// </summary> /// <returns>IPAddress.</returns> - public string GetLocalIpAddress() + public IEnumerable<string> GetLocalIpAddresses() { var host = Dns.GetHostEntry(Dns.GetHostName()); - var ip = host.AddressList.LastOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); - - if (ip == null) - { - return null; - } - - return ip.ToString(); + // Reverse them because the last one is usually the correct one + // It's not fool-proof so ultimately the consumer will have to examine them and decide + return host.AddressList + .Where(i => i.AddressFamily == AddressFamily.InterNetwork) + .Select(i => i.ToString()) + .Reverse(); } /// <summary> diff --git a/MediaBrowser.Common/Net/IHttpServer.cs b/MediaBrowser.Common/Net/IHttpServer.cs index 45da18e1b..8bbaac039 100644 --- a/MediaBrowser.Common/Net/IHttpServer.cs +++ b/MediaBrowser.Common/Net/IHttpServer.cs @@ -27,6 +27,12 @@ namespace MediaBrowser.Common.Net bool SupportsWebSockets { get; } /// <summary> + /// Gets the local end points. + /// </summary> + /// <value>The local end points.</value> + IEnumerable<string> LocalEndPoints { get; } + + /// <summary> /// Stops this instance. /// </summary> void Stop(); diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 782855cd1..8265cfeb7 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Common.Net /// Gets the machine's local ip address /// </summary> /// <returns>IPAddress.</returns> - string GetLocalIpAddress(); + IEnumerable<string> GetLocalIpAddresses(); /// <summary> /// Gets a random port number that is currently available diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs index 01b867bdb..893715b73 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs @@ -14,6 +14,7 @@ using ServiceStack.WebHost.Endpoints; using ServiceStack.WebHost.Endpoints.Extensions; using ServiceStack.WebHost.Endpoints.Support; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -76,6 +77,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// </summary> private readonly ContainerAdapter _containerAdapter; + private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + + /// <summary> + /// Gets the local end points. + /// </summary> + /// <value>The local end points.</value> + public IEnumerable<string> LocalEndPoints + { + get { return _localEndPoints.Keys.ToList(); } + } + /// <summary> /// Initializes a new instance of the <see cref="HttpServer" /> class. /// </summary> @@ -340,15 +352,24 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// <param name="ctx">The CTX.</param> private void LogHttpRequest(HttpListenerContext ctx) { - var log = new StringBuilder(); + var endpoint = ctx.Request.LocalEndPoint; - log.AppendLine("Url: " + ctx.Request.Url); - log.AppendLine("Headers: " + string.Join(",", ctx.Request.Headers.AllKeys.Select(k => k + "=" + ctx.Request.Headers[k]))); + if (endpoint != null) + { + var address = endpoint.ToString(); - var type = ctx.Request.IsWebSocketRequest ? "Web Socket" : "HTTP " + ctx.Request.HttpMethod; + _localEndPoints.AddOrUpdate(address, address, (key, existing) => address); + } if (EnableHttpRequestLogging) { + var log = new StringBuilder(); + + log.AppendLine("Url: " + ctx.Request.Url); + log.AppendLine("Headers: " + string.Join(",", ctx.Request.Headers.AllKeys.Select(k => k + "=" + ctx.Request.Headers[k]))); + + var type = ctx.Request.IsWebSocketRequest ? "Web Socket" : "HTTP " + ctx.Request.HttpMethod; + _logger.LogMultiline(type + " request received from " + ctx.Request.RemoteEndPoint, LogSeverity.Debug, log); } } diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs index 17f5b7b15..af32f08de 100644 --- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs +++ b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs @@ -1,13 +1,14 @@ -using System.Linq; -using MediaBrowser.Common.Implementations.NetworkManagement; +using MediaBrowser.Common.Implementations.NetworkManagement; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Logging; using System; +using System.Linq; using System.Net; using System.Net.Sockets; using System.Reactive.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Udp @@ -22,8 +23,18 @@ namespace MediaBrowser.Server.Implementations.Udp /// </summary> private readonly ILogger _logger; + /// <summary> + /// The _network manager + /// </summary> private readonly INetworkManager _networkManager; + /// <summary> + /// The _HTTP server + /// </summary> + private readonly IHttpServer _httpServer; + /// <summary> + /// The _server configuration manager + /// </summary> private readonly IServerConfigurationManager _serverConfigurationManager; /// <summary> @@ -32,11 +43,15 @@ namespace MediaBrowser.Server.Implementations.Udp /// <param name="logger">The logger.</param> /// <param name="networkManager">The network manager.</param> /// <param name="serverConfigurationManager">The server configuration manager.</param> - public UdpServer(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager) + /// <param name="httpServer">The HTTP server.</param> + public UdpServer(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) { _logger = logger; _networkManager = networkManager; _serverConfigurationManager = serverConfigurationManager; + _httpServer = httpServer; + + new Timer(state => _logger.Info("Internal address {0}", GetLocalIpAddress()), null, 0, 1000); } /// <summary> @@ -54,14 +69,42 @@ namespace MediaBrowser.Server.Implementations.Udp { _logger.Info("Received UDP server request from " + e.RemoteEndPoint); - // Send a response back with our ip address and port - var response = String.Format("MediaBrowser{0}|{1}:{2}", context, _networkManager.GetLocalIpAddress(), _serverConfigurationManager.Configuration.HttpServerPortNumber); + var localAddress = GetLocalIpAddress(); + + if (!string.IsNullOrEmpty(localAddress)) + { + // Send a response back with our ip address and port + var response = String.Format("MediaBrowser{0}|{1}:{2}", context, GetLocalIpAddress(), _serverConfigurationManager.Configuration.HttpServerPortNumber); - await SendAsync(Encoding.UTF8.GetBytes(response), e.RemoteEndPoint); + await SendAsync(Encoding.UTF8.GetBytes(response), e.RemoteEndPoint); + } + else + { + _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); + } } } /// <summary> + /// Gets the local ip address. + /// </summary> + /// <returns>System.String.</returns> + private string GetLocalIpAddress() + { + var localAddresses = _networkManager.GetLocalIpAddresses().ToList(); + + // Cross-check the local ip addresses with addresses that have been received on with the http server + var matchedAddress = _httpServer.LocalEndPoints + .ToList() + .Select(i => i.Split(':').FirstOrDefault()) + .Where(i => !string.IsNullOrEmpty(i)) + .FirstOrDefault(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase)); + + // Return the first matched address, if found, or the first known local address + return matchedAddress ?? localAddresses.FirstOrDefault(); + } + + /// <summary> /// The _udp client /// </summary> private UdpClient _udpClient; @@ -203,6 +246,11 @@ namespace MediaBrowser.Server.Implementations.Udp /// <param name="bytes">The bytes.</param> /// <param name="remoteEndPoint">The remote end point.</param> /// <returns>Task.</returns> + /// <exception cref="System.ArgumentNullException"> + /// bytes + /// or + /// remoteEndPoint + /// </exception> public async Task SendAsync(byte[] bytes, string remoteEndPoint) { if (bytes == null) diff --git a/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs index af4ce84e3..595d5c89f 100644 --- a/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs +++ b/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs @@ -7,6 +7,9 @@ using System.Net.Sockets; namespace MediaBrowser.ServerApplication.EntryPoints { + /// <summary> + /// Class UdpServerEntryPoint + /// </summary> public class UdpServerEntryPoint : IServerEntryPoint { /// <summary> @@ -15,20 +18,44 @@ namespace MediaBrowser.ServerApplication.EntryPoints /// <value>The UDP server.</value> private UdpServer UdpServer { get; set; } + /// <summary> + /// The _logger + /// </summary> private readonly ILogger _logger; + /// <summary> + /// The _network manager + /// </summary> private readonly INetworkManager _networkManager; + /// <summary> + /// The _server configuration manager + /// </summary> private readonly IServerConfigurationManager _serverConfigurationManager; + /// <summary> + /// The _HTTP server + /// </summary> + private readonly IHttpServer _httpServer; - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager) + /// <summary> + /// Initializes a new instance of the <see cref="UdpServerEntryPoint"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + /// <param name="networkManager">The network manager.</param> + /// <param name="serverConfigurationManager">The server configuration manager.</param> + /// <param name="httpServer">The HTTP server.</param> + public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) { _logger = logger; _networkManager = networkManager; _serverConfigurationManager = serverConfigurationManager; + _httpServer = httpServer; } - + + /// <summary> + /// Runs this instance. + /// </summary> public void Run() { - var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager); + var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer); try { @@ -42,11 +69,18 @@ namespace MediaBrowser.ServerApplication.EntryPoints } } + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> public void Dispose() { Dispose(true); } + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool dispose) { if (dispose) |
