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);
        }
        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);
        }
        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);
        }