update local address detection

Conflicts:
	MediaBrowser.Server.Startup.Common/ApplicationHost.cs
This commit is contained in:
Luke Pulverenti 2015-12-28 22:39:38 -05:00
parent 2ed5c3d0e7
commit 8998f906c6
8 changed files with 102 additions and 98 deletions

View file

@ -32,6 +32,12 @@ namespace MediaBrowser.Api.System
} }
[Route("/System/Ping", "POST")]
public class PingSystem : IReturnVoid
{
}
/// <summary> /// <summary>
/// Class RestartApplication /// Class RestartApplication
/// </summary> /// </summary>
@ -117,6 +123,11 @@ namespace MediaBrowser.Api.System
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
public void Post(PingSystem request)
{
}
public object Get(GetServerLogs request) public object Get(GetServerLogs request)
{ {
List<FileSystemMetadata> files; List<FileSystemMetadata> files;

View file

@ -69,7 +69,7 @@ namespace MediaBrowser.Common.Implementations.Networking
list.AddRange(GetLocalIpAddressesFallback()); list.AddRange(GetLocalIpAddressesFallback());
} }
return list.Where(i => !IPAddress.IsLoopback(i)).Where(FilterIpAddress).DistinctBy(i => i.ToString()); return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
} }
private bool FilterIpAddress(IPAddress address) private bool FilterIpAddress(IPAddress address)
@ -232,7 +232,7 @@ namespace MediaBrowser.Common.Implementations.Networking
return properties.UnicastAddresses return properties.UnicastAddresses
.Select(i => i.Address) .Select(i => i.Address)
.Where(i => i.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(i)) .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
.ToList(); .ToList();
} }
catch (Exception ex) catch (Exception ex)

View file

@ -1,6 +1,8 @@
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using System; using System;
using System.Collections.Generic;
using System.Net;
namespace MediaBrowser.Controller namespace MediaBrowser.Controller
{ {
@ -63,7 +65,7 @@ namespace MediaBrowser.Controller
/// Gets the local ip address. /// Gets the local ip address.
/// </summary> /// </summary>
/// <value>The local ip address.</value> /// <value>The local ip address.</value>
string LocalIpAddress { get; } List<IPAddress> LocalIpAddresses { get; }
/// <summary> /// <summary>
/// Gets the local API URL. /// Gets the local API URL.

View file

@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net
/// the ssl certificate localtion on the file system.</param> /// the ssl certificate localtion on the file system.</param>
void StartServer(IEnumerable<string> urlPrefixes, string certificatePath); void StartServer(IEnumerable<string> urlPrefixes, string certificatePath);
/// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
IEnumerable<string> LocalEndPoints { get; }
/// <summary> /// <summary>
/// Stops this instance. /// Stops this instance.
/// </summary> /// </summary>

View file

@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main
private readonly List<string> _registeredServerIds = new List<string>(); private readonly List<string> _registeredServerIds = new List<string>();
private bool _dlnaServerStarted; private bool _dlnaServerStarted;
public DlnaEntryPoint(IServerConfigurationManager config, public DlnaEntryPoint(IServerConfigurationManager config,
ILogManager logManager, ILogManager logManager,
IServerApplicationHost appHost, IServerApplicationHost appHost,
INetworkManager network, INetworkManager network,
ISessionManager sessionManager, ISessionManager sessionManager,
IHttpClient httpClient, IHttpClient httpClient,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IUserManager userManager, IUserManager userManager,
IDlnaManager dlnaManager, IDlnaManager dlnaManager,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
IUserDataManager userDataManager, IUserDataManager userDataManager,
ILocalizationManager localization, ILocalizationManager localization,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery) ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
{ {
_config = config; _config = config;
@ -148,14 +148,20 @@ namespace MediaBrowser.Dlna.Main
private void RegisterServerEndpoints() private void RegisterServerEndpoints()
{ {
foreach (var address in _network.GetLocalIpAddresses()) foreach (var address in _appHost.LocalIpAddresses)
{ {
var addressString = address.ToString (); //if (IPAddress.IsLoopback(address))
var guid = addressString.GetMD5(); //{
// // Should we allow this?
// continue;
//}
var addressString = address.ToString();
var guid = addressString.GetMD5();
var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml"; var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml";
var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI); var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
var services = new List<string> var services = new List<string>
{ {
@ -166,8 +172,8 @@ namespace MediaBrowser.Dlna.Main
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1", "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
"uuid:" + guid.ToString("N") "uuid:" + guid.ToString("N")
}; };
_ssdpHandler.RegisterNotification(guid, uri, address, services); _ssdpHandler.RegisterNotification(guid, uri, address, services);
_registeredServerIds.Add(guid.ToString("N")); _registeredServerIds.Add(guid.ToString("N"));
} }

View file

@ -110,8 +110,11 @@ namespace MediaBrowser.Dlna.Ssdp
{ {
if (e.LocalEndPoint == null) if (e.LocalEndPoint == null)
{ {
var ip = _appHost.LocalIpAddress; var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0); if (ip != null)
{
e.LocalEndPoint = new IPEndPoint(ip, 0);
}
} }
if (e.LocalEndPoint != null) if (e.LocalEndPoint != null)

View file

@ -40,33 +40,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected; public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting; public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting;
private readonly List<string> _localEndpoints = new List<string>();
private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim();
public string CertificatePath { get; private set; } public string CertificatePath { get; private set; }
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
/// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
public IEnumerable<string> LocalEndPoints
{
get
{
_localEndpointLock.EnterReadLock();
var list = _localEndpoints.ToList();
_localEndpointLock.ExitReadLock();
return list;
}
}
public HttpListenerHost(IApplicationHost applicationHost, public HttpListenerHost(IApplicationHost applicationHost,
ILogManager logManager, ILogManager logManager,
IServerConfigurationManager config, IServerConfigurationManager config,
@ -178,22 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private void OnRequestReceived(string localEndPoint) private void OnRequestReceived(string localEndPoint)
{ {
var ignore = _networkManager.IsInPrivateAddressSpace(localEndPoint);
if (ignore)
{
return;
}
if (_localEndpointLock.TryEnterWriteLock(100))
{
var list = _localEndpoints;
list.Remove(localEndPoint);
list.Insert(0, localEndPoint);
_localEndpointLock.ExitWriteLock();
}
} }
/// <summary> /// <summary>

View file

@ -91,10 +91,12 @@ using MediaBrowser.Server.Startup.Common.Migrations;
using MediaBrowser.WebDashboard.Api; using MediaBrowser.WebDashboard.Api;
using MediaBrowser.XbmcMetadata.Providers; using MediaBrowser.XbmcMetadata.Providers;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -207,6 +209,7 @@ namespace MediaBrowser.Server.Startup.Common
private readonly string _remotePackageName; private readonly string _remotePackageName;
internal INativeApp NativeApp { get; set; } internal INativeApp NativeApp { get; set; }
private Timer _ipAddressCacheTimer;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost" /> class. /// Initializes a new instance of the <see cref="ApplicationHost" /> class.
@ -230,6 +233,8 @@ namespace MediaBrowser.Server.Startup.Common
NativeApp = nativeApp; NativeApp = nativeApp;
SetBaseExceptionMessage(); SetBaseExceptionMessage();
_ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
} }
private Version _version; private Version _version;
@ -1108,14 +1113,14 @@ namespace MediaBrowser.Server.Startup.Common
try try
{ {
// 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 = LocalIpAddress; var address = LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
if (!string.IsNullOrWhiteSpace(address)) if (address != null)
{ {
address = GetLocalApiUrl(address); return GetLocalApiUrl(address.ToString());
} }
return address; return null;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1133,41 +1138,62 @@ namespace MediaBrowser.Server.Startup.Common
HttpPort.ToString(CultureInfo.InvariantCulture)); HttpPort.ToString(CultureInfo.InvariantCulture));
} }
public string LocalIpAddress public List<IPAddress> LocalIpAddresses
{
get
{
return HttpServerIpAddresses.FirstOrDefault();
}
}
private IEnumerable<string> HttpServerIpAddresses
{ {
get get
{ {
var localAddresses = NetworkManager.GetLocalIpAddresses() var localAddresses = NetworkManager.GetLocalIpAddresses()
.Select(i => i.ToString()) .Where(IsIpAddressValid)
.ToList(); .ToList();
var httpServerAddresses = HttpServer.LocalEndPoints return localAddresses;
.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;
}
return matchedAddresses;
} }
} }
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private bool IsIpAddressValid(IPAddress address)
{
if (IPAddress.IsLoopback(address))
{
return true;
}
var apiUrl = GetLocalApiUrl(address.ToString());
apiUrl += "/system/ping";
bool cachedResult;
if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
{
return cachedResult;
}
try
{
using (var response = HttpClient.SendAsync(new HttpRequestOptions
{
Url = apiUrl,
BufferContent = false,
LogErrorResponseBody = false,
LogErrors = false
}, "POST").Result)
{
_validAddressResults.AddOrUpdate(apiUrl, true, (k, v) => true);
return true;
}
}
catch
{
_validAddressResults.AddOrUpdate(apiUrl, true, (k, v) => false);
return false;
}
}
private void OnCacheClearTimerFired(object state)
{
_validAddressResults.Clear();
}
public string FriendlyName public string FriendlyName
{ {
get get