Pārlūkot izejas kodu

Fix autodiscovery

Shadowghost 2 gadi atpakaļ
vecāks
revīzija
87d0158a4a

+ 8 - 1
Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs

@@ -79,6 +79,10 @@ namespace Emby.Server.Implementations.EntryPoints
             {
                 if (_enableMultiSocketBinding)
                 {
+                    // Add global broadcast socket
+                    _udpServers.Add(new UdpServer(_logger, _appHost, _config, System.Net.IPAddress.Broadcast, PortNumber));
+
+                    // Add bind address specific broadcast sockets
                     foreach (var bindAddress in _networkManager.GetInternalBindAddresses())
                     {
                         if (bindAddress.AddressFamily == AddressFamily.InterNetworkV6)
@@ -87,7 +91,10 @@ namespace Emby.Server.Implementations.EntryPoints
                             continue;
                         }
 
-                        _udpServers.Add(new UdpServer(_logger, _appHost, _config, bindAddress.Address, PortNumber));
+                        var broadcastAddress = NetworkExtensions.GetBroadcastAddress(bindAddress.Subnet);
+                        _logger.LogDebug("Binding UDP server to {Address}", broadcastAddress.ToString());
+
+                        _udpServers.Add(new UdpServer(_logger, _appHost, _config, broadcastAddress, PortNumber));
                     }
                 }
                 else

+ 28 - 31
Jellyfin.Networking/Manager/NetworkManager.cs

@@ -280,7 +280,7 @@ namespace Jellyfin.Networking.Manager
                 }
 
                 _logger.LogDebug("Discovered {0} interfaces.", _interfaces.Count);
-                _logger.LogDebug("Interfaces addresses : {0}", _interfaces.Select(s => s.Address).ToString());
+                _logger.LogDebug("Interfaces addresses : {0}", _interfaces.Select(s => s.Address.ToString()));
             }
         }
 
@@ -726,20 +726,11 @@ namespace Jellyfin.Networking.Manager
                 }
 
                 bool isExternal = !_lanSubnets.Any(network => network.Contains(source));
-                _logger.LogDebug("GetBindInterface with source. External: {IsExternal}:", isExternal);
+                _logger.LogDebug("GetBindInterface with source {Source}. External: {IsExternal}:", source, isExternal);
 
-                if (MatchesPublishedServerUrl(source, isExternal, out string res, out port))
+                if (MatchesPublishedServerUrl(source, isExternal, out result))
                 {
-                    if (port != null)
-                    {
-                        _logger.LogInformation("{Source}: Using BindAddress {Address}:{Port}", source, res, port);
-                    }
-                    else
-                    {
-                        _logger.LogInformation("{Source}: Using BindAddress {Address}", source, res);
-                    }
-
-                    return res;
+                    return result;
                 }
 
                 // No preference given, so move on to bind addresses.
@@ -868,41 +859,37 @@ namespace Jellyfin.Networking.Manager
         /// <param name="source">IP source address to use.</param>
         /// <param name="isInExternalSubnet">True if the source is in an external subnet.</param>
         /// <param name="bindPreference">The published server URL that matches the source address.</param>
-        /// <param name="port">The resultant port, if one exists.</param>
         /// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
-        private bool MatchesPublishedServerUrl(IPAddress source, bool isInExternalSubnet, out string bindPreference, out int? port)
+        private bool MatchesPublishedServerUrl(IPAddress source, bool isInExternalSubnet, out string bindPreference)
         {
             bindPreference = string.Empty;
-            port = null;
+            int? port = null;
 
             var validPublishedServerUrls = _publishedServerUrls.Where(x => x.Key.Address.Equals(IPAddress.Any)
                                                                             || x.Key.Address.Equals(IPAddress.IPv6Any)
                                                                             || x.Key.Subnet.Contains(source))
                                                                 .GroupBy(x => x.Key)
-                                                                .Select(y => y.First())
+                                                                .Select(x => x.First())
+                                                                .OrderBy(x => x.Key.Address.Equals(IPAddress.Any)
+                                                                            || x.Key.Address.Equals(IPAddress.IPv6Any))
                                                                 .ToList();
 
             // Check for user override.
             foreach (var data in validPublishedServerUrls)
             {
-                // Get address interface
-                var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(s => s.Subnet.Contains(data.Key.Address));
+                // Get address interface.
+                var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Key.Subnet.Contains(x.Address));
 
-                // Remaining. Match anything.
-                if (data.Key.Address.Equals(IPAddress.Broadcast))
-                {
-                    bindPreference = data.Value;
-                    break;
-                }
-                else if ((data.Key.Address.Equals(IPAddress.Any) || data.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
+                if (isInExternalSubnet && (data.Key.Address.Equals(IPAddress.Any) || data.Key.Address.Equals(IPAddress.IPv6Any)))
                 {
                     // External.
                     bindPreference = data.Value;
                     break;
                 }
-                else if (intf?.Address != null)
+
+                if (intf?.Address != null)
                 {
-                    // Match ip address.
+                    // Match IP address.
                     bindPreference = data.Value;
                     break;
                 }
@@ -910,6 +897,7 @@ namespace Jellyfin.Networking.Manager
 
             if (string.IsNullOrEmpty(bindPreference))
             {
+                _logger.LogInformation("{Source}: No matching bind address override found", source);
                 return false;
             }
 
@@ -924,6 +912,15 @@ namespace Jellyfin.Networking.Manager
                 }
             }
 
+            if (port != null)
+            {
+                _logger.LogInformation("{Source}: Matching bind address override found {Address}:{Port}", source, bindPreference, port);
+            }
+            else
+            {
+                _logger.LogInformation("{Source}: Matching bind address override found {Address}", source, bindPreference);
+            }
+
             return true;
         }
 
@@ -967,12 +964,12 @@ namespace Jellyfin.Networking.Manager
                         if (bindAddress != null)
                         {
                             result = NetworkExtensions.FormatIpString(bindAddress);
-                            _logger.LogDebug("{Source}: GetBindInterface: Has source, found a matching external bind interface: {Result}", source, result);
+                            _logger.LogDebug("{Source}: External request received, matching external bind interface found: {Result}", source, result);
                             return true;
                         }
                     }
 
-                    _logger.LogWarning("{Source}: External request received, no external interface bind found, trying internal interfaces.", source);
+                    _logger.LogWarning("{Source}: External request received, no matching external bind interface found, trying internal interfaces.", source);
                 }
                 else
                 {
@@ -987,7 +984,7 @@ namespace Jellyfin.Networking.Manager
                     if (bindAddress != null)
                     {
                         result = NetworkExtensions.FormatIpString(bindAddress);
-                        _logger.LogWarning("{Source}: Request received, matching internal interface bind found: {Result}", source, result);
+                        _logger.LogDebug("{Source}: Internal request received, matching internal bind interface found: {Result}", source, result);
                         return true;
                     }
                 }

+ 31 - 1
MediaBrowser.Common/Net/NetworkExtensions.cs

@@ -56,7 +56,23 @@ namespace MediaBrowser.Common.Net
         /// <returns>String value of the subnet mask in dotted decimal notation.</returns>
         public static IPAddress CidrToMask(byte cidr, AddressFamily family)
         {
-            uint addr = 0xFFFFFFFF << (family == AddressFamily.InterNetwork ? 32 : 128 - cidr);
+            uint addr = 0xFFFFFFFF << ((family == AddressFamily.InterNetwork ? 32 : 128) - cidr);
+            addr = ((addr & 0xff000000) >> 24)
+                   | ((addr & 0x00ff0000) >> 8)
+                   | ((addr & 0x0000ff00) << 8)
+                   | ((addr & 0x000000ff) << 24);
+            return new IPAddress(addr);
+        }
+
+        /// <summary>
+        /// Convert a subnet mask in CIDR notation to a dotted decimal string value. IPv4 only.
+        /// </summary>
+        /// <param name="cidr">Subnet mask in CIDR notation.</param>
+        /// <param name="family">IPv4 or IPv6 family.</param>
+        /// <returns>String value of the subnet mask in dotted decimal notation.</returns>
+        public static IPAddress CidrToMask(int cidr, AddressFamily family)
+        {
+            uint addr = 0xFFFFFFFF << ((family == AddressFamily.InterNetwork ? 32 : 128) - cidr);
             addr = ((addr & 0xff000000) >> 24)
                    | ((addr & 0x00ff0000) >> 8)
                    | ((addr & 0x0000ff00) << 8)
@@ -319,5 +335,19 @@ namespace MediaBrowser.Common.Net
             addresses = Array.Empty<IPAddress>();
             return false;
         }
+
+        /// <summary>
+        /// Gets the broadcast address for a <see cref="IPNetwork"/>.
+        /// </summary>
+        /// <param name="network">The <see cref="IPNetwork"/>.</param>
+        /// <returns>The broadcast address.</returns>
+        public static IPAddress GetBroadcastAddress(IPNetwork network)
+        {
+            uint ipAddress = BitConverter.ToUInt32(network.Prefix.GetAddressBytes(), 0);
+            uint ipMaskV4 = BitConverter.ToUInt32(CidrToMask(network.PrefixLength, AddressFamily.InterNetwork).GetAddressBytes(), 0);
+            uint broadCastIpAddress = ipAddress | ~ipMaskV4;
+
+            return new IPAddress(BitConverter.GetBytes(broadCastIpAddress));
+        }
     }
 }