/////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void AddPortMapping(PortMapping pm, String description) { mappingsListView.BeginUpdate(); { ListViewItem lvi = new ListViewItem(description); lvi.SubItems.Add(pm.LocalPort.ToString()); lvi.SubItems.Add(pm.DesiredExternalPort.ToString()); lvi.SubItems.Add(""); lvi.SubItems.Add(pm.ExternalPort.ToString()); lvi.Tag = pm; mappings.Add(lvi); mappingsListView.VirtualListSize = mappings.Count; } mappingsListView.EndUpdate(); PortMapper.SharedInstance.AddPortMapping(pm); }
internal virtual void OnDidChangeMappingStatus(PortMapping pm) { // It is vitally important that we Invoke this on a background thread! // The mapping status is generally changed within the context of a lock on the mappings list. // This lock is also used within public API methods, // so if we don't use a background thread, there's a potential for deadlock. Thread bgThread = new Thread(new ParameterizedThreadStart(OnDidChangeMappingStatusThread)); bgThread.IsBackground = true; bgThread.Start(pm); }
private void PortMapper_DidChangeMappingStatus(PortMapper sender, PortMapping pm) { DebugLog.WriteLine("Form1: PortMapper_DidChangeMappingStatus"); foreach (ListViewItem lvi in mappings) { PortMapping lvi_pm = (PortMapping)lvi.Tag; if (lvi_pm == pm) { mappingsListView.RedrawItems(lvi.Index, lvi.Index, false); } } }
private void okButton_Click(object sender, EventArgs e) { UInt16 localPort; UInt16.TryParse(localPortTextBox.Text, out localPort); UInt16 publicPort; UInt16.TryParse(publicPortTextBox.Text, out publicPort); PortMappingTransportProtocol protocol; if (tcpCheckBox.Checked) { if (udpCheckBox.Checked) protocol = PortMappingTransportProtocol.Both; else protocol = PortMappingTransportProtocol.TCP; } else { protocol = PortMappingTransportProtocol.UDP; } PortMapping pm = new PortMapping(localPort, publicPort, protocol); String description; if (descriptionTextBox.ForeColor == Color.Gray) description = ""; else description = descriptionTextBox.Text; WindowManager.GetMainForm().AddPortMapping(pm, description); ClearForm(); Close(); }
/// <summary> /// Asynchronously removes the given port mapping. /// </summary> /// <param name="pm"> /// The port mapping to remove. /// </param> public void RemovePortMapping(PortMapping pm) { if(pm == null) return; // All public API methods are wrapped in a single thread lock. // This frees users to invoke the public API from multiple threads, but provides us a bit of sanity. lock (singleThreadLock) { lock (portMappings) { portMappings.Remove(pm); } lock (portMappingsToRemove) { if (pm.MappingStatus != PortMappingStatus.Unmapped) { portMappingsToRemove.Add(pm); } } if (isRunning) UpdatePortMappings(); } }
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; }
private bool RemovePortMapping(PortMapping portMapping, ref NATPMP.natpmp_t natpmp) { return ApplyPortMapping(portMapping, true, ref natpmp); }
private bool RefreshPortMapping(PortMapping portMapping, ref NATPMP.natpmp_t natpmp) { return ApplyPortMapping(portMapping, false, ref natpmp); }
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; }