diff --git a/router/java/src/net/i2p/router/transport/Addresses.java b/router/java/src/net/i2p/router/transport/Addresses.java index cd82a9086d5ce6a56ca6e5d39ec214e04728d6c8..53278af789d0f0c814dac871feb84ee44f8124e8 100644 --- a/router/java/src/net/i2p/router/transport/Addresses.java +++ b/router/java/src/net/i2p/router/transport/Addresses.java @@ -64,9 +64,8 @@ public class Addresses { ia.isMulticastAddress() || ia.isSiteLocalAddress() || !(ia instanceof Inet4Address)) { -///////// testing // System.err.println("Skipping: " + ia.getHostAddress()); -// return; + return; } String ip = ia.getHostAddress(); set.add(ip); diff --git a/router/java/src/net/i2p/router/transport/Transport.java b/router/java/src/net/i2p/router/transport/Transport.java index 145129651ebb622607ebca557b9b9d3c27aa3b5f..d7d73b77b55ea57682e84d2a62286f94a026ee2c 100644 --- a/router/java/src/net/i2p/router/transport/Transport.java +++ b/router/java/src/net/i2p/router/transport/Transport.java @@ -40,6 +40,7 @@ public interface Transport { public static final String SOURCE_CONFIG = "Configuration change"; public void externalAddressReceived(String source, byte[] ip, int port); public void forwardPortStatus(int port, boolean success, String reason); + public int getRequestedPort(); public void setListener(TransportEventListener listener); public String getStyle(); diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index 685f6189ef4a5e396b1f6b03f4b02bcf40db9a13..be31d35f884250eb65067b2a9f46c1aa789ff142 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -445,6 +445,15 @@ public abstract class TransportImpl implements Transport { */ public void forwardPortStatus(int port, boolean success, String reason) {} + /** + * What port would the transport like to have forwarded by UPnP. + * This can't be passed via getCurrentAddress(), as we have to open the port + * before we can publish the address. + * + * @return port or -1 for none or 0 for any + */ + public int getRequestedPort() { return -1; } + /** Who to notify on message availability */ public void setListener(TransportEventListener listener) { _listener = listener; } /** Make this stuff pretty (only used in the old console) */ diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index ea3e09b82f61b4824976dec8d311678189c7d0f9..8e4e504052a79d90d1176f9e85658aba32bc212b 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.Vector; @@ -139,6 +140,8 @@ public class TransportManager implements TransportEventListener { if (_log.shouldLog(Log.DEBUG)) _log.debug("Transport " + i + " (" + t.getStyle() + ") started"); } + // kick UPnP - Do this to get the ports opened even before UDP registers an address + transportAddressChanged(); _log.debug("Done start listening on transports"); _context.router().rebuildRouterInfo(); } @@ -285,16 +288,47 @@ public class TransportManager implements TransportEventListener { return TransportImpl.getIP(dest); } - Map getAddresses() { - Map rv = new HashMap(_transports.size()); - for (int i = 0; i < _transports.size(); i++) { - Transport t = (Transport)_transports.get(i); + public Map<String, RouterAddress> getAddresses() { + Map<String, RouterAddress> rv = new HashMap(_transports.size()); + for (Transport t : _transports) { if (t.getCurrentAddress() != null) rv.put(t.getStyle(), t.getCurrentAddress()); } return rv; } + /** + * Include the published port, or the requested port, for each transport + * which we will pass along to UPnP + */ + private Map<String, Integer> getPorts() { + Map<String, Integer> rv = new HashMap(_transports.size()); + for (Transport t : _transports) { + int port = t.getRequestedPort(); + if (t.getCurrentAddress() != null) { + Properties opts = t.getCurrentAddress().getOptions(); + if (opts != null) { + String s = opts.getProperty("port"); + if (s != null) { + try { + port = Integer.parseInt(s); + } catch (NumberFormatException nfe) {} + } + } + } + // Use UDP port for NTCP too - see comment in NTCPTransport.getRequestedPort() for why this is here + if (t.getStyle().equals(NTCPTransport.STYLE) && port <= 0 && + Boolean.valueOf(_context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)).booleanValue()) { + Transport udp = getTransport(UDPTransport.STYLE); + if (udp != null) + port = t.getRequestedPort(); + } + if (port > 0) + rv.put(t.getStyle(), Integer.valueOf(port)); + } + return rv; + } + public TransportBid getBid(OutNetMessage msg) { List bids = getBids(msg); if ( (bids == null) || (bids.size() <= 0) ) @@ -399,7 +433,7 @@ public class TransportManager implements TransportEventListener { public void transportAddressChanged() { if (_upnpManager != null) - _upnpManager.update(getAddresses()); + _upnpManager.update(getPorts()); } public List getMostRecentErrorMessages() { diff --git a/router/java/src/net/i2p/router/transport/UPnPManager.java b/router/java/src/net/i2p/router/transport/UPnPManager.java index ca7873903b0cae11a89c9418ec0878f1ff7ec06c..f402d9c07c10725537c5063eb583a3ba4930c0b7 100644 --- a/router/java/src/net/i2p/router/transport/UPnPManager.java +++ b/router/java/src/net/i2p/router/transport/UPnPManager.java @@ -7,7 +7,6 @@ package net.i2p.router.transport; import java.net.InetAddress; import java.util.HashSet; import java.util.Map; -import java.util.Properties; import java.util.Set; import net.i2p.data.RouterAddress; @@ -66,26 +65,14 @@ public class UPnPManager { } /** call when the ports might have changed */ - public void update(Map<String, RouterAddress> addresses) { + public void update(Map<String, Integer> ports) { if (_log.shouldLog(Log.DEBUG)) _log.debug("UPnP Update:"); if (!_isRunning) return; - Set<ForwardPort> forwards = new HashSet(addresses.size()); - for (String style : addresses.keySet()) { - RouterAddress ra = addresses.get(style); - if (ra == null) - continue; - Properties opts = ra.getOptions(); - if (opts == null) - continue; - String s = opts.getProperty("port"); - if (s == null) - continue; - int port = -1; - try { - port = Integer.parseInt(s); - } catch (NumberFormatException nfe) { continue; } + Set<ForwardPort> forwards = new HashSet(ports.size()); + for (String style : ports.keySet()) { + int port = ports.get(style).intValue(); int protocol = -1; if ("SSU".equals(style)) protocol = ForwardPort.PROTOCOL_UDP_IPV4; @@ -144,7 +131,7 @@ public class UPnPManager { style = "NTCP"; else continue; - boolean success = fps.status >= ForwardPortStatus.PROBABLE_SUCCESS; + boolean success = fps.status >= ForwardPortStatus.MAYBE_SUCCESS; _manager.forwardPortStatus(style, fp.portNumber, success, fps.reasonString); } } diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java index 32a108ec0656a4caac32dc852905cb38d49aa74e..21bbcdda1836be7c2d8a8ea64577a06e4e051bdf 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java @@ -552,6 +552,14 @@ public class NTCPTransport extends TransportImpl { } } + public int getRequestedPort() { + // would be nice to do this here but we can't easily get to the UDP transport.getRequested_Port() + // from here, so we do it in TransportManager. + // if (Boolean.valueOf(_context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)).booleanValue()) + // return foo; + return _context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_PORT, -1); + } + /** * This doesn't (completely) block, caller should check isAlive() * before calling startListening() or restartListening() diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 9e4289e38672a3b090e7e15d596258c61f9c5953..c9e4bc538b2ed67be7f9ef9bd567c8bdd3edc61d 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -217,13 +217,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (_externalListenPort <= 0) { // no explicit external port, so lets try an internal one port = _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT); - if (port <= 0) { - port = DEFAULT_INTERNAL_PORT; - //port = 1024 + _context.random().nextInt(31*1024); - //if (_log.shouldLog(Log.INFO)) - // _log.info("Selecting an arbitrary port to bind to: " + port); - _context.router().setConfigSetting(PROP_INTERNAL_PORT, port+""); - } // attempt to use it as our external port - this will be overridden by // externalAddressReceived(...) _context.router().setConfigSetting(PROP_EXTERNAL_PORT, port+""); @@ -314,7 +307,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority public int getLocalPort() { return _externalListenPort; } public InetAddress getLocalAddress() { return _externalListenHost; } public int getExternalPort() { return _externalListenPort; } - + public int getRequestedPort() { + if (_externalListenPort > 0) + return _externalListenPort; + return _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT); + } + /** * If we have received an inbound connection in the last 2 minutes, don't allow * our IP to change.