Ver código fonte

adjust discovery of local ip addresses

Luke Pulverenti 10 anos atrás
pai
commit
6130cb2403

+ 22 - 4
MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -24,14 +24,32 @@ namespace MediaBrowser.Common.Implementations.Networking
         /// <returns>IPAddress.</returns>
         /// <returns>IPAddress.</returns>
         public IEnumerable<string> GetLocalIpAddresses()
         public IEnumerable<string> GetLocalIpAddresses()
         {
         {
-            var list = GetIPsDefault().Where(i => !IPAddress.IsLoopback(i)).Select(i => i.ToString()).ToList();
+            var list = GetIPsDefault()
+                .Where(i => !IPAddress.IsLoopback(i))
+                .Select(i => i.ToString())
+                .ToList();
 
 
-            if (list.Count > 0)
+            try
             {
             {
-                return list;
+                var listFromDns = Dns.GetHostAddresses(Dns.GetHostName())
+                    .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
+                    .Where(i => !IPAddress.IsLoopback(i))
+                    .Select(i => i.ToString())
+                    .ToList();
+
+                if (listFromDns.Count > 0)
+                {
+                    return listFromDns
+                        .OrderBy(i => (list.Contains(i, StringComparer.OrdinalIgnoreCase) ? 0 : 1))
+                        .ToList();
+                }
             }
             }
+            catch
+            {
 
 
-            return GetLocalIpAddressesFallback();
+            }
+            
+            return list;
         }
         }
 
 
         public bool IsInLocalNetwork(string endpoint)
         public bool IsInLocalNetwork(string endpoint)

+ 8 - 1
MediaBrowser.Controller/IServerApplicationHost.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common;
+using System.Collections.Generic;
+using MediaBrowser.Common;
 using MediaBrowser.Model.System;
 using MediaBrowser.Model.System;
 using System;
 using System;
 
 
@@ -46,5 +47,11 @@ namespace MediaBrowser.Controller
         /// </summary>
         /// </summary>
         /// <value>The name of the friendly.</value>
         /// <value>The name of the friendly.</value>
         string FriendlyName { get; }
         string FriendlyName { get; }
+
+        /// <summary>
+        /// Gets the HTTP server ip addresses.
+        /// </summary>
+        /// <value>The HTTP server ip addresses.</value>
+        IEnumerable<string> HttpServerIpAddresses { get; }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Dlna/Main/DlnaEntryPoint.cs

@@ -111,7 +111,7 @@ namespace MediaBrowser.Dlna.Main
 
 
                 _ssdpHandler.Start();
                 _ssdpHandler.Start();
 
 
-                _deviceDiscovery = new DeviceDiscovery(_logger, _config, _httpClient, _ssdpHandler, _network);
+                _deviceDiscovery = new DeviceDiscovery(_logger, _config, _ssdpHandler, _appHost);
 
 
                 _deviceDiscovery.Start();
                 _deviceDiscovery.Start();
             }
             }

+ 20 - 20
MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using System;
 using System;
@@ -21,21 +22,19 @@ namespace MediaBrowser.Dlna.Ssdp
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly SsdpHandler _ssdpHandler;
         private readonly SsdpHandler _ssdpHandler;
         private readonly CancellationTokenSource _tokenSource;
         private readonly CancellationTokenSource _tokenSource;
-        private readonly IHttpClient _httpClient;
-        private readonly INetworkManager _networkManager;
+        private readonly IServerApplicationHost _appHost;
 
 
         public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
         public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
         public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
         public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
 
 
-        public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IHttpClient httpClient, SsdpHandler ssdpHandler, INetworkManager networkManager)
+        public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, SsdpHandler ssdpHandler, IServerApplicationHost appHost)
         {
         {
             _tokenSource = new CancellationTokenSource();
             _tokenSource = new CancellationTokenSource();
 
 
             _logger = logger;
             _logger = logger;
             _config = config;
             _config = config;
-            _httpClient = httpClient;
             _ssdpHandler = ssdpHandler;
             _ssdpHandler = ssdpHandler;
-            _networkManager = networkManager;
+            _appHost = appHost;
         }
         }
 
 
         public void Start()
         public void Start()
@@ -48,21 +47,21 @@ namespace MediaBrowser.Dlna.Ssdp
 
 
                 if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
                 if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
                     continue;
                     continue;
-
+                
                 var ipV4 = network.GetIPProperties().GetIPv4Properties();
                 var ipV4 = network.GetIPProperties().GetIPv4Properties();
                 if (null == ipV4)
                 if (null == ipV4)
                     continue;
                     continue;
 
 
-                var localIp = network.GetIPProperties().UnicastAddresses
+                var localIps = network.GetIPProperties().UnicastAddresses
                     .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
                     .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
                     .Select(i => i.Address)
                     .Select(i => i.Address)
-                    .FirstOrDefault();
+                    .ToList();
 
 
-                if (localIp != null)
+                foreach (var localIp in localIps)
                 {
                 {
                     try
                     try
                     {
                     {
-                        CreateListener(localIp, ipV4.Index);
+                        CreateListener(localIp);
                     }
                     }
                     catch (Exception e)
                     catch (Exception e)
                     {
                     {
@@ -71,7 +70,7 @@ namespace MediaBrowser.Dlna.Ssdp
                 }
                 }
             }
             }
         }
         }
-
+        
         void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
         void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
         {
         {
             string nts;
             string nts;
@@ -87,9 +86,9 @@ namespace MediaBrowser.Dlna.Ssdp
 
 
             try
             try
             {
             {
-                var ip = _networkManager.GetLocalIpAddresses().FirstOrDefault();
+                var ip = _appHost.HttpServerIpAddresses.FirstOrDefault();
 
 
-                if (ip != null)
+                if (!string.IsNullOrWhiteSpace(ip))
                 {
                 {
                     e.LocalIp = IPAddress.Parse(ip);
                     e.LocalIp = IPAddress.Parse(ip);
                     TryCreateDevice(e);
                     TryCreateDevice(e);
@@ -116,19 +115,17 @@ namespace MediaBrowser.Dlna.Ssdp
                 return new List<NetworkInterface>();
                 return new List<NetworkInterface>();
             }
             }
         }
         }
-        private void CreateListener(IPAddress localIp, int networkInterfaceIndex)
+        private void CreateListener(IPAddress localIp)
         {
         {
             Task.Factory.StartNew(async (o) =>
             Task.Factory.StartNew(async (o) =>
             {
             {
                 try
                 try
                 {
                 {
-                    var socket = GetMulticastSocket(networkInterfaceIndex);
-
                     var endPoint = new IPEndPoint(localIp, 1900);
                     var endPoint = new IPEndPoint(localIp, 1900);
 
 
-                    socket.Bind(endPoint);
+                    var socket = GetMulticastSocket(localIp, endPoint);
 
 
-                    _logger.Info("Creating SSDP listener on {0}, network interface index {1}", localIp, networkInterfaceIndex);
+                    _logger.Info("Creating SSDP listener on {0}", localIp);
 
 
                     var receiveBuffer = new byte[64000];
                     var receiveBuffer = new byte[64000];
 
 
@@ -188,12 +185,15 @@ namespace MediaBrowser.Dlna.Ssdp
 
 
         }
         }
 
 
-        private Socket GetMulticastSocket(int networkInterfaceIndex)
+        private Socket GetMulticastSocket(IPAddress localIpAddress, EndPoint localEndpoint)
         {
         {
             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
             socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
             socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
-            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), networkInterfaceIndex));
+            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIpAddress));
             socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
             socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
+
+            socket.Bind(localEndpoint);
+            
             return socket;
             return socket;
         }
         }
 
 

+ 23 - 5
MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -14,7 +14,6 @@ using ServiceStack.Host.HttpListener;
 using ServiceStack.Logging;
 using ServiceStack.Logging;
 using ServiceStack.Web;
 using ServiceStack.Web;
 using System;
 using System;
-using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
@@ -40,15 +39,26 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
 
         public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
         public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
 
 
-        private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-        
+        private readonly List<string> _localEndpoints = new List<string>();
+
+        private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim();
+
         /// <summary>
         /// <summary>
         /// Gets the local end points.
         /// Gets the local end points.
         /// </summary>
         /// </summary>
         /// <value>The local end points.</value>
         /// <value>The local end points.</value>
         public IEnumerable<string> LocalEndPoints
         public IEnumerable<string> LocalEndPoints
         {
         {
-            get { return _listener == null ? new List<string>() : _localEndPoints.Keys.ToList(); }
+            get
+            {
+                _localEndpointLock.EnterReadLock();
+
+                var list = _localEndpoints.ToList();
+
+                _localEndpointLock.ExitReadLock();
+
+                return list;
+            }
         }
         }
 
 
         public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
         public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
@@ -156,7 +166,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
 
         private void OnRequestReceived(string localEndPoint)
         private void OnRequestReceived(string localEndPoint)
         {
         {
-            _localEndPoints.GetOrAdd(localEndPoint, localEndPoint);
+            if (_localEndpointLock.TryEnterWriteLock(100))
+            {
+                var list = _localEndpoints.ToList();
+
+                list.Remove(localEndPoint);
+                list.Insert(0, localEndPoint);
+
+                _localEndpointLock.ExitWriteLock();
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 32 - 10
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -950,17 +950,8 @@ namespace MediaBrowser.ServerApplication
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
         private string GetLocalIpAddress()
         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 the first matched address, if found, or the first known local address
-            var address = matchedAddress ?? localAddresses.FirstOrDefault();
+            var address = HttpServerIpAddresses.FirstOrDefault();
 
 
             if (!string.IsNullOrWhiteSpace(address))
             if (!string.IsNullOrWhiteSpace(address))
             {
             {
@@ -972,6 +963,37 @@ namespace MediaBrowser.ServerApplication
             return address;
             return address;
         }
         }
 
 
+        public IEnumerable<string> HttpServerIpAddresses
+        {
+            get
+            {
+                var localAddresses = NetworkManager.GetLocalIpAddresses()
+                    .ToList();
+
+                if (localAddresses.Count < 2)
+                {
+                    return localAddresses;
+                }
+
+                var httpServerAddresses = HttpServer.LocalEndPoints
+                    .Select(i => i.Split(':').FirstOrDefault())
+                    .Where(i => !string.IsNullOrEmpty(i))
+                    .ToList();
+
+                // Cross-check the local ip addresses with addresses that have been received on with the http server
+                var matchedAddresses = httpServerAddresses
+                    .Where(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase))
+                    .ToList();
+
+                if (matchedAddresses.Count == 0)
+                {
+                    return localAddresses.Take(1);
+                }
+
+                return matchedAddresses;
+            }
+        }
+
         public string FriendlyName
         public string FriendlyName
         {
         {
             get
             get