Exemplo n.º 1
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        #endregion
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        #region Refresh External IP Thread
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void RefreshExternalIPThread()
        {
            Monitor.Enter(multiThreadLock);
            OnDidBeginWorking();

            IntPtr devlistP = IntPtr.Zero;

            byte[] lanAddr      = new byte[16];
            byte[] externalAddr = new byte[16];

            bool didFail = false;

            devlistP = MiniUPnP.upnpDiscover(2500, IntPtr.Zero, IntPtr.Zero);
            if (devlistP == IntPtr.Zero)
            {
                DebugLog.WriteLine("UPnP: No IDG Device found on the network (1)");
                didFail = true;
            }
            else
            {
                MiniUPnP.UPNPDev devlist = MiniUPnP.PtrToUPNPDev(devlistP);

                // Check all of the devices for reachability
                bool             foundIDGDevice = false;
                MiniUPnP.UPNPDev device         = devlist;

                IPAddress routerIP = PortMapper.SharedInstance.RouterIPAddress;

                List <String> descURLs = new List <String>();

                bool done = false;
                while (!done)
                {
                    try
                    {
                        Uri uri = new Uri(device.descURL);

                        if (routerIP != null)
                        {
                            if (uri.Host == routerIP.ToString())
                            {
                                descURLs.Insert(0, device.descURL);
                            }
                            else
                            {
                                descURLs.Add(device.descURL);
                            }
                        }
                        else
                        {
                            descURLs.Add(device.descURL);
                        }
                    }
                    catch (Exception e)
                    {
                        DebugLog.WriteLine("UPnP: Error while inspecting url: {0}", device.descURL);
                        DebugLog.WriteLine("UPnP: Exception: {0}", e);
                    }

                    if (device.pNext == IntPtr.Zero)
                    {
                        done = true;
                    }
                    else
                    {
                        device = device.Next;
                    }
                }

                for (int i = 0; i < descURLs.Count && !foundIDGDevice; i++)
                {
                    String url = descURLs[i];
                    DebugLog.WriteLine("UPnP: Trying URL: {0}", url);

                    // Reset service type.
                    // This will help us determine if the exception below can safely be ignored.
                    igddata.ServiceType = null;

                    int r = 0;
                    try
                    {
                        //	r = MiniUPnP.UPNP_GetIGDFromUrl(url, ref urls, ref igddata, lanAddr, lanAddr.Length);

                        MiniUPnP.UPNPUrls_2 urls_2 = new MiniUPnP.UPNPUrls_2();
                        unsafe
                        {
                            r = MiniUPnP.UPNP_GetIGDFromUrl(url, &urls_2, ref igddata, lanAddr, lanAddr.Length);
                            MiniUPnP.FreeUPNPUrls(&urls_2);
                        }

                        // Find urls
                        GetUPNPUrls(url);
                    }
                    catch (AccessViolationException)
                    {
                        // I have no idea why the above method sometimes throws an AccessException.
                        // The odd part about it is that all the data gets marshaled over and back properly.
                        // So the exception can safely be ignored, it just bugs me because it feels like a hack.
                        DebugLog.WriteLine("Ignoring exception from method MiniUPnP.UPNP_GetIGDFromUrl");

                        if (igddata.ServiceType != null)
                        {
                            r = 1;
                        }
                    }

                    if (r == 1)
                    {
                        r = MiniUPnP.UPNPCOMMAND_UNKNOWN_ERROR;
                        try
                        {
                            r = MiniUPnP.UPNP_GetExternalIPAddress(urls.controlURL, igddata.ServiceType, externalAddr);
                        }
                        catch (AccessViolationException)
                        {
                            // I have no idea why the above method sometimes throws an AccessException.
                            // The odd part about it is that all the data gets marshaled over and back properly.
                            // So the exception can safely be ignored, it just bugs me because it feels like a hack.
                            DebugLog.WriteLine("Ignoring exception from method MiniUPnP.UPNP_GetExternalIPAddress");

                            if (externalAddr[0] != 0)
                            {
                                r = MiniUPnP.UPNPCOMMAND_SUCCESS;
                            }
                        }

                        if (r != MiniUPnP.UPNPCOMMAND_SUCCESS)
                        {
                            DebugLog.WriteLine("UPnP: GetExternalIPAddress returned {0}", r);
                        }
                        else
                        {
                            IPAddress externalIP;
                            IPAddress.TryParse(MiniUPnP.NullTerminatedArrayToString(externalAddr), out externalIP);

                            if (externalIP != null)
                            {
                                OnDidGetExternalIPAddress(externalIP);

                                foundIDGDevice = true;
                                didFail        = false;
                            }
                        }
                    }
                }

                if (!foundIDGDevice)
                {
                    DebugLog.WriteLine("UPnP: No IDG Device found on the network (2)");
                    didFail = true;
                }

                try
                {
                    MiniUPnP.freeUPNPDevlist(devlistP);
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that all the data gets marshaled over and back properly.
                    // So the exception can safely be ignored, it just bugs me because it feels like a hack.
                    DebugLog.WriteLine("Ignoring exception from method MiniUPnP.freeUPNPDevlist");
                }
            }

            Monitor.Exit(multiThreadLock);

            if (refreshExternalIPThreadFlags != ThreadFlags.None)
            {
                if ((refreshExternalIPThreadFlags & ThreadFlags.ShouldRestart) > 0)
                {
                    Refresh();
                }
            }
            else
            {
                if (didFail)
                {
                    OnDidFail();
                }
                else
                {
                    UpdatePortMappings();
                }
            }
            OnDidEndWorking();
        }
Exemplo n.º 2
0
        private void DoUpdateExistingUPnPPortMappings()
        {
            List <ExistingUPnPPortMapping> existingMappings = new List <ExistingUPnPPortMapping>();

            Dictionary <UInt16, ExistingUPnPPortMapping> existingMappingsUdpDict =
                new Dictionary <UInt16, ExistingUPnPPortMapping>();
            Dictionary <UInt16, ExistingUPnPPortMapping> existingMappingsTcpDict =
                new Dictionary <UInt16, ExistingUPnPPortMapping>();

            int r = 0;
            int i = 0;

            byte[] index     = new byte[6];
            byte[] intClient = new byte[16];
            byte[] intPort   = new byte[6];
            byte[] extPort   = new byte[6];
            byte[] protocol  = new byte[4];
            byte[] desc      = new byte[80];
            byte[] enabled   = new byte[6];
            byte[] rHost     = new byte[64];
            byte[] duration  = new byte[16];

            do
            {
                // Convert "int i" to a null-terminated char array
                String iStr     = i.ToString();
                int    maxCount = Math.Min(iStr.Length, 5);
                System.Text.Encoding.ASCII.GetBytes(iStr, 0, maxCount, index, 0);

                // Reset all the other null-terminated char arrays
                intClient[0] = 0;
                intPort[0]   = 0;
                extPort[0]   = 0;
                protocol[0]  = 0;                 // Warning - not in Cocoa version
                desc[0]      = 0;
                enabled[0]   = 0;
                rHost[0]     = 0;
                duration[0]  = 0;

                r = MiniUPnP.UPNPCOMMAND_UNKNOWN_ERROR;
                try
                {
                    r = MiniUPnP.UPNP_GetGenericPortMappingEntry(urls.controlURL, igddata.ServiceType,
                                                                 index,
                                                                 extPort, intClient, intPort,
                                                                 protocol, desc, enabled,
                                                                 rHost, duration);
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that all the data gets marshaled over and back properly.
                    // So the exception can safely be ignored, it just bugs me because it feels like a hack.
                    DebugLog.WriteLine("Ignoring exception from method MiniUPnP.UPNP_GetGenericPortMappingEntry");

                    r = MiniUPnP.UPNPCOMMAND_SUCCESS;
                }

                if (r == MiniUPnP.UPNPCOMMAND_SUCCESS)
                {
                    IPAddress iAddr;
                    IPAddress.TryParse(MiniUPnP.NullTerminatedArrayToString(intClient), out iAddr);

                    UInt16 iPort;
                    UInt16.TryParse(MiniUPnP.NullTerminatedArrayToString(intPort), out iPort);

                    UInt16 ePort;
                    UInt16.TryParse(MiniUPnP.NullTerminatedArrayToString(extPort), out ePort);

                    PortMappingTransportProtocol transportProtocol = 0;
                    String protocolStr = MiniUPnP.NullTerminatedArrayToString(protocol);
                    if (protocolStr.Equals("UDP", StringComparison.OrdinalIgnoreCase))
                    {
                        transportProtocol |= PortMappingTransportProtocol.UDP;
                    }
                    if (protocolStr.Equals("TCP", StringComparison.OrdinalIgnoreCase))
                    {
                        transportProtocol |= PortMappingTransportProtocol.TCP;
                    }

                    String description = MiniUPnP.NullTerminatedArrayToString(desc);

                    ExistingUPnPPortMapping existingPM;
                    existingPM = new ExistingUPnPPortMapping(iAddr, iPort, ePort, transportProtocol, description);

                    existingMappings.Add(existingPM);

                    if ((transportProtocol & PortMappingTransportProtocol.UDP) > 0)
                    {
                        existingMappingsUdpDict[ePort] = existingPM;
                    }
                    if ((transportProtocol & PortMappingTransportProtocol.TCP) > 0)
                    {
                        existingMappingsTcpDict[ePort] = existingPM;
                    }

                    DebugLog.WriteLine("Existing UPnP: {0}: {1} {2}->{3}:{4} ({5})",
                                       i, protocolStr, ePort, iAddr, iPort, description);
                }

                i++;
            } while ((r == MiniUPnP.UPNPCOMMAND_SUCCESS) && (updatePortMappingsThreadFlags == ThreadFlags.None));

            // Update stored list of existing mappings
            existingUPnPPortMappings        = existingMappings;
            existingUPnPPortMappingsUdpDict = existingMappingsUdpDict;
            existingUPnPPortMappingsTcpDict = existingMappingsTcpDict;
        }