public ExistingUPnPPortMapping(IPAddress localAddress, UInt16 localPort, UInt16 externalPort,
                                PortMappingTransportProtocol transportProtocol, String description)
 {
     this.localAddress      = localAddress;
     this.localPort         = localPort;
     this.externalPort      = externalPort;
     this.transportProtocol = transportProtocol;
     this.description       = description;
 }
 public ExistingUPnPPortMapping(IPAddress localAddress, UInt16 localPort, UInt16 externalPort,
     PortMappingTransportProtocol transportProtocol, String description)
 {
     this.localAddress = localAddress;
     this.localPort = localPort;
     this.externalPort = externalPort;
     this.transportProtocol = transportProtocol;
     this.description = description;
 }
        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;
        }
        public PortMapping(UInt16 localPort, UInt16 desiredExternalPort, PortMappingTransportProtocol protocol)
        {
            this.localPort = localPort;
            this.desiredExternalPort = desiredExternalPort;
            this.transportProtocol = protocol;

            this.mappingStatus = PortMappingStatus.Unmapped;
        }
        private bool ApplyPortMapping(PortMapping portMapping, bool remove, ref NATPMP.natpmp_t natpmp)
        {
            NATPMP.natpmpresp_t response = new NATPMP.natpmpresp_t();
            int r;

            Win32.TimeValue         timeout = new Win32.TimeValue();
            Win32.FileDescriptorSet fds     = new Win32.FileDescriptorSet(1);

            if (!remove)
            {
                portMapping.SetMappingStatus(PortMappingStatus.Trying);
            }
            PortMappingTransportProtocol protocol = portMapping.TransportProtocol;

            for (int i = 1; i <= 2; i++)
            {
                PortMappingTransportProtocol currentProtocol;
                if (i == 1)
                {
                    currentProtocol = PortMappingTransportProtocol.UDP;
                }
                else
                {
                    currentProtocol = PortMappingTransportProtocol.TCP;
                }

                if (protocol == currentProtocol || protocol == PortMappingTransportProtocol.Both)
                {
                    r = NATPMP.sendnewportmappingrequest(ref natpmp,
                                                         (i == 1) ? NATPMP.PROTOCOL_UDP : NATPMP.PROTOCOL_TCP,
                                                         portMapping.LocalPort, portMapping.DesiredExternalPort, (uint)(remove ? 0 : 3600));

                    do
                    {
                        fds.Count    = 1;
                        fds.Array[0] = (IntPtr)natpmp.s;
                        NATPMP.getnatpmprequesttimeout(ref natpmp, ref timeout);

                        Win32.select(0, ref fds, IntPtr.Zero, IntPtr.Zero, ref timeout);

                        r = NATPMP.readnatpmpresponseorretry(ref natpmp, ref response);
                    }while(r == NATPMP.ERR_TRYAGAIN);

                    if (r < 0)
                    {
                        portMapping.SetMappingStatus(PortMappingStatus.Unmapped);
                        return(false);
                    }
                }
            }

            if (remove)
            {
                portMapping.SetMappingStatus(PortMappingStatus.Unmapped);
            }
            else
            {
                updateInterval = Math.Min(updateInterval, response.pnu_newportmapping.lifetime / 2);
                if (updateInterval < 60)
                {
                    DebugLog.WriteLine("NAT-PMP: ApplyPortMapping: Caution - new port mapping had a lifetime < 120 ({0})",
                                       response.pnu_newportmapping.lifetime);

                    updateInterval = 60;
                }
                portMapping.SetExternalPort(response.pnu_newportmapping.mappedpublicport);
                portMapping.SetMappingStatus(PortMappingStatus.Mapped);
            }

            return(true);
        }