From 68f67b7c8edb5d78867ca2222bb6e5c16d922cff Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Nov 2013 15:17:42 +0000 Subject: [PATCH] UPnP: (ticket #1123) - Add new config i2np.upnp.ignore to specify UDNs of ignored devices - Add display of ignored devices on /peers --- .../src/net/i2p/router/transport/UPnP.java | 73 ++++++++++++++++--- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/router/java/src/net/i2p/router/transport/UPnP.java b/router/java/src/net/i2p/router/transport/UPnP.java index 9d38230e1e..99b30d346d 100644 --- a/router/java/src/net/i2p/router/transport/UPnP.java +++ b/router/java/src/net/i2p/router/transport/UPnP.java @@ -8,6 +8,7 @@ import java.net.MalformedURLException; import java.net.UnknownHostException; import java.net.URL; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -78,6 +79,8 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { private Device _router; private Service _service; + // UDN -> friendly name + private final Map<String, String> _otherUDNs; private boolean isDisabled = false; // We disable the plugin if more than one IGD is found private volatile boolean _serviceLacksAPM; private final Object lock = new Object(); @@ -92,6 +95,7 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { private ForwardPortCallback forwardCallback; private static final String PROP_ADVANCED = "routerconsole.advanced"; + private static final String PROP_IGNORE = "i2np.upnp.ignore"; public UPnP(I2PAppContext context) { super(); @@ -99,6 +103,7 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { _log = _context.logManager().getLog(UPnP.class); portsToForward = new HashSet<ForwardPort>(); portsForwarded = new HashSet<ForwardPort>(); + _otherUDNs = new HashMap<String, String>(4); addDeviceChangeListener(this); } @@ -178,21 +183,33 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { * DeviceChangeListener */ public void deviceAdded(Device dev) { + String udn = dev.getUDN(); + if (udn == null) + udn = "???"; + String name = dev.getFriendlyName(); + if (name == null) + name = "???"; synchronized (lock) { if(isDisabled) { if (_log.shouldLog(Log.WARN)) - _log.warn("Plugin has been disabled previously, ignoring new device."); + _log.warn("Plugin has been disabled previously, ignoring " + name + " UDN: " + udn); + _otherUDNs.put(udn, name); return; } } if(!ROUTER_DEVICE.equals(dev.getDeviceType()) || !dev.isRootDevice()) { if (_log.shouldLog(Log.WARN)) - _log.warn("UP&P non-IGD device found, ignoring : " + dev.getFriendlyName()); + _log.warn("UP&P non-IGD device found, ignoring " + name); + synchronized (lock) { + _otherUDNs.put(udn, name); + } return; // ignore non-IGD devices } else if(isNATPresent()) { // maybe we should see if the old one went away before ignoring the new one? - if (_log.shouldLog(Log.WARN)) - _log.warn("UP&P ignoring additional IGD device found: " + dev.getFriendlyName() + " UDN: " + dev.getUDN()); + _log.logAlways(Log.WARN, "UP&P ignoring additional device " + name + " UDN: " + udn); + synchronized (lock) { + _otherUDNs.put(udn, name); + } /********** seems a little drastic isDisabled = true; @@ -206,11 +223,29 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { return; } - if (_log.shouldLog(Log.WARN)) - _log.warn("UP&P IGD found : " + dev.getFriendlyName() + " UDN: " + dev.getUDN() + " lease time: " + dev.getLeaseTime()); + boolean ignore = false; + String toIgnore = _context.getProperty(PROP_IGNORE); + if (toIgnore != null) { + String[] ignores = toIgnore.split("[,; \r\n\t]"); + for (int i = 0; i < ignores.length; i++) { + if (ignores[i].equals(udn)) { + ignore = true; + _log.logAlways(Log.WARN, "Ignoring by config: " + name + " UDN: " + udn); + break; + } + } + } synchronized(lock) { - _router = dev; + if (ignore) { + _otherUDNs.put(udn, name); + return; + } else { + _router = dev; + } } + + if (_log.shouldLog(Log.WARN)) + _log.warn("UP&P IGD found : " + name + " UDN: " + udn + " lease time: " + dev.getLeaseTime()); discoverService(); // We have found the device we need: stop the listener thread @@ -303,16 +338,21 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { * DeviceChangeListener */ public void deviceRemoved(Device dev ){ + String udn = dev.getUDN(); if (_log.shouldLog(Log.WARN)) - _log.warn("UP&P device removed : " + dev.getFriendlyName() + " UDN: " + dev.getUDN()); + _log.warn("UP&P device removed : " + dev.getFriendlyName() + " UDN: " + udn); synchronized (lock) { if(_router == null) return; + if (udn != null) + _otherUDNs.remove(udn); + else + _otherUDNs.remove("???"); // I2P this wasn't working //if(_router.equals(dev)) { if(ROUTER_DEVICE.equals(dev.getDeviceType()) && dev.isRootDevice() && stringEquals(_router.getFriendlyName(), dev.getFriendlyName()) && - stringEquals(_router.getUDN(), dev.getUDN())) { + stringEquals(_router.getUDN(), udn)) { if (_log.shouldLog(Log.WARN)) _log.warn("UP&P IGD device removed : " + dev.getFriendlyName()); _router = null; @@ -557,6 +597,21 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { final StringBuilder sb = new StringBuilder(); sb.append("<h3><a name=\"upnp\"></a>").append(_("UPnP Status")).append("</h3>"); + synchronized(_otherUDNs) { + if (!_otherUDNs.isEmpty()) { + sb.append(_("Disabled UPnP Devices")); + sb.append("<ul>"); + for (Map.Entry<String, String> e : _otherUDNs.entrySet()) { + String udn = e.getKey(); + String name = e.getValue(); + sb.append("<li>").append(name) + .append("<br>UDN: ").append(udn) + .append("</li>"); + } + sb.append("</ul>"); + } + } + if(isDisabled) { sb.append(_("UPnP has been disabled; Do you have more than one UPnP Internet Gateway Device on your LAN ?")); return sb.toString(); -- GitLab