Browse Source

Updated to the latest

Greenback 4 years ago
parent
commit
9a9b2bfb2e

+ 3 - 5
Jellyfin.Networking/Configuration/NetworkConfiguration.cs

@@ -99,8 +99,7 @@ namespace Jellyfin.Networking.Configuration
         public bool UPnPCreateHttpPortMap { get; set; }
 
         /// <summary>
-        /// Gets or sets the UDPPortRange
-        /// Gets or sets client udp port range.
+        /// Gets or sets the UDPPortRange.
         /// </summary>
         public string UDPPortRange { get; set; } = string.Empty;
 
@@ -115,8 +114,8 @@ namespace Jellyfin.Networking.Configuration
         public bool EnableIPV4 { get; set; } = true;
 
         /// <summary>
-        /// Gets or sets a value indicating whether detailed ssdp logs are sent to the console/log.
-        /// "Emby.Dlna": "Debug" must be set in logging.default.json for this property to work.
+        /// Gets or sets a value indicating whether detailed SSDP logs are sent to the console/log.
+        /// "Emby.Dlna": "Debug" must be set in logging.default.json for this property to have any effect.
         /// </summary>
         public bool EnableSSDPTracing { get; set; }
 
@@ -143,7 +142,6 @@ namespace Jellyfin.Networking.Configuration
         public bool IgnoreVirtualInterfaces { get; set; } = true;
 
         /// <summary>
-        /// Gets or sets the VirtualInterfaceNames
         /// Gets or sets a value indicating the interfaces that should be ignored. The list can be comma separated. <seealso cref="IgnoreVirtualInterfaces"/>.
         /// </summary>
         public string VirtualInterfaceNames { get; set; } = "vEthernet*";

+ 101 - 83
Jellyfin.Networking/Manager/NetworkManager.cs

@@ -182,7 +182,7 @@ namespace Jellyfin.Networking.Manager
         public IReadOnlyCollection<PhysicalAddress> GetMacAddresses()
         {
             // Populated in construction - so always has values.
-            return _macAddresses.AsReadOnly();
+            return _macAddresses;
         }
 
         /// <inheritdoc/>
@@ -378,7 +378,7 @@ namespace Jellyfin.Networking.Manager
                 }
             }
 
-            _logger.LogDebug("GetBindInterface: Source: {0}, External: {1}:", haveSource, isExternal);
+            _logger.LogDebug("GetBindInterface: Source: {HaveSource}, External: {IsExternal}:", haveSource, isExternal);
 
             // No preference given, so move on to bind addresses.
             if (MatchesBindInterface(source, isExternal, out string result))
@@ -408,20 +408,20 @@ namespace Jellyfin.Networking.Manager
                         if (intf.Contains(source))
                         {
                             result = FormatIP6String(intf.Address);
-                            _logger.LogDebug("{0}: GetBindInterface: Has source, matched best internal interface on range. {1}", source, result);
+                            _logger.LogDebug("{Source}: GetBindInterface: Has source, matched best internal interface on range. {Result}", source, result);
                             return result;
                         }
                     }
                 }
 
                 result = FormatIP6String(interfaces.First().Address);
-                _logger.LogDebug("{0}: GetBindInterface: Matched first internal interface. {1}", source, result);
+                _logger.LogDebug("{Source}: GetBindInterface: Matched first internal interface. {Result}", source, result);
                 return result;
             }
 
             // There isn't any others, so we'll use the loopback.
             result = IsIP6Enabled ? "::" : "127.0.0.1";
-            _logger.LogWarning("{0}: GetBindInterface: Loopback return.", source, result);
+            _logger.LogWarning("{Source}: GetBindInterface: Loopback {Result} returned.", source, result);
             return result;
         }
 
@@ -552,7 +552,7 @@ namespace Jellyfin.Networking.Manager
             {
                 result = new Collection<IPObject>();
 
-                _logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
+                _logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", token);
 
                 // Replace interface tags with the interface IP's.
                 foreach (IPNetAddress iface in _interfaceAddresses)
@@ -575,7 +575,7 @@ namespace Jellyfin.Networking.Manager
         /// Reloads all settings and re-initialises the instance.
         /// </summary>
         /// <param name="configuration">The <see cref="NetworkConfiguration"/> to use.</param>
-        public void UpdateSettings(NetworkConfiguration configuration)
+        public void UpdateSettings(object configuration)
         {
             NetworkConfiguration config = (NetworkConfiguration)configuration ?? throw new ArgumentNullException(nameof(configuration));
 
@@ -740,7 +740,7 @@ namespace Jellyfin.Networking.Manager
             // Null check required here for automated testing.
             if (IsInterface(token, out int index))
             {
-                _logger.LogInformation("Interface {0} used in settings. Using its interface addresses.", token);
+                _logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", token);
 
                 // Replace interface tags with the interface IP's.
                 foreach (IPNetAddress iface in _interfaceAddresses)
@@ -780,7 +780,7 @@ namespace Jellyfin.Networking.Manager
             }
             else
             {
-                _logger.LogDebug("Invalid or unknown network {0}.", token);
+                _logger.LogDebug("Invalid or unknown network {Token}.", token);
             }
         }
 
@@ -867,7 +867,7 @@ namespace Jellyfin.Networking.Manager
                     var parts = entry.Split('=');
                     if (parts.Length != 2)
                     {
-                        _logger.LogError("Unable to parse bind override. {0}", entry);
+                        _logger.LogError("Unable to parse bind override: {Entry}", entry);
                     }
                     else
                     {
@@ -893,7 +893,7 @@ namespace Jellyfin.Networking.Manager
                         }
                         else
                         {
-                            _logger.LogError("Unable to parse bind ip address. {0}", parts[1]);
+                            _logger.LogError("Unable to parse bind ip address. {Parts}", parts[1]);
                         }
                     }
                 }
@@ -905,30 +905,35 @@ namespace Jellyfin.Networking.Manager
         /// </summary>
         private void InitialiseBind(NetworkConfiguration config)
         {
-            string[] lanAddresses = config.LocalNetworkAddresses;
+            lock (_intLock)
+            {
+                string[] lanAddresses = config.LocalNetworkAddresses;
 
-            // TODO: remove when bug fixed: https://github.com/jellyfin/jellyfin-web/issues/1334
+                // TODO: remove when bug fixed: https://github.com/jellyfin/jellyfin-web/issues/1334
 
-            if (lanAddresses.Length == 1 && lanAddresses[0].IndexOf(',', StringComparison.OrdinalIgnoreCase) != -1)
-            {
-                lanAddresses = lanAddresses[0].Split(',');
-            }
+                if (lanAddresses.Length == 1 && lanAddresses[0].IndexOf(',', StringComparison.OrdinalIgnoreCase) != -1)
+                {
+                    lanAddresses = lanAddresses[0].Split(',');
+                }
 
-            // TODO: end fix: https://github.com/jellyfin/jellyfin-web/issues/1334
+                // TODO: end fix: https://github.com/jellyfin/jellyfin-web/issues/1334
 
-            // Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded.
-            if (config.IgnoreVirtualInterfaces)
-            {
-                var newList = lanAddresses.ToList();
-                newList.AddRange(config.VirtualInterfaceNames.Split(',').ToList());
-                lanAddresses = newList.ToArray();
-            }
+                // Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded.
+                if (config.IgnoreVirtualInterfaces)
+                {
+                    var virtualInterfaceNames = config.VirtualInterfaceNames.Split(',');
+                    var newList = new string[lanAddresses.Length + virtualInterfaceNames.Length];
+                    Array.Copy(lanAddresses, newList, lanAddresses.Length);
+                    Array.Copy(virtualInterfaceNames, 0, newList, lanAddresses.Length, virtualInterfaceNames.Length);
+                    lanAddresses = newList;
+                }
 
-            // Read and parse bind addresses and exclusions, removing ones that don't exist.
-            _bindAddresses = CreateIPCollection(lanAddresses).Union(_interfaceAddresses);
-            _bindExclusions = CreateIPCollection(lanAddresses, true).Union(_interfaceAddresses);
-            _logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString());
-            _logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString());
+                // Read and parse bind addresses and exclusions, removing ones that don't exist.
+                _bindAddresses = CreateIPCollection(lanAddresses).Union(_interfaceAddresses);
+                _bindExclusions = CreateIPCollection(lanAddresses, true).Union(_interfaceAddresses);
+                _logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString());
+                _logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString());
+            }
         }
 
         /// <summary>
@@ -936,7 +941,10 @@ namespace Jellyfin.Networking.Manager
         /// </summary>
         private void InitialiseRemote(NetworkConfiguration config)
         {
-            RemoteAddressFilter = CreateIPCollection(config.RemoteIPFilter);
+            lock (_intLock)
+            {
+                RemoteAddressFilter = CreateIPCollection(config.RemoteIPFilter);
+            }
         }
 
         /// <summary>
@@ -959,7 +967,8 @@ namespace Jellyfin.Networking.Manager
                 // If no LAN addresses are specified - all private subnets are deemed to be the LAN
                 _usingPrivateAddresses = _lanSubnets.Count == 0;
 
-                // NOTE: The order of the commands in this statement matters.
+                // NOTE: The order of the commands generating the collection in this statement matters.
+                // Altering the order will cause the collections to be created incorrectly.
                 if (_usingPrivateAddresses)
                 {
                     _logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
@@ -1020,6 +1029,7 @@ namespace Jellyfin.Networking.Manager
 
                 _interfaceNames.Clear();
                 _interfaceAddresses.Clear();
+                _macAddresses.Clear();
 
                 try
                 {
@@ -1051,7 +1061,7 @@ namespace Jellyfin.Networking.Manager
                                     };
 
                                     int tag = nw.Tag;
-                                    if ((ipProperties.GatewayAddresses.Count > 0) && !nw.IsLoopback())
+                                    if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback())
                                     {
                                         // -ve Tags signify the interface has a gateway.
                                         nw.Tag *= -1;
@@ -1072,7 +1082,7 @@ namespace Jellyfin.Networking.Manager
                                     };
 
                                     int tag = nw.Tag;
-                                    if ((ipProperties.GatewayAddresses.Count > 0) && !nw.IsLoopback())
+                                    if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback())
                                     {
                                         // -ve Tags signify the interface has a gateway.
                                         nw.Tag *= -1;
@@ -1087,9 +1097,10 @@ namespace Jellyfin.Networking.Manager
                             }
                         }
 #pragma warning disable CA1031 // Do not catch general exception types
-                        catch
+                        catch (Exception ex)
                         {
                             // Ignore error, and attempt to continue.
+                            _logger.LogError(ex, "Error encountered parsing interfaces.");
                         }
 #pragma warning restore CA1031 // Do not catch general exception types
                     }
@@ -1100,8 +1111,7 @@ namespace Jellyfin.Networking.Manager
                     // If for some reason we don't have an interface info, resolve our DNS name.
                     if (_interfaceAddresses.Count == 0)
                     {
-                        _logger.LogWarning("No interfaces information available. Using loopback.");
-
+                        _logger.LogError("No interfaces information available. Resolving DNS name.");
                         IPHost host = new IPHost(Dns.GetHostName());
                         foreach (var a in host.GetAddresses())
                         {
@@ -1110,7 +1120,7 @@ namespace Jellyfin.Networking.Manager
 
                         if (_interfaceAddresses.Count == 0)
                         {
-                            _logger.LogError("No interfaces information available. Resolving DNS name.");
+                            _logger.LogWarning("No interfaces information available. Using loopback.");
                             // Last ditch attempt - use loopback address.
                             _interfaceAddresses.AddItem(IPNetAddress.IP4Loopback);
                             if (IsIP6Enabled)
@@ -1131,11 +1141,11 @@ namespace Jellyfin.Networking.Manager
         /// Attempts to match the source against a user defined bind interface.
         /// </summary>
         /// <param name="source">IP source address to use.</param>
-        /// <param name="isExternal">True if the source is in the external subnet.</param>
+        /// <param name="isInExternalSubnet">True if the source is in the 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(IPObject source, bool isExternal, out string bindPreference, out int? port)
+        private bool MatchesPublishedServerUrl(IPObject source, bool isInExternalSubnet, out string bindPreference, out int? port)
         {
             bindPreference = string.Empty;
             port = null;
@@ -1144,12 +1154,12 @@ namespace Jellyfin.Networking.Manager
             foreach (var addr in _publishedServerUrls)
             {
                 // Remaining. Match anything.
-                if (addr.Key.Equals(IPAddress.Broadcast))
+                if (addr.Key.Address.Equals(IPAddress.Broadcast))
                 {
                     bindPreference = addr.Value;
                     break;
                 }
-                else if ((addr.Key.Equals(IPAddress.Any) || addr.Key.Equals(IPAddress.IPv6Any)) && isExternal)
+                else if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
                 {
                     // External.
                     bindPreference = addr.Value;
@@ -1163,38 +1173,38 @@ namespace Jellyfin.Networking.Manager
                 }
             }
 
-            if (!string.IsNullOrEmpty(bindPreference))
+            if (string.IsNullOrEmpty(bindPreference))
+            {
+                return false;
+            }
+
+            // Has it got a port defined?
+            var parts = bindPreference.Split(':');
+            if (parts.Length > 1)
             {
-                // Has it got a port defined?
-                var parts = bindPreference.Split(':');
-                if (parts.Length > 1)
+                if (int.TryParse(parts[1], out int p))
                 {
-                    if (int.TryParse(parts[1], out int p))
-                    {
-                        bindPreference = parts[0];
-                        port = p;
-                    }
+                    bindPreference = parts[0];
+                    port = p;
                 }
-
-                return true;
             }
 
-            return false;
+            return true;
         }
 
         /// <summary>
         /// Attempts to match the source against a user defined bind interface.
         /// </summary>
         /// <param name="source">IP source address to use.</param>
-        /// <param name="isExternal">True if the source is in the external subnet.</param>
+        /// <param name="isInExternalSubnet">True if the source is in the external subnet.</param>
         /// <param name="result">The result, if a match is found.</param>
         /// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
-        private bool MatchesBindInterface(IPObject source, bool isExternal, out string result)
+        private bool MatchesBindInterface(IPObject source, bool isInExternalSubnet, out string result)
         {
             result = string.Empty;
-            var nc = _bindAddresses.Exclude(_bindExclusions);
+            var addresses = _bindAddresses.Exclude(_bindExclusions);
 
-            int count = nc.Count;
+            int count = addresses.Count;
             if (count == 1 && (_bindAddresses[0].Equals(IPAddress.Any) || _bindAddresses[0].Equals(IPAddress.IPv6Any)))
             {
                 // Ignore IPAny addresses.
@@ -1205,26 +1215,34 @@ namespace Jellyfin.Networking.Manager
             {
                 // Check to see if any of the bind interfaces are in the same subnet.
 
-                Collection<IPObject> bindResult;
                 IPAddress? defaultGateway = null;
-                IPAddress? bindAddress;
+                IPAddress? bindAddress = null;
 
-                if (isExternal)
+                if (isInExternalSubnet)
                 {
                     // Find all external bind addresses. Store the default gateway, but check to see if there is a better match first.
-                    bindResult = CreateCollection(nc
-                        .Where(p => !IsInLocalNetwork(p))
-                        .OrderBy(p => p.Tag));
-                    defaultGateway = bindResult.FirstOrDefault()?.Address;
-                    bindAddress = bindResult
-                        .Where(p => p.Contains(source))
-                        .OrderBy(p => p.Tag)
-                        .FirstOrDefault()?.Address;
+                    foreach (var addr in addresses.OrderBy(p => p.Tag))
+                    {
+                        if (defaultGateway == null && !IsInLocalNetwork(addr))
+                        {
+                            defaultGateway = addr.Address;
+                        }
+
+                        if (bindAddress == null && addr.Contains(source))
+                        {
+                            bindAddress = addr.Address;
+                        }
+
+                        if (defaultGateway != null && bindAddress != null)
+                        {
+                            break;
+                        }
+                    }
                 }
                 else
                 {
                     // Look for the best internal address.
-                    bindAddress = nc
+                    bindAddress = addresses
                         .Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None)))
                         .OrderBy(p => p.Tag)
                         .FirstOrDefault()?.Address;
@@ -1233,23 +1251,23 @@ namespace Jellyfin.Networking.Manager
                 if (bindAddress != null)
                 {
                     result = FormatIP6String(bindAddress);
-                    _logger.LogDebug("{0}: GetBindInterface: Has source, found a match bind interface subnets. {1}", source, result);
+                    _logger.LogDebug("{Source}: GetBindInterface: Has source, found a match bind interface subnets. {Result}", source, result);
                     return true;
                 }
 
-                if (isExternal && defaultGateway != null)
+                if (isInExternalSubnet && defaultGateway != null)
                 {
                     result = FormatIP6String(defaultGateway);
-                    _logger.LogDebug("{0}: GetBindInterface: Using first user defined external interface. {1}", source, result);
+                    _logger.LogDebug("{Source}: GetBindInterface: Using first user defined external interface. {Result}", source, result);
                     return true;
                 }
 
-                result = FormatIP6String(nc.First().Address);
-                _logger.LogDebug("{0}: GetBindInterface: Selected first user defined interface. {1}", source, result);
+                result = FormatIP6String(addresses[0].Address);
+                _logger.LogDebug("{Source}: GetBindInterface: Selected first user defined interface. {Result}", source, result);
 
-                if (isExternal)
+                if (isInExternalSubnet)
                 {
-                    _logger.LogWarning("{0}: External request received, however, only an internal interface bind found.", source);
+                    _logger.LogWarning("{Source}: External request received, however, only an internal interface bind found.", source);
                 }
 
                 return true;
@@ -1268,12 +1286,12 @@ namespace Jellyfin.Networking.Manager
         {
             result = string.Empty;
             // Get the first WAN interface address that isn't a loopback.
-            var extResult = CreateCollection(_interfaceAddresses
+            var extResult = _interfaceAddresses
                 .Exclude(_bindExclusions)
                 .Where(p => !IsInLocalNetwork(p))
-                .OrderBy(p => p.Tag));
+                .OrderBy(p => p.Tag);
 
-            if (extResult.Count > 0)
+            if (extResult.Any())
             {
                 // Does the request originate in one of the interface subnets?
                 // (For systems with multiple internal network cards, and multiple subnets)
@@ -1282,19 +1300,19 @@ namespace Jellyfin.Networking.Manager
                     if (!IsInLocalNetwork(intf) && intf.Contains(source))
                     {
                         result = FormatIP6String(intf.Address);
-                        _logger.LogDebug("{0}: GetBindInterface: Selected best external on interface on range. {1}", source, result);
+                        _logger.LogDebug("{Source}: GetBindInterface: Selected best external on interface on range. {Result}", source, result);
                         return true;
                     }
                 }
 
                 result = FormatIP6String(extResult.First().Address);
-                _logger.LogDebug("{0}: GetBindInterface: Selected first external interface. {0}", source, result);
+                _logger.LogDebug("{Source}: GetBindInterface: Selected first external interface. {Result}", source, result);
                 return true;
             }
 
             // Have to return something, so return an internal address
 
-            _logger.LogWarning("{0}: External request received, however, no WAN interface found.", source);
+            _logger.LogWarning("{Source}: External request received, however, no WAN interface found.", source);
             return false;
         }
     }

+ 15 - 14
MediaBrowser.Common/Net/IPHost.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System;
+using System.Diagnostics;
 using System.Linq;
 using System.Net;
 using System.Net.Sockets;
@@ -13,6 +14,11 @@ namespace MediaBrowser.Common.Net
     /// </summary>
     public class IPHost : IPObject
     {
+        /// <summary>
+        /// Gets or sets timeout value before resolve required, in minutes.
+        /// </summary>
+        public const int Timeout = 30;
+
         /// <summary>
         /// Represents an IPHost that has no value.
         /// </summary>
@@ -21,7 +27,7 @@ namespace MediaBrowser.Common.Net
         /// <summary>
         /// Time when last resolved in ticks.
         /// </summary>
-        private long _lastResolved;
+        private DateTime? _lastResolved = null;
 
         /// <summary>
         /// Gets the IP Addresses, attempting to resolve the name, if there are none.
@@ -83,15 +89,9 @@ namespace MediaBrowser.Common.Net
             {
                 // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length,
                 // which is automatically determined by it's IP type. Anything else is meaningless.
-                throw new NotImplementedException("The prefix length on a host cannot be set.");
             }
         }
 
-        /// <summary>
-        /// Gets or sets timeout value before resolve required, in minutes.
-        /// </summary>
-        public byte Timeout { get; set; } = 30;
-
         /// <summary>
         /// Gets a value indicating whether the address has a value.
         /// </summary>
@@ -395,15 +395,15 @@ namespace MediaBrowser.Common.Net
         private bool ResolveHost()
         {
             // When was the last time we resolved?
-            if (_lastResolved == 0)
+            if (_lastResolved == null)
             {
-                _lastResolved = DateTime.UtcNow.Ticks;
+                _lastResolved = DateTime.UtcNow;
             }
 
-            // If we haven't resolved before, or out timer has run out...
-            if ((_addresses.Length == 0 && !Resolved) || (TimeSpan.FromTicks(DateTime.UtcNow.Ticks - _lastResolved).TotalMinutes > Timeout))
+            // If we haven't resolved before, or our timer has run out...
+            if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved?.AddMinutes(Timeout)))
             {
-                _lastResolved = DateTime.UtcNow.Ticks;
+                _lastResolved = DateTime.UtcNow;
                 ResolveHostInternal().GetAwaiter().GetResult();
                 Resolved = true;
             }
@@ -433,9 +433,10 @@ namespace MediaBrowser.Common.Net
                         IPHostEntry ip = await Dns.GetHostEntryAsync(HostName).ConfigureAwait(false);
                         _addresses = ip.AddressList;
                     }
-                    catch (SocketException)
+                    catch (SocketException ex)
                     {
-                        // Ignore socket errors, as the result value will just be an empty array.
+                        // Log and then ignore socket errors, as the result value will just be an empty array.
+                        Debug.WriteLine("GetHostEntryAsync failed with {Message}.", ex.Message);
                     }
                 }
             }

+ 4 - 4
MediaBrowser.Common/Net/IPNetAddress.cs

@@ -18,17 +18,17 @@ namespace MediaBrowser.Common.Net
         /// <summary>
         /// IPv4 multicast address.
         /// </summary>
-        public static readonly IPAddress MulticastIPv4 = IPAddress.Parse("239.255.255.250");
+        public static readonly IPAddress SSDPMulticastIPv4 = IPAddress.Parse("239.255.255.250");
 
         /// <summary>
         /// IPv6 local link multicast address.
         /// </summary>
-        public static readonly IPAddress MulticastIPv6LinkLocal = IPAddress.Parse("ff02::C");
+        public static readonly IPAddress SSDPMulticastIPv6LinkLocal = IPAddress.Parse("ff02::C");
 
         /// <summary>
         /// IPv6 site local multicast address.
         /// </summary>
-        public static readonly IPAddress MulticastIPv6SiteLocal = IPAddress.Parse("ff05::C");
+        public static readonly IPAddress SSDPMulticastIPv6SiteLocal = IPAddress.Parse("ff05::C");
 
         /// <summary>
         /// IP4Loopback address host.
@@ -235,7 +235,7 @@ namespace MediaBrowser.Common.Net
         /// <summary>
         /// Returns a textual representation of this object.
         /// </summary>
-        /// <param name="shortVersion">Set to true, if the subnet is to be included as part of the address.</param>
+        /// <param name="shortVersion">Set to true, if the subnet is to be excluded as part of the address.</param>
         /// <returns>String representation of this object.</returns>
         public string ToString(bool shortVersion)
         {

+ 21 - 10
MediaBrowser.Common/Net/IPObject.cs

@@ -86,7 +86,9 @@ namespace MediaBrowser.Common.Net
             // prefix length value. eg. /16 on a 4 octet ip4 address (192.168.2.240) will result in the 2 and the 240 being zeroed out.
             // Where there is not an exact boundary (eg /23), mod is used to calculate how many bits of this value are to be kept.
 
-            byte[] addressBytes = address.GetAddressBytes();
+            // GetAddressBytes
+            Span<byte> addressBytes = stackalloc byte[address.AddressFamily == AddressFamily.InterNetwork ? 4 : 16];
+            address.TryWriteBytes(addressBytes, out _);
 
             int div = prefixLength / 8;
             int mod = prefixLength % 8;
@@ -170,14 +172,16 @@ namespace MediaBrowser.Common.Net
 
             if (!address.Equals(IPAddress.None))
             {
-                if (address.AddressFamily == AddressFamily.InterNetwork)
+                if (address.IsIPv4MappedToIPv6)
                 {
-                    if (address.IsIPv4MappedToIPv6)
-                    {
-                        address = address.MapToIPv4();
-                    }
+                    address = address.MapToIPv4();
+                }
 
-                    byte[] octet = address.GetAddressBytes();
+                if (address.AddressFamily == AddressFamily.InterNetwork)
+                {
+                    // GetAddressBytes
+                    Span<byte> octet = stackalloc byte[4];
+                    address.TryWriteBytes(octet, out _);
 
                     return (octet[0] == 10)
                            || (octet[0] == 172 && octet[1] >= 16 && octet[1] <= 31) // RFC1918
@@ -186,7 +190,10 @@ namespace MediaBrowser.Common.Net
                 }
                 else
                 {
-                    byte[] octet = address.GetAddressBytes();
+                    // GetAddressBytes
+                    Span<byte> octet = stackalloc byte[16];
+                    address.TryWriteBytes(octet, out _);
+
                     uint word = (uint)(octet[0] << 8) + octet[1];
 
                     return (word >= 0xfe80 && word <= 0xfebf) // fe80::/10 :Local link.
@@ -223,7 +230,9 @@ namespace MediaBrowser.Common.Net
                 return false;
             }
 
-            byte[] octet = address.GetAddressBytes();
+            // GetAddressBytes
+            Span<byte> octet = stackalloc byte[16];
+            address.TryWriteBytes(octet, out _);
             uint word = (uint)(octet[0] << 8) + octet[1];
 
             return word >= 0xfe80 && word <= 0xfebf; // fe80::/10 :Local link.
@@ -261,7 +270,9 @@ namespace MediaBrowser.Common.Net
             byte cidrnet = 0;
             if (!mask.Equals(IPAddress.Any))
             {
-                byte[] bytes = mask.GetAddressBytes();
+                // GetAddressBytes
+                Span<byte> bytes = stackalloc byte[mask.AddressFamily == AddressFamily.InterNetwork ? 4 : 16];
+                mask.TryWriteBytes(bytes, out _);
 
                 var zeroed = false;
                 for (var i = 0; i < bytes.Length; i++)