소스 검색

lighten up nat project

Luke Pulverenti 8 년 전
부모
커밋
8e57296f69

+ 0 - 19
Mono.Nat/Exceptions/MappingException.cs

@@ -25,11 +25,9 @@
 //
 
 using System;
-using System.Security.Permissions;
 
 namespace Mono.Nat
 {
-	[Serializable]
 	public class MappingException : Exception
 	{
 		private int errorCode;
@@ -45,7 +43,6 @@ namespace Mono.Nat
 			get { return this.errorText; }
 		}
 
-		#region Constructors
 		public MappingException()
 			: base()
 		{
@@ -67,21 +64,5 @@ namespace Mono.Nat
 			: base(message, innerException)
 		{
 		}
-
-		protected MappingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
-			: base(info, context)
-		{
-		}
-		#endregion
-
-		[SecurityPermission(SecurityAction.Demand, SerializationFormatter=true)]
-		public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
-		{
-			if(info==null) throw new ArgumentNullException("info");
-
-			this.errorCode = info.GetInt32("errorCode");
-			this.errorText = info.GetString("errorText");
-			base.GetObjectData(info, context);
-		}
 	}
 }

+ 3 - 40
Mono.Nat/NatUtility.cs

@@ -66,14 +66,12 @@ namespace Mono.Nat
         {
             EnabledProtocols = new List<NatProtocol>
             {
-                NatProtocol.Upnp,
                 NatProtocol.Pmp
             };
 
             searching = new ManualResetEvent(false);
 
             controllers = new List<ISearcher>();
-            controllers.Add(UpnpSearcher.Instance);
             controllers.Add(PmpSearcher.Instance);
 
             controllers.ForEach(searcher =>
@@ -111,10 +109,6 @@ namespace Mono.Nat
                 {
                     var enabledProtocols = EnabledProtocols.ToList();
 
-                    if (enabledProtocols.Contains(UpnpSearcher.Instance.Protocol))
-                    {
-                        Receive(UpnpSearcher.Instance, UpnpSearcher.sockets);
-                    }
                     if (enabledProtocols.Contains(PmpSearcher.Instance.Protocol))
                     {
                         Receive(PmpSearcher.Instance, PmpSearcher.sockets);
@@ -149,20 +143,6 @@ namespace Mono.Nat
 				}
             }
         }
-
-        static void Receive(IMapper mapper, List<UdpClient> clients)
-        {
-            IPEndPoint received = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 5351);
-            foreach (UdpClient client in clients)
-            {
-                if (client.Available > 0)
-                {
-                    IPAddress localAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address;
-                    byte[] data = client.Receive(ref received);
-                    mapper.Handle(localAddress, data);
-                }
-            }
-        }
 		
 		public static void StartDiscovery ()
 		{
@@ -184,7 +164,7 @@ namespace Mono.Nat
                     mapper = new PmpMapper();
                     break;
                 case MapperType.Upnp:
-                    mapper = new UpnpMapper();
+                    mapper = new UpnpMapper(Logger);
                     mapper.DeviceFound += (sender, args) =>
                     {
                         if (DeviceFound != null)
@@ -199,23 +179,6 @@ namespace Mono.Nat
             searching.Reset();
             
         }
-
-        //So then why is it here? -Nick
-		[Obsolete ("This method serves no purpose and shouldn't be used")]
-		public static IPAddress[] GetLocalAddresses (bool includeIPv6)
-		{
-			List<IPAddress> addresses = new List<IPAddress> ();
-
-			IPHostEntry hostInfo = Dns.GetHostEntry (Dns.GetHostName ());
-			foreach (IPAddress address in hostInfo.AddressList) {
-				if (address.AddressFamily == AddressFamily.InterNetwork ||
-					(includeIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6)) {
-					addresses.Add (address);
-				}
-			}
-			
-			return addresses.ToArray ();
-		}
 		
 		//checks if an IP address is a private address space as defined by RFC 1918
 		public static bool IsPrivateAddressSpace (IPAddress address)
@@ -239,7 +202,7 @@ namespace Mono.Nat
 	        switch (protocol)
 	        {
                 case NatProtocol.Upnp:
-	                UpnpSearcher.Instance.Handle(localAddress, response, endpoint);
+	                //UpnpSearcher.Instance.Handle(localAddress, response, endpoint);
 	                break;
                 case NatProtocol.Pmp:
 	                PmpSearcher.Instance.Handle(localAddress, response, endpoint);
@@ -254,7 +217,7 @@ namespace Mono.Nat
             switch (protocol)
             {
                 case NatProtocol.Upnp:
-                    UpnpSearcher.Instance.Handle(localAddress, deviceInfo, endpoint);
+                    new UpnpSearcher(Logger).Handle(localAddress, deviceInfo, endpoint);
                     break;
                 default:
                     throw new ArgumentException("Unexpected protocol: " + protocol);

+ 4 - 6
Mono.Nat/Upnp/Mappers/UpnpMapper.cs

@@ -32,6 +32,7 @@ using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading;
+using MediaBrowser.Model.Logging;
 
 namespace Mono.Nat.Upnp.Mappers
 {
@@ -42,7 +43,8 @@ namespace Mono.Nat.Upnp.Mappers
 
         public UdpClient Client { get; set; }
 
-        public UpnpMapper()
+        public UpnpMapper(ILogger logger)
+            : base(logger)
         {
             //Bind to local port 1900 for ssdp responses
             Client = new UdpClient(1900);
@@ -88,11 +90,7 @@ namespace Mono.Nat.Upnp.Mappers
             }
             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(Encoding.UTF8.GetString(response));
+                Logger.ErrorException("Error mapping port. Data string: {0}", ex, Encoding.UTF8.GetString(response));
             }
         }
 

+ 6 - 3
Mono.Nat/Upnp/Messages/GetServicesMessage.cs

@@ -27,6 +27,7 @@
 using System;
 using System.Diagnostics;
 using System.Net;
+using MediaBrowser.Model.Logging;
 
 namespace Mono.Nat.Upnp
 {
@@ -34,18 +35,20 @@ namespace Mono.Nat.Upnp
     {
         private string servicesDescriptionUrl;
         private EndPoint hostAddress;
+        private readonly ILogger _logger;
 
-        public GetServicesMessage(string description, EndPoint hostAddress)
+        public GetServicesMessage(string description, EndPoint hostAddress, ILogger logger)
             :base(null)
         {
             if (string.IsNullOrEmpty(description))
-                Trace.WriteLine("Description is null");
+                _logger.Warn("Description is null");
 
             if (hostAddress == null)
-                Trace.WriteLine("hostaddress is null");
+                _logger.Warn("hostaddress is null");
 
             this.servicesDescriptionUrl = description;
             this.hostAddress = hostAddress;
+            _logger = logger;
         }
 
 

+ 8 - 185
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)

+ 9 - 1
Mono.Nat/Upnp/Upnp.cs

@@ -33,11 +33,19 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Text;
+using MediaBrowser.Model.Logging;
 
 namespace Mono.Nat.Upnp
 {
     internal class Upnp
     {
+        protected readonly ILogger Logger;
+
+        public Upnp(ILogger logger)
+        {
+            Logger = logger;
+        }
+
         public UpnpNatDevice Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
         {
             // Convert it to a string for easy parsing
@@ -77,7 +85,7 @@ namespace Mono.Nat.Upnp
                 throw new NotSupportedException("Received non-supported device type");
 
             // We have an internet gateway device now
-            return new UpnpNatDevice(localAddress, dataString, urn);
+            return new UpnpNatDevice(localAddress, dataString, urn, Logger);
         }
     }
 }

+ 11 - 8
Mono.Nat/Upnp/UpnpNatDevice.cs

@@ -33,6 +33,7 @@ using System.Xml;
 using System.Text;
 using System.Diagnostics;
 using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Model.Logging;
 
 namespace Mono.Nat.Upnp
 {
@@ -43,8 +44,9 @@ namespace Mono.Nat.Upnp
 		private string serviceDescriptionUrl;
 		private string controlUrl;
 		private string serviceType;
+        private readonly ILogger _logger;
 
-		public override IPAddress LocalAddress
+        public override IPAddress LocalAddress
 		{
 			get { return localAddress; }
 		}
@@ -54,7 +56,7 @@ namespace Mono.Nat.Upnp
 		/// </summary>
 		private NatDeviceCallback callback;
 
-        internal UpnpNatDevice(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint hostEndPoint, string serviceType)
+        internal UpnpNatDevice(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint hostEndPoint, string serviceType, ILogger logger)
         {
             this.LastSeen = DateTime.Now;
             this.localAddress = localAddress;
@@ -62,6 +64,7 @@ namespace Mono.Nat.Upnp
             // Split the string at the "location" section so i can extract the ipaddress and service description url
             string locationDetails = deviceInfo.Location.ToString();
             this.serviceType = serviceType;
+            _logger = logger;
 
             // Make sure we have no excess whitespace
             locationDetails = locationDetails.Trim();
@@ -88,16 +91,17 @@ namespace Mono.Nat.Upnp
             }
         }
 
-        internal UpnpNatDevice (IPAddress localAddress, string deviceDetails, string serviceType)
+        internal UpnpNatDevice (IPAddress localAddress, string deviceDetails, string serviceType, ILogger logger)
 		{
-			this.LastSeen = DateTime.Now;
+            _logger = logger;
+            this.LastSeen = DateTime.Now;
 			this.localAddress = localAddress;
 
 			// Split the string at the "location" section so i can extract the ipaddress and service description url
 			string locationDetails = deviceDetails.Substring(deviceDetails.IndexOf("Location", StringComparison.InvariantCultureIgnoreCase) + 9).Split('\r')[0];
             this.serviceType = serviceType;
 
-			// Make sure we have no excess whitespace
+            // Make sure we have no excess whitespace
 			locationDetails = locationDetails.Trim();
 
 			// FIXME: Is this reliable enough. What if we get a hostname as opposed to a proper http address
@@ -131,8 +135,7 @@ namespace Mono.Nat.Upnp
 			}
 			else
 			{
-				Trace.WriteLine("Couldn't decode address. Please send following string to the developer: ");
-				Trace.WriteLine(deviceDetails);
+                logger.Warn("Couldn't decode address: " + deviceDetails);
 			}
 		}
 
@@ -527,7 +530,7 @@ namespace Mono.Nat.Upnp
 
 			// Create a HTTPWebRequest to download the list of services the device offers
 			byte[] body;
-			WebRequest request = new GetServicesMessage(this.serviceDescriptionUrl, this.hostEndPoint).Encode(out body);
+			WebRequest request = new GetServicesMessage(this.serviceDescriptionUrl, this.hostEndPoint, _logger).Encode(out body);
 			if (body.Length > 0)
 				NatUtility.Log("Error: Services Message contained a body");
 			request.BeginGetResponse(this.ServicesReceived, request);