@ -9,55 +9,38 @@ using System.Threading.Tasks;
using MediaBrowser.Common.Net ;
using MediaBrowser.Model.IO ;
using MediaBrowser.Model.Net ;
using MediaBrowser.Model.System ;
using Microsoft.Extensions.Logging ;
using OperatingSystem = MediaBrowser . Common . System . OperatingSystem ;
namespace Emby.Server.Implementations.Networking
{
public class NetworkManager : INetworkManager
{
pr otected ILogger Logger { get ; private set ; }
pr ivate readonly ILogger _logger ;
p ublic event EventHandler NetworkChanged ;
p ublic Func < string [ ] > LocalSubnetsFn { get ; set ; }
p rivate IPAddress [ ] _localIpAddresses ;
p rivate readonly object _localIpAddressSyncLock = new object ( ) ;
public NetworkManager ( ILogger Factory loggerFactory )
public NetworkManager ( ILogger < NetworkManager > logger )
{
Logger = loggerFactory . CreateLogger ( nameof ( NetworkManager ) ) ;
// In FreeBSD these events cause a crash
if ( OperatingSystem . Id ! = OperatingSystemId . BSD )
{
try
{
NetworkChange . NetworkAddressChanged + = NetworkChange_NetworkAddressChanged ;
}
catch ( Exception ex )
{
Logger . LogError ( ex , "Error binding to NetworkAddressChanged event" ) ;
}
_logger = logger ;
try
{
NetworkChange . NetworkAvailabilityChanged + = NetworkChange_NetworkAvailabilityChanged ;
}
catch ( Exception ex )
{
Logger . LogError ( ex , "Error binding to NetworkChange_NetworkAvailabilityChanged event" ) ;
}
}
NetworkChange . NetworkAddressChanged + = OnNetworkAddressChanged ;
NetworkChange . NetworkAvailabilityChanged + = OnNetworkAvailabilityChanged ;
}
private void NetworkChange_NetworkAvailabilityChanged ( object sender , NetworkAvailabilityEventArgs e )
public Func < string [ ] > LocalSubnetsFn { get ; set ; }
public event EventHandler NetworkChanged ;
private void OnNetworkAvailabilityChanged ( object sender , NetworkAvailabilityEventArgs e )
{
Logger . LogDebug ( "NetworkAvailabilityChanged" ) ;
_logger . LogDebug ( "NetworkAvailabilityChanged" ) ;
OnNetworkChanged ( ) ;
}
private void NetworkChange_ NetworkAddressChanged( object sender , EventArgs e )
private void On NetworkAddressChanged( object sender , EventArgs e )
{
L ogger. LogDebug ( "NetworkAddressChanged" ) ;
_l ogger. LogDebug ( "NetworkAddressChanged" ) ;
OnNetworkChanged ( ) ;
}
@ -68,39 +51,35 @@ namespace Emby.Server.Implementations.Networking
_localIpAddresses = null ;
_macAddresses = null ;
}
if ( NetworkChanged ! = null )
{
NetworkChanged ( this , EventArgs . Empty ) ;
}
}
private IpAddressInfo [ ] _localIpAddresses ;
private readonly object _localIpAddressSyncLock = new object ( ) ;
public IpAddressInfo [ ] GetLocalIpAddresses ( bool ignoreVirtualInterface = true )
public IPAddress [ ] GetLocalIpAddresses ( bool ignoreVirtualInterface = true )
{
lock ( _localIpAddressSyncLock )
{
if ( _localIpAddresses = = null )
{
var addresses = GetLocalIpAddressesInternal ( ignoreVirtualInterface ) . Result. Select ( ToIpAddressInfo ) . ToArray( ) ;
var addresses = GetLocalIpAddressesInternal ( ignoreVirtualInterface ) . ToArray( ) ;
_localIpAddresses = addresses ;
return addresses ;
}
return _localIpAddresses ;
}
}
private async Task < List < IPAddress > > GetLocalIpAddressesInternal ( bool ignoreVirtualInterface )
private List < IPAddress > GetLocalIpAddressesInternal ( bool ignoreVirtualInterface )
{
var list = GetIPsDefault ( ignoreVirtualInterface )
. ToList ( ) ;
var list = GetIPsDefault ( ignoreVirtualInterface ) . ToList ( ) ;
if ( list . Count = = 0 )
{
list . AddRange ( await GetLocalIpAddressesFallback ( ) . ConfigureAwait ( false ) ) ;
list = GetLocalIpAddressesFallback ( ) . GetAwaiter ( ) . GetResult ( ) . ToList ( ) ;
}
var listClone = list . ToList ( ) ;
@ -351,13 +330,13 @@ namespace Emby.Server.Implementations.Networking
try
{
var host = uri . DnsSafeHost ;
L ogger. LogDebug ( "Resolving host {0}" , host ) ;
_l ogger. LogDebug ( "Resolving host {0}" , host ) ;
address = GetIpAddresses ( host ) . Result . FirstOrDefault ( ) ;
if ( address ! = null )
{
L ogger. LogDebug ( "{0} resolved to {1}" , host , address ) ;
_l ogger. LogDebug ( "{0} resolved to {1}" , host , address ) ;
return IsInLocalNetworkInternal ( address . ToString ( ) , false ) ;
}
@ -368,7 +347,7 @@ namespace Emby.Server.Implementations.Networking
}
catch ( Exception ex )
{
L ogger. LogError ( ex , "Error resolving hostname" ) ;
_l ogger. LogError ( ex , "Error resolving hostname" ) ;
}
}
}
@ -381,56 +360,41 @@ namespace Emby.Server.Implementations.Networking
return Dns . GetHostAddressesAsync ( hostName ) ;
}
private List < IPAddress > GetIPsDefault ( bool ignoreVirtualInterface )
private IEnumerable < IPAddress > GetIPsDefault ( bool ignoreVirtualInterface )
{
NetworkInterface[ ] interfaces ;
IEnumerable< NetworkInterface > interfaces ;
try
{
var validStatuses = new [ ] { OperationalStatus . Up , OperationalStatus . Unknown } ;
interfaces = NetworkInterface . GetAllNetworkInterfaces ( )
. Where ( i = > validStatuses . Contains ( i . OperationalStatus ) )
. ToArray ( ) ;
. Where ( x = > x . OperationalStatus = = OperationalStatus . Up
| | x . OperationalStatus = = OperationalStatus . Unknown ) ;
}
catch ( Exception ex )
catch ( NetworkInformation Exception ex )
{
L ogger. LogError ( ex , "Error in GetAllNetworkInterfaces" ) ;
return new List < IPAddress > ( ) ;
_l ogger. LogError ( ex , "Error in GetAllNetworkInterfaces" ) ;
return Enumerable . Empty < IPAddress > ( ) ;
}
return interfaces . SelectMany ( network = >
{
var ipProperties = network . GetIPProperties ( ) ;
try
{
// suppress logging because it might be causing nas device wake up
//logger.LogDebug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
var ipProperties = network . GetIPProperties ( ) ;
// Try to exclude virtual adapters
// http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms
var addr = ipProperties . GatewayAddresses . FirstOrDefault ( ) ;
if ( addr = = null | | ignoreVirtualInterface & & string . Equals ( addr . Address . ToString ( ) , "0.0.0.0" , StringComparison . OrdinalIgnoreCase ) )
{
return new List < IPAddress > ( ) ;
}
return ipProperties . UnicastAddresses
. Select ( i = > i . Address )
. Where ( i = > i . AddressFamily = = AddressFamily . InterNetwork | | i . AddressFamily = = AddressFamily . InterNetworkV6 )
. ToList ( ) ;
}
catch ( Exception ex )
// Try to exclude virtual adapters
// http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms
var addr = ipProperties . GatewayAddresses . FirstOrDefault ( ) ;
if ( addr = = null
| | ( ignoreVirtualInterface
& & ( addr . Address . Equals ( IPAddress . Any ) | | addr . Address . Equals ( IPAddress . IPv6Any ) ) ) )
{
Logger . LogError ( ex , "Error querying network interface" ) ;
return new List < IPAddress > ( ) ;
return Enumerable . Empty < IPAddress > ( ) ;
}
return ipProperties . UnicastAddresses
. Select ( i = > i . Address )
. Where ( i = > i . AddressFamily = = AddressFamily . InterNetwork | | i . AddressFamily = = AddressFamily . InterNetworkV6 ) ;
} ) . GroupBy ( i = > i . ToString ( ) )
. Select ( x = > x . First ( ) )
. ToList ( ) ;
. Select ( x = > x . First ( ) ) ;
}
private static async Task < IEnumerable < IPAddress > > GetLocalIpAddressesFallback ( )
@ -612,32 +576,10 @@ namespace Emby.Server.Implementations.Networking
return hosts [ 0 ] ;
}
public IpAddressInfo ParseIpAddress ( string ipAddress )
{
if ( TryParseIpAddress ( ipAddress , out var info ) )
{
return info ;
}
throw new ArgumentException ( "Invalid ip address: " + ipAddress ) ;
}
public bool TryParseIpAddress ( string ipAddress , out IpAddressInfo ipAddressInfo )
public bool IsInSameSubnet ( IPAddress address1 , IPAddress address2 , IPAddress subnetMask )
{
if ( IPAddress . TryParse ( ipAddress , out var address ) )
{
ipAddressInfo = ToIpAddressInfo ( address ) ;
return true ;
}
ipAddressInfo = null ;
return false ;
}
public bool IsInSameSubnet ( IpAddressInfo address1 , IpAddressInfo address2 , IpAddressInfo subnetMask )
{
IPAddress network1 = GetNetworkAddress ( ToIPAddress ( address1 ) , ToIPAddress ( subnetMask ) ) ;
IPAddress network2 = GetNetworkAddress ( ToIPAddress ( address2 ) , ToIPAddress ( subnetMask ) ) ;
IPAddress network1 = GetNetworkAddress ( address1 , subnetMask ) ;
IPAddress network2 = GetNetworkAddress ( address2 , subnetMask ) ;
return network1 . Equals ( network2 ) ;
}
@ -656,13 +598,13 @@ namespace Emby.Server.Implementations.Networking
{
broadcastAddress [ i ] = ( byte ) ( ipAdressBytes [ i ] & ( subnetMaskBytes [ i ] ) ) ;
}
return new IPAddress ( broadcastAddress ) ;
}
public I pAddressInfo GetLocalIpSubnetMask ( IpAddressInfo address )
public I PAddress GetLocalIpSubnetMask ( IPAddress address )
{
NetworkInterface [ ] interfaces ;
IPAddress ipaddress = ToIPAddress ( address ) ;
try
{
@ -674,7 +616,7 @@ namespace Emby.Server.Implementations.Networking
}
catch ( Exception ex )
{
L ogger. LogError ( ex , "Error in GetAllNetworkInterfaces" ) ;
_l ogger. LogError ( ex , "Error in GetAllNetworkInterfaces" ) ;
return null ;
}
@ -684,83 +626,15 @@ namespace Emby.Server.Implementations.Networking
{
foreach ( UnicastIPAddressInformation ip in ni . GetIPProperties ( ) . UnicastAddresses )
{
if ( ip . Address . Equals ( ip address) & & ip . IPv4Mask ! = null )
if ( ip . Address . Equals ( address) & & ip . IPv4Mask ! = null )
{
return ToIpAddressInfo( ip. IPv4Mask ) ;
return ip. IPv4Mask ;
}
}
}
}
return null ;
}
public static IpEndPointInfo ToIpEndPointInfo ( IPEndPoint endpoint )
{
if ( endpoint = = null )
{
return null ;
}
return new IpEndPointInfo ( ToIpAddressInfo ( endpoint . Address ) , endpoint . Port ) ;
}
public static IPEndPoint ToIPEndPoint ( IpEndPointInfo endpoint )
{
if ( endpoint = = null )
{
return null ;
}
return new IPEndPoint ( ToIPAddress ( endpoint . IpAddress ) , endpoint . Port ) ;
}
public static IPAddress ToIPAddress ( IpAddressInfo address )
{
if ( address . Equals ( IpAddressInfo . Any ) )
{
return IPAddress . Any ;
}
if ( address . Equals ( IpAddressInfo . IPv6Any ) )
{
return IPAddress . IPv6Any ;
}
if ( address . Equals ( IpAddressInfo . Loopback ) )
{
return IPAddress . Loopback ;
}
if ( address . Equals ( IpAddressInfo . IPv6Loopback ) )
{
return IPAddress . IPv6Loopback ;
}
return IPAddress . Parse ( address . Address ) ;
}
public static IpAddressInfo ToIpAddressInfo ( IPAddress address )
{
if ( address . Equals ( IPAddress . Any ) )
{
return IpAddressInfo . Any ;
}
if ( address . Equals ( IPAddress . IPv6Any ) )
{
return IpAddressInfo . IPv6Any ;
}
if ( address . Equals ( IPAddress . Loopback ) )
{
return IpAddressInfo . Loopback ;
}
if ( address . Equals ( IPAddress . IPv6Loopback ) )
{
return IpAddressInfo . IPv6Loopback ;
}
return new IpAddressInfo ( address . ToString ( ) , address . AddressFamily = = AddressFamily . InterNetworkV6 ? IpAddressFamily . InterNetworkV6 : IpAddressFamily . InterNetwork ) ;
}
public async Task < IpAddressInfo [ ] > GetHostAddressesAsync ( string host )
{
var addresses = await Dns . GetHostAddressesAsync ( host ) . ConfigureAwait ( false ) ;
return addresses . Select ( ToIpAddressInfo ) . ToArray ( ) ;
return null ;
}
/// <summary>