diff --git a/history.txt b/history.txt index 2c4e4574d7..13bcf7a827 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,5 @@ 2022-05-11 zzz + * Transport: Fix thrashing of UPnP IPv6 listen sockets * Util: Rename modified apache classes (Gitlab ticket #353) 2022-05-02 zzz diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index d1964d0a73..70f962848e 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Git"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 17; + public final static long BUILD = 18; /** for example "-test" */ public final static String EXTRA = "-rc"; diff --git a/router/java/src/net/i2p/router/transport/UPnP.java b/router/java/src/net/i2p/router/transport/UPnP.java index 33f4da638e..92c4d99789 100644 --- a/router/java/src/net/i2p/router/transport/UPnP.java +++ b/router/java/src/net/i2p/router/transport/UPnP.java @@ -3,6 +3,7 @@ * http://www.gnu.org/ for further details of the GPL. */ package net.i2p.router.transport; +import java.io.IOException; import java.io.Serializable; import java.net.InetAddress; import java.net.Inet6Address; @@ -724,12 +725,20 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis int slash = addr.indexOf('/'); if (slash >= 0) addr = addr.substring(slash + 1); + int pct = addr.indexOf('%'); + if (pct > 0) + addr = addr.substring(0, pct); if (!addrs.contains(addr)) { + // the first time through this will close a lot of sockets, + // because HTTPServerList binds to every address, + // including IPv6 deprecated iter.remove(); skt.close(); skt.stop(); if (_log.shouldWarn()) _log.warn("Closed HTTP server socket: " + addr); + } else if (_log.shouldDebug()) { + _log.debug("Retained HTTP server socket: " + addr); } oldaddrs.add(addr); } @@ -758,6 +767,9 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis for (Iterator iter = list.iterator(); iter.hasNext(); ) { SSDPSearchResponseSocket skt = iter.next(); String addr = skt.getLocalAddress(); + int pct = addr.indexOf('%'); + if (pct > 0) + addr = addr.substring(0, pct); if (!addrs.contains(addr)) { iter.remove(); skt.setControlPoint(null); @@ -765,6 +777,8 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis skt.stop(); if (_log.shouldWarn()) _log.warn("Closed SSDP search response socket: " + addr); + } else if (_log.shouldDebug()) { + _log.debug("Retained SSDP search response socket: " + addr); } oldaddrs.add(addr); } @@ -785,6 +799,9 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis for (Iterator iter = nlist.iterator(); iter.hasNext(); ) { SSDPNotifySocket skt = iter.next(); String addr = skt.getLocalAddress(); + int pct = addr.indexOf('%'); + if (pct > 0) + addr = addr.substring(0, pct); if (!addrs.contains(addr)) { iter.remove(); skt.setControlPoint(null); @@ -792,20 +809,29 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis skt.stop(); if (_log.shouldWarn()) _log.warn("Closed SSDP notify socket: " + addr); + } else if (_log.shouldDebug()) { + _log.debug("Retained SSDP notify socket: " + addr); } oldaddrs.add(addr); } for (String addr : addrs) { if (!oldaddrs.contains(addr)) { - // TODO this calls open() in constructor, fails silently - SSDPNotifySocket socket = new SSDPNotifySocket(addr); - socket.setControlPoint(this); - socket.start(); - nlist.add(socket); - if (_log.shouldWarn()) - _log.warn("Added SSDP notify socket: " + addr); + try { + SSDPNotifySocket socket = new SSDPNotifySocket(addr); + socket.setControlPoint(this); + socket.start(); + nlist.add(socket); + if (_log.shouldWarn()) + _log.warn("Added SSDP notify socket: " + addr); + } catch (IOException ioe) { + if (_log.shouldWarn()) + _log.warn("Failed to add SSDP notify socket: " + addr, ioe); + } } } + + if (_log.shouldDebug()) + _log.debug("Current sockets:\nHTTP: " + hlist + "\nSearch response: " + list + "\nNotify: " + nlist); } } @@ -1562,7 +1588,8 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis Service service; synchronized(lock) { if(!isNATPresent()) { - _log.error("Can't removeMapping: " + isNATPresent() + " " + _router); + if (_log.shouldWarn()) + _log.warn("Can't removeMapping: " + isNATPresent() + " " + _router); return false; } service = fp.isIP6 ? _service6 : _service; diff --git a/router/java/src/org/cybergarage/http/HTTPServer.java b/router/java/src/org/cybergarage/http/HTTPServer.java index 5c37deaff1..1747fef9fb 100644 --- a/router/java/src/org/cybergarage/http/HTTPServer.java +++ b/router/java/src/org/cybergarage/http/HTTPServer.java @@ -262,4 +262,8 @@ public class HTTPServer implements Runnable httpServerThread = null; return true; } + + /** I2P */ + @Override + public String toString() { return getBindAddress(); } } diff --git a/router/java/src/org/cybergarage/upnp/Device.java b/router/java/src/org/cybergarage/upnp/Device.java index 00b0b866b5..54ac981d25 100644 --- a/router/java/src/org/cybergarage/upnp/Device.java +++ b/router/java/src/org/cybergarage/upnp/Device.java @@ -98,6 +98,7 @@ package org.cybergarage.upnp; import java.io.File; import java.io.InputStream; +import java.io.IOException; import java.net.InetAddress; import java.net.URL; import java.util.Calendar; @@ -1439,7 +1440,14 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, public void announce(String bindAddr) { String devLocation = getLocationURL(bindAddr); - SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); + SSDPNotifySocket ssdpSock; + // I2P + try { + ssdpSock = new SSDPNotifySocket(bindAddr); + } catch (IOException ioe) { + Debug.warning("Failed announce from " + bindAddr, ioe); + return; + } SSDPNotifyRequest ssdpReq = new SSDPNotifyRequest(); ssdpReq.setServer(UPnP.getServerName()); @@ -1514,7 +1522,14 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, } public void byebye(String bindAddr) { - SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); + SSDPNotifySocket ssdpSock; + // I2P + try { + ssdpSock = new SSDPNotifySocket(bindAddr); + } catch (IOException ioe) { + Debug.warning("Failed byebye from " + bindAddr, ioe); + return; + } SSDPNotifyRequest ssdpReq = new SSDPNotifyRequest(); ssdpReq.setNTS(NTS.BYEBYE); diff --git a/router/java/src/org/cybergarage/upnp/Service.java b/router/java/src/org/cybergarage/upnp/Service.java index c598ba72e0..8752b0e946 100644 --- a/router/java/src/org/cybergarage/upnp/Service.java +++ b/router/java/src/org/cybergarage/upnp/Service.java @@ -73,6 +73,7 @@ package org.cybergarage.upnp; import java.io.File; import java.io.InputStream; +import java.io.IOException; import java.net.URL; import java.util.Iterator; @@ -662,9 +663,14 @@ public class Service ssdpReq.setNT(serviceNT); ssdpReq.setUSN(serviceUSN); - SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); - Device.notifyWait(); - ssdpSock.post(ssdpReq); + // I2P + try { + SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); + Device.notifyWait(); + ssdpSock.post(ssdpReq); + } catch (IOException ioe) { + Debug.warning("Failed announce from " + bindAddr, ioe); + } } public void byebye(String bindAddr) @@ -679,9 +685,14 @@ public class Service ssdpReq.setNT(devNT); ssdpReq.setUSN(devUSN); - SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); - Device.notifyWait(); - ssdpSock.post(ssdpReq); + // I2P + try { + SSDPNotifySocket ssdpSock = new SSDPNotifySocket(bindAddr); + Device.notifyWait(); + ssdpSock.post(ssdpReq); + } catch (IOException ioe) { + Debug.warning("Failed announce from " + bindAddr, ioe); + } } public boolean serviceSearchResponse(SSDPPacket ssdpPacket) diff --git a/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java b/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java index 34cb29aa7a..2e1fdf1f6a 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java @@ -55,6 +55,8 @@ public class HTTPMUSocket private InetSocketAddress ssdpMultiGroup = null; private MulticastSocket ssdpMultiSock = null; private NetworkInterface ssdpMultiIf = null; + /** I2P */ + private InetAddress _bindAddress; //////////////////////////////////////////////// // Constructor @@ -80,6 +82,7 @@ public class HTTPMUSocket public String getLocalAddress() { + /**** I2P fix if (ssdpMultiGroup == null || ssdpMultiIf == null) return ""; InetAddress mcastAddr = ssdpMultiGroup.getAddress(); @@ -92,6 +95,10 @@ public class HTTPMUSocket return addr.getHostAddress(); } return ""; + ****/ + if (_bindAddress == null) + return ""; + return _bindAddress.getHostAddress(); } /** @@ -151,6 +158,8 @@ public class HTTPMUSocket ssdpMultiGroup = new InetSocketAddress(InetAddress.getByName(addr), port); ssdpMultiIf = NetworkInterface.getByInetAddress(bindAddr); ssdpMultiSock.joinGroup(ssdpMultiGroup, ssdpMultiIf); + // I2P + _bindAddress = bindAddr; } catch (Exception e) { Debug.warning(e); @@ -256,5 +265,10 @@ public class HTTPMUSocket return recvPacket; } + + /** I2P */ + @Override + public String toString() { return getLocalAddress(); } + } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java b/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java index 38fb6ed3ca..ec7d3fec53 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java @@ -268,5 +268,10 @@ public class HTTPUSocket return true; } */ + + /** I2P */ + @Override + public String toString() { return localAddr; } + } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java index 104cbf8c6d..adbb3c4b94 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java @@ -54,7 +54,7 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable // Constructor //////////////////////////////////////////////// - public SSDPNotifySocket(String bindAddr) + public SSDPNotifySocket(String bindAddr) throws IOException { String addr = SSDP.ADDRESS; useIPv6Address = false; @@ -62,7 +62,9 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable addr = SSDP.getIPv6Address(); useIPv6Address = true; } - open(addr, SSDP.PORT, bindAddr); + boolean ok = open(addr, SSDP.PORT, bindAddr); + if (!ok) + throw new IOException("Bind to " + bindAddr + " failed"); Debug.message("Opened SSDP notify socket at " + bindAddr + ':' + SSDP.PORT); setControlPoint(null); } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java index a594849c88..a99f05748c 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java @@ -15,12 +15,14 @@ package org.cybergarage.upnp.ssdp; +import java.io.IOException; import java.net.InetAddress; import java.util.*; import org.cybergarage.net.*; import org.cybergarage.upnp.*; +import org.cybergarage.util.Debug; public class SSDPNotifySocketList extends Vector { @@ -86,8 +88,12 @@ public class SSDPNotifySocketList extends Vector for (int i = 0; i < bindAddresses.length; i++) { if(bindAddresses[i]!=null){ - SSDPNotifySocket ssdpNotifySocket = new SSDPNotifySocket(bindAddresses[i]); - add(ssdpNotifySocket); + try { + SSDPNotifySocket ssdpNotifySocket = new SSDPNotifySocket(bindAddresses[i]); + add(ssdpNotifySocket); + } catch (IOException ioe) { + Debug.warning("Failed bind to " + bindAddresses[i], ioe); + } } } return true; diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocket.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocket.java index 8d840c7d1d..28298c9b12 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocket.java @@ -54,8 +54,10 @@ public class SSDPSearchSocket extends HTTPMUSocket implements Runnable * @param multicast The multicast address to use as destination * @since 1.8 */ - public SSDPSearchSocket(String bindAddr,int port,String multicast){ - open(bindAddr,multicast); + public SSDPSearchSocket(String bindAddr,int port,String multicast) throws IOException { + boolean ok = open(bindAddr,multicast); + if (!ok) + throw new IOException("Bind to " + bindAddr + " failed"); } /** @@ -63,12 +65,15 @@ public class SSDPSearchSocket extends HTTPMUSocket implements Runnable * @param bindAddr the binding address for sending multicast packet * @since 1.8 */ - public SSDPSearchSocket(InetAddress bindAddr){ + public SSDPSearchSocket(InetAddress bindAddr) throws IOException { + boolean ok; if(bindAddr.getAddress().length!=4){ - this.open((Inet6Address)bindAddr); + ok = this.open((Inet6Address)bindAddr); }else{ - this.open((Inet4Address)bindAddr); + ok = this.open((Inet4Address)bindAddr); } + if (!ok) + throw new IOException("Bind to " + bindAddr + " failed"); } //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java index 298652758b..5de8432598 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java @@ -18,11 +18,13 @@ package org.cybergarage.upnp.ssdp; +import java.io.IOException; import java.net.InetAddress; import java.util.Vector; import org.cybergarage.net.HostInterface; import org.cybergarage.upnp.device.SearchListener; +import org.cybergarage.util.Debug; public class SSDPSearchSocketList extends Vector { @@ -101,12 +103,16 @@ public class SSDPSearchSocketList extends Vector for (int i = 0; i < bindAddresses.length; i++) { if(bindAddresses[i]!=null){ - SSDPSearchSocket ssdpSearchSocket; - if(HostInterface.isIPv6Address(bindAddresses[i])) - ssdpSearchSocket = new SSDPSearchSocket(bindAddresses[i],port ,multicastIPv6 ); - else - ssdpSearchSocket = new SSDPSearchSocket(bindAddresses[i],port,multicastIPv4 ); - add(ssdpSearchSocket); + try { + SSDPSearchSocket ssdpSearchSocket; + if(HostInterface.isIPv6Address(bindAddresses[i])) + ssdpSearchSocket = new SSDPSearchSocket(bindAddresses[i],port ,multicastIPv6 ); + else + ssdpSearchSocket = new SSDPSearchSocket(bindAddresses[i],port,multicastIPv4 ); + add(ssdpSearchSocket); + } catch (IOException ioe) { + Debug.warning("Failed bind to " + bindAddresses[i], ioe); + } } } return true;