Пример #1
0
        private bool RemovePortMapping(ExistingUPnPPortMapping portMapping)
        {
            int result = MiniUPnP.UPNPCOMMAND_SUCCESS;

            bool udpResult = true;
            bool tcpResult = true;

            String extPortStr = portMapping.ExternalPort.ToString();

            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.UDP) > 0)
            {
                try
                {
                    result = MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "UDP");
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that it works perfect, except for the stupid exception.
                    // 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_DeletePortMapping");
                }

                DebugLog.WriteLine("UPnP: RemovePortMapping: UDP: result = {0}", result);
                udpResult = (result == MiniUPnP.UPNPCOMMAND_SUCCESS);
            }
            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.TCP) > 0)
            {
                try
                {
                    result = MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "TCP");
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that it works perfect, except for the stupid exception.
                    // 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_DeletePortMapping");
                }

                DebugLog.WriteLine("UPnP: RemovePortMapping: TCP: result = {0}", result);
                tcpResult = (result == MiniUPnP.UPNPCOMMAND_SUCCESS);
            }

            return(udpResult && tcpResult);
        }
Пример #2
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();
        }
Пример #3
0
        private bool AddPortMapping(PortMapping portMapping)
        {
            portMapping.SetMappingStatus(PortMappingStatus.Trying);

            String intPortStr  = portMapping.LocalPort.ToString();
            String intClient   = PortMapper.SharedInstance.LocalIPAddress.ToString();
            String description = GetPortMappingDescription();

            bool done         = false;
            int  attemptCount = 0;

            do
            {
                int udpErrCode = 0;
                int tcpErrCode = 0;

                bool udpResult = true;
                bool tcpResult = true;

                UInt16 extPort;
                if (portMapping.DesiredExternalPort < (65535 - 40))
                {
                    extPort = (UInt16)(portMapping.DesiredExternalPort + attemptCount);
                }
                else
                {
                    extPort = (UInt16)(portMapping.DesiredExternalPort - attemptCount);
                }

                String extPortStr = extPort.ToString();

                if ((portMapping.TransportProtocol & PortMappingTransportProtocol.UDP) > 0)
                {
                    ExistingUPnPPortMapping existingPM;
                    if (existingUPnPPortMappingsUdpDict.TryGetValue(extPort, out existingPM))
                    {
                        udpErrCode = 718;
                        DebugLog.WriteLine("UPnP: AddPortMapping: UDP: mapping already exists");
                    }
                    else
                    {
                        udpErrCode = MiniUPnP.UPNP_AddPortMapping(urls.controlURL, igddata.ServiceType,
                                                                  extPortStr, intPortStr, intClient, description, "UDP");
                        DebugLog.WriteLine("UPnP: AddPortMapping: UDP: result = {0}", udpErrCode);
                    }

                    udpResult = (udpErrCode == MiniUPnP.UPNPCOMMAND_SUCCESS);
                }
                if ((portMapping.TransportProtocol & PortMappingTransportProtocol.TCP) > 0)
                {
                    ExistingUPnPPortMapping existingPM;
                    if (existingUPnPPortMappingsTcpDict.TryGetValue(extPort, out existingPM))
                    {
                        tcpErrCode = 718;
                        DebugLog.WriteLine("UPnP: AddPortMapping: TCP: mapping already exists");
                    }
                    else
                    {
                        tcpErrCode = MiniUPnP.UPNP_AddPortMapping(urls.controlURL, igddata.ServiceType,
                                                                  extPortStr, intPortStr, intClient, description, "TCP");
                        DebugLog.WriteLine("UPnP: AddPortMapping: TCP: result = {0}", tcpErrCode);
                    }

                    tcpResult = (tcpErrCode == MiniUPnP.UPNPCOMMAND_SUCCESS);
                }

                if (udpResult && !tcpResult)
                {
                    DebugLog.WriteLine("Deleting UDP mapping");
                    try
                    {
                        MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "UDP");
                    }
                    catch (AccessViolationException)
                    {
                        // I have no idea why the above method sometimes throws an AccessException.
                        // The odd part about it is that it works perfect, except for the stupid exception.
                        // 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_DeletePortMapping");
                    }
                }
                if (tcpResult && !udpResult)
                {
                    DebugLog.WriteLine("Deleting TCP mapping");
                    try
                    {
                        MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "TCP");
                    }
                    catch (AccessViolationException)
                    {
                        // I have no idea why the above method sometimes throws an AccessException.
                        // The odd part about it is that it works perfect, except for the stupid exception.
                        // 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_DeletePortMapping");
                    }
                }

                if (udpResult && tcpResult)
                {
                    // All attempted port mappings were successful
                    portMapping.SetExternalPort(extPort);
                    portMapping.SetMappingStatus(PortMappingStatus.Mapped);
                    return(true);
                }

                attemptCount++;
                if (attemptCount >= 10)
                {
                    // We've tried 10 different mappings and still no success
                    done = true;
                }
                else if (!udpResult && udpErrCode != 718)
                {
                    // We received non-conflict error
                    done = true;
                }
                else if (!tcpResult && tcpErrCode != 718)
                {
                    // We received non-conflict error
                    done = true;
                }
            } while (!done);

            portMapping.SetMappingStatus(PortMappingStatus.Unmapped);
            return(false);
        }
Пример #4
0
        private bool RemovePortMapping(PortMapping portMapping)
        {
            // Make sure the mapping still belongs to us
            IPAddress ourIP          = PortMapper.SharedInstance.LocalIPAddress;
            String    ourDescription = GetPortMappingDescription();

            bool udpMappingStolen = false;
            bool tcpMappingStolen = false;

            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.UDP) > 0)
            {
                ExistingUPnPPortMapping existingPM;
                if (existingUPnPPortMappingsUdpDict.TryGetValue(portMapping.ExternalPort, out existingPM))
                {
                    if (!existingPM.LocalAddress.Equals(ourIP) || !existingPM.Description.Equals(ourDescription))
                    {
                        // The mapping was stolen by another machine or process
                        // Do not remove it, but for our purposes we can consider it removed

                        DebugLog.WriteLine("UPnP: RemovePortMapping: UDP mapping stolen");
                        udpMappingStolen = true;
                    }
                }
            }
            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.TCP) > 0)
            {
                ExistingUPnPPortMapping existingPM;
                if (existingUPnPPortMappingsTcpDict.TryGetValue(portMapping.ExternalPort, out existingPM))
                {
                    if (!existingPM.LocalAddress.Equals(ourIP) || !existingPM.Description.Equals(ourDescription))
                    {
                        // The mapping was stolen by another machine or process
                        // Do not remove it, but for our purposes we can consider it removed

                        DebugLog.WriteLine("UPnP: RemovePortMapping: TCM mapping stolen");
                        tcpMappingStolen = true;
                    }
                }
            }

            int result = MiniUPnP.UPNPCOMMAND_SUCCESS;

            bool udpResult = true;
            bool tcpResult = true;

            String extPortStr = portMapping.ExternalPort.ToString();

            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.UDP) > 0 && !udpMappingStolen)
            {
                try
                {
                    result = MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "UDP");
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that it works perfect, except for the stupid exception.
                    // 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_DeletePortMapping");
                }

                DebugLog.WriteLine("UPnP: RemovePortMapping: UDP: result = {0}", result);
                udpResult = (result == MiniUPnP.UPNPCOMMAND_SUCCESS);
            }
            if ((portMapping.TransportProtocol & PortMappingTransportProtocol.TCP) > 0 && !tcpMappingStolen)
            {
                try
                {
                    result = MiniUPnP.UPNP_DeletePortMapping(urls.controlURL, igddata.ServiceType, extPortStr, "TCP");
                }
                catch (AccessViolationException)
                {
                    // I have no idea why the above method sometimes throws an AccessException.
                    // The odd part about it is that it works perfect, except for the stupid exception.
                    // 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_DeletePortMapping");
                }

                DebugLog.WriteLine("UPnP: RemovePortMapping: TCP: result = {0}", result);
                tcpResult = (result == MiniUPnP.UPNPCOMMAND_SUCCESS);
            }

            portMapping.SetMappingStatus(PortMappingStatus.Unmapped);

            return(udpResult && tcpResult);
        }
Пример #5
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;
        }