From 168587b2a0d1f495a9f85e05b1e518f615b0cfcc Mon Sep 17 00:00:00 2001 From: Sven Van den brande Date: Sun, 27 Mar 2016 23:11:27 +0200 Subject: Remove unused code... --- .../EntryPoints/ActivityLogEntryPoint.cs | 18 ++++++++---------- .../EntryPoints/ExternalPortForwarding.cs | 1 - .../EntryPoints/LibraryChangedNotifier.cs | 4 +--- .../EntryPoints/LoadRegistrations.cs | 1 - .../EntryPoints/Notifications/Notifications.cs | 2 -- .../EntryPoints/UsageReporter.cs | 1 - 6 files changed, 9 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs index dfaedbc9d..46ddf3dd8 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs @@ -5,11 +5,9 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; using MediaBrowser.Controller.Activity; -using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; @@ -206,7 +204,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints Name = name, Type = "SessionEnded", ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint), - UserId = (session.UserId.HasValue ? session.UserId.Value.ToString("N") : null) + UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null }); } @@ -336,7 +334,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints Name = name, Type = "SessionStarted", ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint), - UserId = (session.UserId.HasValue ? session.UserId.Value.ToString("N") : null) + UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null }); } @@ -518,16 +516,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints int days = span.Days; if (days >= DaysInYear) { - int years = (days / DaysInYear); + int years = days / DaysInYear; values.Add(CreateValueString(years, "year")); - days = (days % DaysInYear); + days = days % DaysInYear; } // Number of months if (days >= DaysInMonth) { - int months = (days / DaysInMonth); + int months = days / DaysInMonth; values.Add(CreateValueString(months, "month")); - days = (days % DaysInMonth); + days = days % DaysInMonth; } // Number of days if (days >= 1) @@ -547,7 +545,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints for (int i = 0; i < values.Count; i++) { if (builder.Length > 0) - builder.Append((i == (values.Count - 1)) ? " and " : ", "); + builder.Append(i == values.Count - 1 ? " and " : ", "); builder.Append(values[i]); } // Return result @@ -562,7 +560,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private static string CreateValueString(int value, string description) { return String.Format("{0:#,##0} {1}", - value, (value == 1) ? description : String.Format("{0}s", description)); + value, value == 1 ? description : String.Format("{0}s", description)); } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 2b2c338dd..95763c43f 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -10,7 +10,6 @@ using System.Globalization; using System.IO; using System.Net; using System.Text; -using System.Threading; using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Implementations.EntryPoints diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 237c7157b..afc4e9702 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; @@ -11,7 +10,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.LiveTv; namespace MediaBrowser.Server.Implementations.EntryPoints { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs index efda36821..f41d81137 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; using System; -using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Threading; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index da1d25f2c..918110226 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -22,8 +22,6 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.LiveTv; namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs index cbec91679..7e22efb23 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs @@ -8,7 +8,6 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Logging; namespace MediaBrowser.Server.Implementations.EntryPoints -- cgit v1.2.3 From d5b7ed325e5930b30fd8ecf54088d1bccdd2e8ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 14:46:03 -0400 Subject: switch from Mono.Nat to Open.Nat --- .../EntryPoints/ExternalPortForwarding.cs | 221 ++++----------------- .../MediaBrowser.Server.Implementations.csproj | 4 + .../packages.config | 1 + 3 files changed, 49 insertions(+), 177 deletions(-) (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 95763c43f..c0c626438 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; -using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -11,6 +10,9 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; +using Open.Nat; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -20,9 +22,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - - private PeriodicTimer _timer; - private bool _isStarted; + private CancellationTokenSource _currentCancellationTokenSource; + private TimeSpan _interval = TimeSpan.FromHours(1); public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -32,223 +33,89 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _ssdp = ssdp; } - private string _lastConfigIdentifier; - private string GetConfigIdentifier() - { - var values = new List(); - var config = _config.Configuration; - - values.Add(config.EnableUPnP.ToString()); - values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); - values.Add(config.EnableHttps.ToString()); - values.Add(_appHost.EnableHttps.ToString()); - - return string.Join("|", values.ToArray()); - } - - void _config_ConfigurationUpdated(object sender, EventArgs e) - { - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) - { - if (_isStarted) - { - DisposeNat(); - } - - Run(); - } - } - public void Run() { //NatUtility.Logger = new LogWriter(_logger); if (_config.Configuration.EnableUPnP) { - Start(); + Discover(); } - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private void Start() + private async void Discover() { - _logger.Debug("Starting NAT discovery"); - NatUtility.EnabledProtocols = new List - { - NatProtocol.Pmp - }; - NatUtility.DeviceFound += NatUtility_DeviceFound; - - // Mono.Nat does never rise this event. The event is there however it is useless. - // You could remove it with no risk. - NatUtility.DeviceLost += NatUtility_DeviceLost; - - - // it is hard to say what one should do when an unhandled exception is raised - // because there isn't anything one can do about it. Probably save a log or ignored it. - NatUtility.UnhandledException += NatUtility_UnhandledException; - NatUtility.StartDiscovery(); - - _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - - _ssdp.MessageReceived += _ssdp_MessageReceived; + var discoverer = new NatDiscoverer(); - _lastConfigIdentifier = GetConfigIdentifier(); + var cancellationTokenSource = new CancellationTokenSource(10000); + _currentCancellationTokenSource = cancellationTokenSource; - _isStarted = true; - } - - void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) - { - var endpoint = e.EndPoint as IPEndPoint; - - if (endpoint != null && e.LocalEndPoint != null) + try { - NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); - } - } - - void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - var ex = e.ExceptionObject as Exception; + var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); - if (ex == null) - { - //_logger.Error("Unidentified error reported by Mono.Nat"); + await CreateRules(device).ConfigureAwait(false); } - else + catch (OperationCanceledException) { - // Seeing some blank exceptions coming through here - //_logger.ErrorException("Error reported by Mono.Nat: ", ex); - } - } - - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) - { - try - { - var device = e.Device; - _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); - CreateRules(device); } catch (Exception ex) { - // I think it could be a good idea to log the exception because - // you are using permanent portmapping here (never expire) and that means that next time - // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends - // on the router's upnp implementation (specs says it should fail however some routers don't do it) - // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable - // and those errors (upnp errors) could be useful for diagnosting. - - // Commenting out because users are reporting problems out of our control - //_logger.ErrorException("Error creating port forwarding rules", ex); + _logger.ErrorException("Error discovering NAT devices", ex); } - } - - private List _createdRules = new List(); - private void CreateRules(INatDevice device) - { - // On some systems the device discovered event seems to fire repeatedly - // This check will help ensure we're not trying to port map the same device over and over - - var address = device.LocalAddress.ToString(); - - if (!_createdRules.Contains(address)) + finally { - _createdRules.Add(address); - - CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + _currentCancellationTokenSource = null; } - } - private void CreatePortMap(INatDevice device, int privatePort, int publicPort) - { - _logger.Debug("Creating port map on port {0}", privatePort); - device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) + if (_config.Configuration.EnableUPnP) { - Description = _appHost.Name - }); + await Task.Delay(_interval).ConfigureAwait(false); + Discover(); + } } - // As I said before, this method will be never invoked. You can remove it. - void NatUtility_DeviceLost(object sender, DeviceEventArgs e) + private async Task CreateRules(NatDevice device) { - var device = e.Device; - _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); - } + // On some systems the device discovered event seems to fire repeatedly + // This check will help ensure we're not trying to port map the same device over and over - public void Dispose() - { - DisposeNat(); + await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); + await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); } - private void DisposeNat() + private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) { - _logger.Debug("Stopping NAT discovery"); - - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - - _ssdp.MessageReceived -= _ssdp_MessageReceived; + _logger.Debug("Creating port map on port {0}", privatePort); try { - // This is not a significant improvement - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= NatUtility_DeviceFound; - NatUtility.DeviceLost -= NatUtility_DeviceLost; - NatUtility.UnhandledException -= NatUtility_UnhandledException; + await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); } - // Statements in try-block will no fail because StopDiscovery is a one-line - // method that was no chances to fail. - // public static void StopDiscovery () - // { - // searching.Reset(); - // } - // IMO you could remove the catch-block catch (Exception ex) { - _logger.ErrorException("Error stopping NAT Discovery", ex); - } - finally - { - _isStarted = false; + _logger.ErrorException("Error creating port map", ex); } } - private class LogWriter : TextWriter + public void Dispose() { - private readonly ILogger _logger; - - public LogWriter(ILogger logger) - { - _logger = logger; - } - - public override Encoding Encoding - { - get { return Encoding.UTF8; } - } - - public override void WriteLine(string format, params object[] arg) - { - _logger.Debug(format, arg); - } + DisposeNat(); + } - public override void WriteLine(string value) + private void DisposeNat() + { + if (_currentCancellationTokenSource != null) { - _logger.Debug(value); + try + { + _currentCancellationTokenSource.Cancel(); + } + catch (Exception ex) + { + _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); + } } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 97f090ab2..84c1cae54 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,6 +62,10 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll + + ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll + True + ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 66aede029..814a67643 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,6 +7,7 @@ + \ No newline at end of file -- cgit v1.2.3 From e13fcb3cd42b67374621d7e02961e4bd335a235f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:22:07 -0400 Subject: update sat/ip --- .../EntryPoints/ExternalPortForwarding.cs | 18 ++- .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 170 +++++++++------------ .../MediaBrowser.Server.Implementations.csproj | 1 + 3 files changed, 83 insertions(+), 106 deletions(-) (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index c0c626438..a7e5396eb 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -31,20 +31,26 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; + + _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - public void Run() + private void _config_ConfigurationUpdated(object sender, EventArgs e) { - //NatUtility.Logger = new LogWriter(_logger); + } - if (_config.Configuration.EnableUPnP) - { - Discover(); - } + public void Run() + { + Discover(); } private async void Discover() { + if (!_config.Configuration.EnableUPnP) + { + return; + } + var discoverer = new NatDiscoverer(); var cancellationTokenSource = new CancellationTokenSource(10000); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index da1894bb7..413ce4549 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -15,6 +15,7 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Extensions; +using System.Xml.Linq; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { @@ -171,58 +172,87 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public async Task GetInfo(string url, CancellationToken cancellationToken) { + Uri locationUri = new Uri(url); + string devicetype = ""; + string friendlyname = ""; + string uniquedevicename = ""; + string manufacturer = ""; + string manufacturerurl = ""; + string modelname = ""; + string modeldescription = ""; + string modelnumber = ""; + string modelurl = ""; + string serialnumber = ""; + string presentationurl = ""; + string capabilities = ""; + string m3u = ""; + var document = XDocument.Load(locationUri.AbsoluteUri); + var xnm = new XmlNamespaceManager(new NameTable()); + XNamespace n1 = "urn:ses-com:satip"; + XNamespace n0 = "urn:schemas-upnp-org:device-1-0"; + xnm.AddNamespace("root", n0.NamespaceName); + xnm.AddNamespace("satip:", n1.NamespaceName); + if (document.Root != null) + { + var deviceElement = document.Root.Element(n0 + "device"); + if (deviceElement != null) + { + var devicetypeElement = deviceElement.Element(n0 + "deviceType"); + if (devicetypeElement != null) + devicetype = devicetypeElement.Value; + var friendlynameElement = deviceElement.Element(n0 + "friendlyName"); + if (friendlynameElement != null) + friendlyname = friendlynameElement.Value; + var manufactureElement = deviceElement.Element(n0 + "manufacturer"); + if (manufactureElement != null) + manufacturer = manufactureElement.Value; + var manufactureurlElement = deviceElement.Element(n0 + "manufacturerURL"); + if (manufactureurlElement != null) + manufacturerurl = manufactureurlElement.Value; + var modeldescriptionElement = deviceElement.Element(n0 + "modelDescription"); + if (modeldescriptionElement != null) + modeldescription = modeldescriptionElement.Value; + var modelnameElement = deviceElement.Element(n0 + "modelName"); + if (modelnameElement != null) + modelname = modelnameElement.Value; + var modelnumberElement = deviceElement.Element(n0 + "modelNumber"); + if (modelnumberElement != null) + modelnumber = modelnumberElement.Value; + var modelurlElement = deviceElement.Element(n0 + "modelURL"); + if (modelurlElement != null) + modelurl = modelurlElement.Value; + var serialnumberElement = deviceElement.Element(n0 + "serialNumber"); + if (serialnumberElement != null) + serialnumber = serialnumberElement.Value; + var uniquedevicenameElement = deviceElement.Element(n0 + "UDN"); + if (uniquedevicenameElement != null) uniquedevicename = uniquedevicenameElement.Value; + var presentationUrlElement = deviceElement.Element(n0 + "presentationURL"); + if (presentationUrlElement != null) presentationurl = presentationUrlElement.Value; + var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP"); + if (capabilitiesElement != null) capabilities = capabilitiesElement.Value; + var m3uElement = deviceElement.Element(n1 + "X_SATIPM3U"); + if (m3uElement != null) m3u = m3uElement.Value; + } + } + + var result = new SatIpTunerHostInfo { Url = url, + Id = uniquedevicename, IsEnabled = true, Type = SatIpHost.DeviceType, Tuners = 1, - TunersAvailable = 1 + TunersAvailable = 1, + M3UUrl = m3u }; - using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false)) - { - using (var streamReader = new StreamReader(stream)) - { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader)) - { - reader.MoveToContent(); - - // Loop through each element - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "device": - using (var subtree = reader.ReadSubtree()) - { - FillFromDeviceNode(result, subtree); - } - break; - default: - reader.Skip(); - break; - } - } - } - } - } - } - - if (string.IsNullOrWhiteSpace(result.DeviceId)) + result.FriendlyName = friendlyname; + if (string.IsNullOrWhiteSpace(result.Id)) { throw new NotImplementedException(); } - // Device hasn't implemented an m3u list - if (string.IsNullOrWhiteSpace(result.M3UUrl)) - { - result.IsEnabled = false; - } - else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); @@ -233,66 +263,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return result; } - - private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader) - { - reader.MoveToContent(); - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.LocalName) - { - case "UDN": - { - info.DeviceId = reader.ReadElementContentAsString(); - break; - } - - case "friendlyName": - { - info.FriendlyName = reader.ReadElementContentAsString(); - break; - } - - case "satip:X_SATIPCAP": - case "X_SATIPCAP": - { - // DVBS2-2 - var value = reader.ReadElementContentAsString() ?? string.Empty; - var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length == 2) - { - int intValue; - if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.TunersAvailable = intValue; - } - - if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.Tuners = intValue; - } - } - break; - } - - case "satip:X_SATIPM3U": - case "X_SATIPM3U": - { - // /channellist.lua?select=m3u - info.M3UUrl = reader.ReadElementContentAsString(); - break; - } - - default: - reader.Skip(); - break; - } - } - } - } } public class SatIpTunerHostInfo : TunerHostInfo diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 84c1cae54..14d275505 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -103,6 +103,7 @@ ..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll + ..\ThirdParty\UniversalDetector\UniversalDetector.dll -- cgit v1.2.3 From 132766ff15cd2511ca09be0f2b878ebf5ceb5632 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 00:16:18 -0400 Subject: update ffmpeg --- .../Security/MbAdmin.cs | 4 +- .../Security/PluginSecurityManager.cs | 2 +- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 47 +++++++++++++++------- .../EntryPoints/UsageReporter.cs | 2 +- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFMpegDownloadInfo.cs | 16 +++----- .../FFMpeg/FFMpegDownloader.cs | 47 +++++++++++++++------- .../MediaBrowser.ServerApplication.csproj | 2 + .../ffmpeg/ffmpegx64.7z.REMOVED.git-id | 1 + .../ffmpeg/ffmpegx86.7z.REMOVED.git-id | 1 + 10 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs index ab4a83257..76ff92c2e 100644 --- a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs +++ b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs @@ -3,11 +3,11 @@ namespace MediaBrowser.Common.Implementations.Security { public class MbAdmin { - public const string HttpUrl = "http://www.mb3admin.com/admin/"; + public const string HttpUrl = "https://www.mb3admin.com/admin/"; /// /// Leaving as http for now until we get it squared away /// - public const string HttpsUrl = "http://www.mb3admin.com/admin/"; + public const string HttpsUrl = "https://www.mb3admin.com/admin/"; } } diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index af58c3731..4e01041bc 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Common.Implementations.Security public class PluginSecurityManager : ISecurityManager { private const string MBValidateUrl = MbAdmin.HttpsUrl + "service/registration/validate"; - private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "http://mb3admin.com/admin/service/appstore/register"; + private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.com/admin/service/appstore/register"; /// /// The _is MB supporter diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 2d1ec1273..3cdeb1afd 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Dlna.Ssdp private Timer _notificationTimer; private bool _isDisposed; - private readonly ConcurrentDictionary> _devices = new ConcurrentDictionary>(); + private readonly Dictionary> _devices = new Dictionary>(); private readonly IApplicationHost _appHost; @@ -172,9 +172,12 @@ namespace MediaBrowser.Dlna.Ssdp { get { - var devices = _devices.ToList(); + lock (_devices) + { + var devices = _devices.ToList(); - return devices.SelectMany(i => i.Value).ToList(); + return devices.SelectMany(i => i.Value).ToList(); + } } } @@ -482,26 +485,42 @@ namespace MediaBrowser.Dlna.Ssdp public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable services) { - var list = _devices.GetOrAdd(uuid, new List()); + lock (_devices) + { + List list; + List dl; + if (_devices.TryGetValue(uuid, out dl)) + { + list = dl; + } + else + { + list = new List(); + _devices[uuid] = list; + } - list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); + list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); - NotifyAll(); - _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + NotifyAll(); + _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + } } public void UnregisterNotification(string uuid) { - List dl; - if (_devices.TryRemove(uuid, out dl)) + lock (_devices) { - - foreach (var d in dl.ToList()) + List dl; + if (_devices.TryGetValue(uuid, out dl)) { - NotifyDevice(d, "byebye", true); - } + _devices.Remove(uuid); + foreach (var d in dl.ToList()) + { + NotifyDevice(d, "byebye", true); + } - _logger.Debug("Unregistered mount {0}", uuid); + _logger.Debug("Unregistered mount {0}", uuid); + } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs index 7e22efb23..7b3a7a30d 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly IHttpClient _httpClient; private readonly IUserManager _userManager; private readonly ILogger _logger; - private const string MbAdminUrl = "http://www.mb3admin.com/admin/"; + private const string MbAdminUrl = "https://www.mb3admin.com/admin/"; public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger) { diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index dd7e3cc01..b5988b18a 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -618,7 +618,7 @@ namespace MediaBrowser.Server.Startup.Common /// Task. private async Task RegisterMediaEncoder(IProgress progress) { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment) + var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 60cb50e30..4979ff82b 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg public string FFProbeFilename { get; set; } public string ArchiveType { get; set; } public string[] DownloadUrls { get; set; } + public bool IsEmbedded { get; set; } public FFMpegDownloadInfo() { @@ -54,8 +55,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20160131"; + info.Version = "20160401"; info.ArchiveType = "7z"; + info.IsEmbedded = true; switch (environment.SystemArchitecture) { @@ -81,17 +83,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win64.7z", - "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20151109-git-480bad7-win64-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" }; case Architecture.X86: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win32.7z", - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20151109-git-480bad7-win32-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" }; } break; diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs index 000568c15..c538b81a4 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -23,13 +24,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private readonly IZipClient _zipClient; private readonly IFileSystem _fileSystem; private readonly NativeEnvironment _environment; + private Assembly _ownerAssembly; private readonly string[] _fontUrls = { "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z" }; - public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment) + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment, Assembly ownerAssembly) { _logger = logger; _appPaths = appPaths; @@ -37,6 +39,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg _zipClient = zipClient; _fileSystem = fileSystem; _environment = environment; + _ownerAssembly = ownerAssembly; } public async Task GetFFMpegInfo(NativeEnvironment environment, StartupOptions options, IProgress progress) @@ -78,11 +81,11 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg Version = version }; - _fileSystem.CreateDirectory(versionedDirectoryPath); + _fileSystem.CreateDirectory(versionedDirectoryPath); var excludeFromDeletions = new List { versionedDirectoryPath }; - if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) + if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) { // ffmpeg not present. See if there's an older version we can start with var existingVersion = GetExistingVersion(info, rootEncoderPath); @@ -106,7 +109,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + if (_environment.OperatingSystem == OperatingSystem.Windows) + { + await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + } DeleteOlderFolders(Path.GetDirectoryName(versionedDirectoryPath), excludeFromDeletions); @@ -189,6 +195,21 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private async Task DownloadFFMpeg(FFMpegDownloadInfo downloadinfo, string directory, IProgress progress) { + if (downloadinfo.IsEmbedded) + { + var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(Path.GetDirectoryName(tempFile)); + + using (var stream = _ownerAssembly.GetManifestResourceStream(downloadinfo.DownloadUrls[0])) + { + using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(fs).ConfigureAwait(false); + } + } + ExtractFFMpeg(downloadinfo, tempFile, directory); + } + foreach (var url in downloadinfo.DownloadUrls) { progress.Report(0); @@ -216,10 +237,8 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { throw new ApplicationException("ffmpeg unvailable. Please install it and start the server with two command line arguments: -ffmpeg \"{PATH}\" and -ffprobe \"{PATH}\""); } - else - { - throw new ApplicationException("Unable to download required components. Please try again later."); - } + + throw new ApplicationException("Unable to download required components. Please try again later."); } private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder) @@ -228,7 +247,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); + _fileSystem.CreateDirectory(tempFolder); try { @@ -247,7 +266,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg })) { var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); - _fileSystem.CopyFile(file, targetFile, true); + _fileSystem.CopyFile(file, targetFile, true); SetFilePermissions(targetFile); } } @@ -311,13 +330,13 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { var fontsDirectory = Path.Combine(targetPath, "fonts"); - _fileSystem.CreateDirectory(fontsDirectory); + _fileSystem.CreateDirectory(fontsDirectory); const string fontFilename = "ARIALUNI.TTF"; var fontFile = Path.Combine(fontsDirectory, fontFilename); - if (_fileSystem.FileExists(fontFile)) + if (_fileSystem.FileExists(fontFile)) { await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); } @@ -360,7 +379,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { try { - _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); + _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); return; } catch (IOException ex) @@ -422,7 +441,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg const string fontConfigFilename = "fonts.conf"; var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); - if (!_fileSystem.FileExists(fontConfigFile)) + if (!_fileSystem.FileExists(fontConfigFile)) { var contents = string.Format("{0}ArialArial Unicode MS", fontsDirectory); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 6ba91c06f..d1bf58dda 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -144,6 +144,8 @@ + + diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id new file mode 100644 index 000000000..b0542b75f --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id @@ -0,0 +1 @@ +9dc10b022537738edce7eb71aa8dd4adbfee2c7b \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id new file mode 100644 index 000000000..3939ec44d --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id @@ -0,0 +1 @@ +00fa1afa35fbd0a7e97ad7956e42ae17f6882f64 \ No newline at end of file -- cgit v1.2.3 From 4afc2c9156a266a980d06b6657a74f0f4ad47a65 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 14:23:17 -0400 Subject: set notification info url --- MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs | 3 ++- MediaBrowser.Model/Updates/PackageVersionInfo.cs | 2 ++ .../EntryPoints/Notifications/Notifications.cs | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs index 82ebf92b2..2ffaedc4b 100644 --- a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs +++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs @@ -111,7 +111,8 @@ namespace MediaBrowser.Common.Implementations.Updates targetFilename = targetFilename, versionStr = version.ToString(), requiredVersionStr = "1.0.0", - description = obj.body + description = obj.body, + infoUrl = obj.html_url } }; } diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index b9bf6e7fe..22404b6f6 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -87,5 +87,7 @@ namespace MediaBrowser.Model.Updates /// /// The target filename. public string targetFilename { get; set; } + + public string infoUrl { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 918110226..9e68ce4ef 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -116,7 +116,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications var notification = new NotificationRequest { - NotificationType = type + NotificationType = type, + Url = e.Argument.infoUrl }; notification.Variables["Version"] = e.Argument.versionStr; -- cgit v1.2.3 From ddbf183df59b43e5b9f47c81e923b2669b4e26cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 15:07:43 -0400 Subject: update edge playback --- .../EntryPoints/ExternalPortForwarding.cs | 202 +++++++++++++++------ .../MediaBrowser.Server.Implementations.csproj | 4 - .../packages.config | 1 - 3 files changed, 151 insertions(+), 56 deletions(-) (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index a7e5396eb..5777a0af7 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; +using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -10,9 +11,6 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; -using Open.Nat; -using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -22,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - private CancellationTokenSource _currentCancellationTokenSource; - private TimeSpan _interval = TimeSpan.FromHours(1); + + private PeriodicTimer _timer; + private bool _isStarted; public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -31,78 +30,157 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; + } - _config.ConfigurationUpdated += _config_ConfigurationUpdated; + private string _lastConfigIdentifier; + private string GetConfigIdentifier() + { + var values = new List(); + var config = _config.Configuration; + + values.Add(config.EnableUPnP.ToString()); + values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); + values.Add(config.EnableHttps.ToString()); + values.Add(_appHost.EnableHttps.ToString()); + + return string.Join("|", values.ToArray()); } - private void _config_ConfigurationUpdated(object sender, EventArgs e) + void _config_ConfigurationUpdated(object sender, EventArgs e) { + if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) + { + if (_isStarted) + { + DisposeNat(); + } + + Run(); + } } public void Run() { - Discover(); + //NatUtility.Logger = new LogWriter(_logger); + + if (_config.Configuration.EnableUPnP) + { + Start(); + } + + _config.ConfigurationUpdated -= _config_ConfigurationUpdated; + _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private async void Discover() + private void Start() { - if (!_config.Configuration.EnableUPnP) + _logger.Debug("Starting NAT discovery"); + NatUtility.EnabledProtocols = new List { - return; - } + NatProtocol.Pmp + }; + NatUtility.DeviceFound += NatUtility_DeviceFound; - var discoverer = new NatDiscoverer(); + // Mono.Nat does never rise this event. The event is there however it is useless. + // You could remove it with no risk. + NatUtility.DeviceLost += NatUtility_DeviceLost; - var cancellationTokenSource = new CancellationTokenSource(10000); - _currentCancellationTokenSource = cancellationTokenSource; - try - { - var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); + // it is hard to say what one should do when an unhandled exception is raised + // because there isn't anything one can do about it. Probably save a log or ignored it. + NatUtility.UnhandledException += NatUtility_UnhandledException; + NatUtility.StartDiscovery(); - await CreateRules(device).ConfigureAwait(false); - } - catch (OperationCanceledException) - { + _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + + _ssdp.MessageReceived += _ssdp_MessageReceived; + + _lastConfigIdentifier = GetConfigIdentifier(); + + _isStarted = true; + } + + void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) + { + var endpoint = e.EndPoint as IPEndPoint; + if (endpoint != null && e.LocalEndPoint != null) + { + NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); } - catch (Exception ex) + } + + void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var ex = e.ExceptionObject as Exception; + + if (ex == null) { - _logger.ErrorException("Error discovering NAT devices", ex); + //_logger.Error("Unidentified error reported by Mono.Nat"); } - finally + else { - _currentCancellationTokenSource = null; + // Seeing some blank exceptions coming through here + //_logger.ErrorException("Error reported by Mono.Nat: ", ex); } + } - if (_config.Configuration.EnableUPnP) + void NatUtility_DeviceFound(object sender, DeviceEventArgs e) + { + try { - await Task.Delay(_interval).ConfigureAwait(false); - Discover(); + var device = e.Device; + _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); + + CreateRules(device); + } + catch (Exception ex) + { + // I think it could be a good idea to log the exception because + // you are using permanent portmapping here (never expire) and that means that next time + // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends + // on the router's upnp implementation (specs says it should fail however some routers don't do it) + // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable + // and those errors (upnp errors) could be useful for diagnosting. + + // Commenting out because users are reporting problems out of our control + //_logger.ErrorException("Error creating port forwarding rules", ex); } } - private async Task CreateRules(NatDevice device) + private List _createdRules = new List(); + private void CreateRules(INatDevice device) { // On some systems the device discovered event seems to fire repeatedly // This check will help ensure we're not trying to port map the same device over and over - await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); - await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); + var address = device.LocalAddress.ToString(); + + if (!_createdRules.Contains(address)) + { + _createdRules.Add(address); + + CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); + CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + } } - private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) + private void CreatePortMap(INatDevice device, int privatePort, int publicPort) { _logger.Debug("Creating port map on port {0}", privatePort); - - try + device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) { - await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating port map", ex); - } + Description = _appHost.Name + }); + } + + // As I said before, this method will be never invoked. You can remove it. + void NatUtility_DeviceLost(object sender, DeviceEventArgs e) + { + var device = e.Device; + _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); } public void Dispose() @@ -112,17 +190,39 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void DisposeNat() { - if (_currentCancellationTokenSource != null) + _logger.Debug("Stopping NAT discovery"); + + if (_timer != null) { - try - { - _currentCancellationTokenSource.Cancel(); - } - catch (Exception ex) - { - _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); - } + _timer.Dispose(); + _timer = null; + } + + _ssdp.MessageReceived -= _ssdp_MessageReceived; + + try + { + // This is not a significant improvement + NatUtility.StopDiscovery(); + NatUtility.DeviceFound -= NatUtility_DeviceFound; + NatUtility.DeviceLost -= NatUtility_DeviceLost; + NatUtility.UnhandledException -= NatUtility_UnhandledException; + } + // Statements in try-block will no fail because StopDiscovery is a one-line + // method that was no chances to fail. + // public static void StopDiscovery () + // { + // searching.Reset(); + // } + // IMO you could remove the catch-block + catch (Exception ex) + { + _logger.ErrorException("Error stopping NAT Discovery", ex); + } + finally + { + _isStarted = false; } } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index ae39d3eb9..60d8f737f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,10 +62,6 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll - - ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll - True - ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 814a67643..66aede029 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,7 +7,6 @@ - \ No newline at end of file -- cgit v1.2.3