From 4929a7e63514e51f852a6e96e3da8b5d8cf0bf64 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Wed, 29 Apr 2009 20:42:42 +0000
Subject: [PATCH] - Add getRequestedPort() to transports

---
 .../net/i2p/router/transport/Addresses.java   |  3 +-
 .../net/i2p/router/transport/Transport.java   |  1 +
 .../i2p/router/transport/TransportImpl.java   |  9 ++++
 .../router/transport/TransportManager.java    | 44 ++++++++++++++++---
 .../net/i2p/router/transport/UPnPManager.java | 23 +++-------
 .../router/transport/ntcp/NTCPTransport.java  |  8 ++++
 .../router/transport/udp/UDPTransport.java    | 14 +++---
 7 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/router/java/src/net/i2p/router/transport/Addresses.java b/router/java/src/net/i2p/router/transport/Addresses.java
index cd82a9086d..53278af789 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 145129651e..d7d73b77b5 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 685f6189ef..be31d35f88 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 ea3e09b82f..8e4e504052 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 ca7873903b..f402d9c07c 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 32a108ec06..21bbcdda18 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 9e4289e386..c9e4bc538b 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.
-- 
GitLab