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); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region Update Port Mappings Thread /////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void UpdatePortMappingsThread() { Monitor.Enter(multiThreadLock); OnDidBeginWorking(); // Remove existing mappings scheduled for removal. // These are mappings that weren't created by us, but have been explicity set for removal. List <ExistingUPnPPortMapping> existingMappingsToRemove; existingMappingsToRemove = PortMapper.SharedInstance.ExistingUPnPPortMappingsToRemove; lock (existingMappingsToRemove) { while ((existingMappingsToRemove.Count > 0) && (updatePortMappingsThreadFlags == ThreadFlags.None)) { ExistingUPnPPortMapping existingMappingToRemove = existingMappingsToRemove[0]; RemovePortMapping(existingMappingToRemove); existingMappingsToRemove.RemoveAt(0); } } // We need to safeguard mappings that others might have made. // UPnP is quite generous in giving us what we want, // even if other mappings are there, especially from the same local machine. DoUpdateExistingUPnPPortMappings(); // Remove mappings scheduled for removal List <PortMapping> mappingsToRemove = PortMapper.SharedInstance.PortMappingsToRemove; lock (mappingsToRemove) { while ((mappingsToRemove.Count > 0) && (updatePortMappingsThreadFlags == ThreadFlags.None)) { PortMapping mappingToRemove = mappingsToRemove[0]; if (mappingToRemove.MappingStatus == PortMappingStatus.Mapped) { RemovePortMapping(mappingToRemove); } mappingsToRemove.RemoveAt(0); } } // If the port mapper is running: // -Add new mappings // If the port mapper is stopped: // -Remove any existing mappings List <PortMapping> mappings = PortMapper.SharedInstance.PortMappings; lock (mappings) { for (int i = 0; i < mappings.Count && updatePortMappingsThreadFlags == ThreadFlags.None; i++) { PortMapping currentMapping = mappings[i]; bool isRunning = PortMapper.SharedInstance.IsRunning; if (currentMapping.MappingStatus == PortMappingStatus.Unmapped && isRunning) { AddPortMapping(currentMapping); } else if (currentMapping.MappingStatus == PortMappingStatus.Mapped && !isRunning) { RemovePortMapping(currentMapping); } } } Monitor.Exit(multiThreadLock); if (PortMapper.SharedInstance.IsRunning) { if ((updatePortMappingsThreadFlags & ThreadFlags.ShouldRestart) > 0) { UpdatePortMappings(); } else if ((updatePortMappingsThreadFlags & ThreadFlags.ShouldQuit) > 0) { Refresh(); } } OnDidEndWorking(); }
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; }
/// <summary> /// Asynchronously removes the given port mapping. /// /// This method will also automatically refresh the UPnP mapping table, /// and call the DidReceiveUPNPMappingTable delegate. /// </summary> /// <param name="pm"> /// The port mapping to remove. /// </param> public void RemovePortMapping(ExistingUPnPPortMapping 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) { if (upnpStatus == MappingStatus.Works) { lock (existingUPnPPortMappingsToRemove) { existingUPnPPortMappingsToRemove.Add(pm); } if (isRunning) { requestedUPnPMappingTable = true; UpdatePortMappings(); } } } }
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 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; }