diff options
Diffstat (limited to 'Mono.Nat/Upnp/Searchers/UpnpSearcher.cs')
| -rw-r--r-- | Mono.Nat/Upnp/Searchers/UpnpSearcher.cs | 193 |
1 files changed, 8 insertions, 185 deletions
diff --git a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs index edc5a5d76..3d9df012a 100644 --- a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs +++ b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs @@ -37,96 +37,27 @@ using System.Diagnostics; using System.Net.Sockets; using System.Net.NetworkInformation; using MediaBrowser.Controller.Dlna; +using MediaBrowser.Model.Logging; namespace Mono.Nat { internal class UpnpSearcher : ISearcher { - private const int SearchPeriod = 5 * 60; // The time in seconds between each search - static UpnpSearcher instance = new UpnpSearcher(); - public static List<UdpClient> sockets = CreateSockets(); - - public static UpnpSearcher Instance - { - get { return instance; } - } - public event EventHandler<DeviceEventArgs> DeviceFound; public event EventHandler<DeviceEventArgs> DeviceLost; - private List<INatDevice> devices; - private Dictionary<IPAddress, DateTime> lastFetched; private DateTime nextSearch; - private IPEndPoint searchEndpoint; + private readonly ILogger _logger; - UpnpSearcher() + public UpnpSearcher(ILogger logger) { - devices = new List<INatDevice>(); - lastFetched = new Dictionary<IPAddress, DateTime>(); - //searchEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900); - searchEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900); + _logger = logger; } - static List<UdpClient> CreateSockets() - { - List<UdpClient> clients = new List<UdpClient>(); - try - { - foreach (NetworkInterface n in NetworkInterface.GetAllNetworkInterfaces()) - { - foreach (UnicastIPAddressInformation address in n.GetIPProperties().UnicastAddresses) - { - if (address.Address.AddressFamily == AddressFamily.InterNetwork) - { - try - { - clients.Add(new UdpClient(new IPEndPoint(address.Address, 0))); - } - catch - { - continue; // Move on to the next address. - } - } - } - } - } - catch (Exception) - { - clients.Add(new UdpClient(0)); - } - return clients; - } - public void Search() { - foreach (UdpClient s in sockets) - { - try - { - Search(s); - } - catch - { - // Ignore any search errors - } - } } - void Search(UdpClient client) - { - nextSearch = DateTime.Now.AddSeconds(SearchPeriod); - byte[] data = DiscoverDeviceMessage.EncodeSSDP(); - - // UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2) - for (int i = 0; i < 3; i++) - client.Send(data, data.Length, searchEndpoint); - } - - public IPEndPoint SearchEndpoint - { - get { return searchEndpoint; } - } - public void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint) { // No matter what, this method should never throw an exception. If something goes wrong @@ -145,113 +76,19 @@ namespace Mono.Nat prefix. */ // We have an internet gateway device now - UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty); + UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger); - if (devices.Contains(d)) - { - // We already have found this device, so we just refresh it to let people know it's - // Still alive. If a device doesn't respond to a search, we dump it. - devices[devices.IndexOf(d)].LastSeen = DateTime.Now; - } - else - { - - // If we send 3 requests at a time, ensure we only fetch the services list once - // even if three responses are received - if (lastFetched.ContainsKey(endpoint.Address)) - { - DateTime last = lastFetched[endpoint.Address]; - if ((DateTime.Now - last) < TimeSpan.FromSeconds(20)) - return; - } - lastFetched[endpoint.Address] = DateTime.Now; - - // Once we've parsed the information we need, we tell the device to retrieve it's service list - // Once we successfully receive the service list, the callback provided will be invoked. - NatUtility.Log("Fetching service list: {0}", d.HostEndPoint); - d.GetServicesList(DeviceSetupComplete); - } + NatUtility.Log("Fetching service list: {0}", d.HostEndPoint); + OnDeviceFound(new DeviceEventArgs(d)); } catch (Exception ex) { - NatUtility.Log("Unhandled exception when trying to decode a device's response Send me the following data: "); - NatUtility.Log("ErrorMessage:"); - NatUtility.Log(ex.Message); + _logger.ErrorException("Error decoding device response", ex); } } public void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint) { - // Convert it to a string for easy parsing - string dataString = null; - - // No matter what, this method should never throw an exception. If something goes wrong - // we should still be in a position to handle the next reply correctly. - try { - string urn; - dataString = Encoding.UTF8.GetString(response); - - if (NatUtility.Verbose) - NatUtility.Log("UPnP Response: {0}", dataString); - - /* For UPnP Port Mapping we need ot find either WANPPPConnection or WANIPConnection. - Any other device type is no good to us for this purpose. See the IGP overview paper - page 5 for an overview of device types and their hierarchy. - http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf */ - - /* TODO: Currently we are assuming version 1 of the protocol. We should figure out which - version it is and apply the correct URN. */ - - /* Some routers don't correctly implement the version ID on the URN, so we only search for the type - prefix. */ - - string log = "UPnP Response: Router advertised a '{0}' service"; - StringComparison c = StringComparison.OrdinalIgnoreCase; - if (dataString.IndexOf("urn:schemas-upnp-org:service:WANIPConnection:", c) != -1) { - urn = "urn:schemas-upnp-org:service:WANIPConnection:1"; - NatUtility.Log(log, "urn:schemas-upnp-org:service:WANIPConnection:1"); - } else if (dataString.IndexOf("urn:schemas-upnp-org:service:WANPPPConnection:", c) != -1) { - urn = "urn:schemas-upnp-org:service:WANPPPConnection:1"; - NatUtility.Log(log, "urn:schemas-upnp-org:service:WANPPPConnection:"); - } else - return; - - // We have an internet gateway device now - UpnpNatDevice d = new UpnpNatDevice(localAddress, dataString, urn); - - if (devices.Contains(d)) - { - // We already have found this device, so we just refresh it to let people know it's - // Still alive. If a device doesn't respond to a search, we dump it. - devices[devices.IndexOf(d)].LastSeen = DateTime.Now; - } - else - { - - // If we send 3 requests at a time, ensure we only fetch the services list once - // even if three responses are received - if (lastFetched.ContainsKey(endpoint.Address)) - { - DateTime last = lastFetched[endpoint.Address]; - if ((DateTime.Now - last) < TimeSpan.FromSeconds(20)) - return; - } - lastFetched[endpoint.Address] = DateTime.Now; - - // Once we've parsed the information we need, we tell the device to retrieve it's service list - // Once we successfully receive the service list, the callback provided will be invoked. - NatUtility.Log("Fetching service list: {0}", d.HostEndPoint); - d.GetServicesList(DeviceSetupComplete); - } - } - catch (Exception ex) - { - Trace.WriteLine("Unhandled exception when trying to decode a device's response Send me the following data: "); - Trace.WriteLine("ErrorMessage:"); - Trace.WriteLine(ex.Message); - Trace.WriteLine("Data string:"); - Trace.WriteLine(dataString); - } } public DateTime NextSearch @@ -259,20 +96,6 @@ namespace Mono.Nat get { return nextSearch; } } - private void DeviceSetupComplete(INatDevice device) - { - lock (this.devices) - { - // We don't want the same device in there twice - if (devices.Contains(device)) - return; - - devices.Add(device); - } - - OnDeviceFound(new DeviceEventArgs(device)); - } - private void OnDeviceFound(DeviceEventArgs args) { if (DeviceFound != null) |
