From 5759ba86564d6e2a6529b8800e37ad916ac690fa Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 24 Jun 2017 14:30:15 -0400 Subject: [PATCH] fix network methods not shutting down --- Mono.Nat/NatUtility.cs | 189 +++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 82 deletions(-) diff --git a/Mono.Nat/NatUtility.cs b/Mono.Nat/NatUtility.cs index bcbe5d8d0e..983e868336 100644 --- a/Mono.Nat/NatUtility.cs +++ b/Mono.Nat/NatUtility.cs @@ -41,26 +41,25 @@ using MediaBrowser.Model.Logging; namespace Mono.Nat { - public static class NatUtility - { - private static ManualResetEvent searching; - public static event EventHandler DeviceFound; - public static event EventHandler DeviceLost; - - private static List controllers; - private static bool verbose; + public static class NatUtility + { + public static event EventHandler DeviceFound; + public static event EventHandler DeviceLost; + + private static List controllers; + private static bool verbose; public static List EnabledProtocols { get; set; } - public static ILogger Logger { get; set; } + public static ILogger Logger { get; set; } public static IHttpClient HttpClient { get; set; } public static bool Verbose - { - get { return verbose; } - set { verbose = value; } - } - + { + get { return verbose; } + set { verbose = value; } + } + static NatUtility() { EnabledProtocols = new List @@ -68,8 +67,6 @@ namespace Mono.Nat NatProtocol.Pmp }; - searching = new ManualResetEvent(false); - controllers = new List(); controllers.Add(PmpSearcher.Instance); @@ -86,23 +83,19 @@ namespace Mono.Nat DeviceLost(sender, args); }; }); - - Task.Factory.StartNew(SearchAndListen, TaskCreationOptions.LongRunning); } - internal static void Log(string format, params object[] args) - { - var logger = Logger; - if (logger != null) - logger.Debug(format, args); - } + internal static void Log(string format, params object[] args) + { + var logger = Logger; + if (logger != null) + logger.Debug(format, args); + } - private static async Task SearchAndListen() + private static async Task SearchAndListen(CancellationToken cancellationToken) { - while (true) + while (!cancellationToken.IsCancellationRequested) { - searching.WaitOne(); - try { var enabledProtocols = EnabledProtocols.ToList(); @@ -123,67 +116,99 @@ namespace Mono.Nat } catch (Exception e) { - + } await Task.Delay(100).ConfigureAwait(false); } - } - - static async Task Receive (ISearcher searcher, List clients) - { - foreach (UdpClient client in clients) - { - if (client.Available > 0) - { - IPAddress localAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address; - var result = await client.ReceiveAsync().ConfigureAwait(false); - var data = result.Buffer; - var received = result.RemoteEndPoint; - searcher.Handle(localAddress, data, received); - } + } + + static async Task Receive(ISearcher searcher, List clients) + { + foreach (UdpClient client in clients) + { + if (client.Available > 0) + { + IPAddress localAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address; + var result = await client.ReceiveAsync().ConfigureAwait(false); + var data = result.Buffer; + var received = result.RemoteEndPoint; + searcher.Handle(localAddress, data, received); + } + } + } + + private static CancellationTokenSource _currentCancellationTokenSource; + private static object _runSyncLock = new object(); + public static void StartDiscovery() + { + lock (_runSyncLock) + { + if (_currentCancellationTokenSource == null) + { + return; + } + + var tokenSource = new CancellationTokenSource(); + + _currentCancellationTokenSource = tokenSource; + //Task.Factory.StartNew(() => SearchAndListen(tokenSource.Token), tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); } } - - public static void StartDiscovery () - { - searching.Set(); - } - - public static void StopDiscovery () - { - searching.Reset(); - } - - //checks if an IP address is a private address space as defined by RFC 1918 - public static bool IsPrivateAddressSpace (IPAddress address) - { - byte[] ba = address.GetAddressBytes (); - - switch ((int)ba[0]) { - case 10: - return true; //10.x.x.x - case 172: - return ((int)ba[1] & 16) != 0; //172.16-31.x.x - case 192: - return (int)ba[1] == 168; //192.168.x.x - default: - return false; - } - } - - public static void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint, NatProtocol protocol) - { - switch (protocol) - { + + public static void StopDiscovery() + { + lock (_runSyncLock) + { + var tokenSource = _currentCancellationTokenSource; + + if (tokenSource != null) + { + try + { + tokenSource.Cancel(); + tokenSource.Dispose(); + } + catch + { + + } + + _currentCancellationTokenSource = null; + } + } + } + + //checks if an IP address is a private address space as defined by RFC 1918 + public static bool IsPrivateAddressSpace(IPAddress address) + { + byte[] ba = address.GetAddressBytes(); + + switch ((int)ba[0]) + { + case 10: + return true; //10.x.x.x + case 172: + return ((int)ba[1] & 16) != 0; //172.16-31.x.x + case 192: + return (int)ba[1] == 168; //192.168.x.x + default: + return false; + } + } + + public static void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint, NatProtocol protocol) + { + switch (protocol) + { case NatProtocol.Upnp: - //UpnpSearcher.Instance.Handle(localAddress, response, endpoint); - break; + //UpnpSearcher.Instance.Handle(localAddress, response, endpoint); + break; case NatProtocol.Pmp: - PmpSearcher.Instance.Handle(localAddress, response, endpoint); - break; - default: - throw new ArgumentException("Unexpected protocol: " + protocol); - } + PmpSearcher.Instance.Handle(localAddress, response, endpoint); + break; + default: + throw new ArgumentException("Unexpected protocol: " + protocol); + } } public static void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol)