Author: toad
Date: 2007-06-29 23:35:54 +0000 (Fri, 29 Jun 2007)
New Revision: 13837

Added:
   trunk/freenet/src/freenet/node/NodeIPPortDetector.java
Modified:
   trunk/freenet/src/freenet/node/FNPPacketMangler.java
   trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeARKInserter.java
   trunk/freenet/src/freenet/node/NodeCrypto.java
   trunk/freenet/src/freenet/node/NodeCryptoConfig.java
   trunk/freenet/src/freenet/node/NodeIPDetector.java
   trunk/freenet/src/freenet/node/OutgoingPacketMangler.java
   trunk/freenet/src/freenet/node/PeerNode.java
Log:
Lots more refactoring:
- Peer detection split into global address detection and port (NodeCrypto) - 
specific peer detection
- Opennet refs should now therefore include the correct port
- ARKs are inserted for both opennet and darknet

Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-06-29 
23:14:12 UTC (rev 13836)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-06-29 
23:35:54 UTC (rev 13837)
@@ -1558,4 +1558,8 @@
        public SocketHandler getSocketHandler() {
                return sock;
        }
+
+       public Peer[] getPrimaryIPAddress() {
+               return crypto.detector.getPrimaryPeers();
+       }
 }

Modified: trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
===================================================================
--- trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2007-06-29 
23:14:12 UTC (rev 13836)
+++ trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2007-06-29 
23:35:54 UTC (rev 13837)
@@ -4,6 +4,7 @@
 import java.util.HashSet;
 import java.util.Vector;

+import freenet.io.comm.FreenetInetAddress;
 import freenet.io.comm.Peer;
 import freenet.l10n.L10n;
 import freenet.node.useralerts.ProxyUserAlert;
@@ -239,7 +240,7 @@
                if(logMINOR) Logger.minor(this, "Maybe running IP detection 
plugins", new Exception("debug"));
                PeerNode[] peers = node.getPeerNodes();
                PeerNode[] conns = node.getConnectedPeers();
-               Peer[] nodeAddrs = detector.getPrimaryIPAddress();
+               FreenetInetAddress[] nodeAddrs = detector.getPrimaryIPAddress();
                long now = System.currentTimeMillis();
                synchronized(this) {
                        if(plugins.length == 0) {
@@ -407,7 +408,7 @@
         * @param nodeAddrs Our peers' addresses.
         * @return True if we should run a detection.
         */
-       private boolean shouldDetectDespiteRealIP(long now, PeerNode[] peers, 
Peer[] nodeAddrs) {
+       private boolean shouldDetectDespiteRealIP(long now, PeerNode[] peers, 
FreenetInetAddress[] nodeAddrs) {
                // We might still be firewalled?
                // First, check only once per day or startup
                if(now - lastDetectAttemptEndedTime < 12*60*60*1000) {
@@ -432,7 +433,7 @@
                                                // Is it internal?
                                                boolean internal = false;
                                                for(int 
j=0;j<nodeAddrs.length;j++) {
-                                                       
if(addr.equals(nodeAddrs[j].getAddress())) {
+                                                       
if(addr.equals(nodeAddrs[j])) {
                                                                // Internal
                                                                internal = true;
                                                                break;

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2007-06-29 23:14:12 UTC (rev 
13836)
+++ trunk/freenet/src/freenet/node/Node.java    2007-06-29 23:35:54 UTC (rev 
13837)
@@ -598,6 +598,10 @@

                usm = new MessageCore();

+               // FIXME maybe these configs should actually be under a node.ip 
subconfig?
+               ipDetector = new NodeIPDetector(this);
+               sortOrder = ipDetector.registerConfigs(nodeConfig, sortOrder);
+               
                // Determine the port number

                NodeCryptoConfig darknetConfig = new 
NodeCryptoConfig(nodeConfig, sortOrder++);
@@ -607,9 +611,6 @@
                // Must be created after darknetCrypto
                dnsr = new DNSRequester(this);
                ps = new PacketSender(this);
-               // FIXME maybe these configs should actually be under a node.ip 
subconfig?
-               ipDetector = new NodeIPDetector(this, darknetCrypto);
-               sortOrder = ipDetector.registerConfigs(nodeConfig, sortOrder);

                Logger.normal(Node.class, "Creating node...");

@@ -2587,4 +2588,17 @@
        public SimpleFieldSet exportDarknetPrivateFieldSet() {
                return darknetCrypto.exportPrivateFieldSet();
        }
+
+       /**
+        * Should the IP detection code only use the IP address override and 
the bindTo information,
+        * rather than doing a full detection?
+        */
+       public synchronized boolean dontDetect() {
+               // Only return true if bindTo is set on all ports which are in 
use
+               if(!darknetCrypto.bindto.isRealInternetAddress(false, true)) 
return false;
+               if(opennet != null) {
+                       if(opennet.crypto.bindto.isRealInternetAddress(false, 
true)) return false;
+               }
+               return true;
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodeARKInserter.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeARKInserter.java 2007-06-29 23:14:12 UTC 
(rev 13836)
+++ trunk/freenet/src/freenet/node/NodeARKInserter.java 2007-06-29 23:35:54 UTC 
(rev 13837)
@@ -30,14 +30,14 @@
         */
        private final Node node;
        private final NodeCrypto crypto;
-       private final NodeIPDetector detector;
+       private final NodeIPPortDetector detector;
        private static boolean logMINOR;

        /**
         * @param node
         * @param old If true, use the old ARK rather than the new ARK
         */
-       NodeARKInserter(Node node, NodeCrypto crypto, NodeIPDetector detector) {
+       NodeARKInserter(Node node, NodeCrypto crypto, NodeIPPortDetector 
detector) {
                this.node = node;
                this.crypto = crypto;
                this.detector = detector;
@@ -82,7 +82,7 @@
        }

        private boolean checkIPUpdated() {
-               Peer[] p = detector.getPrimaryIPAddress();
+               Peer[] p = detector.detectPrimaryPeers();
                if(p == null) {
                        if(logMINOR) Logger.minor(this, "Not inserting because 
no IP address");
                        return false; // no point inserting

Modified: trunk/freenet/src/freenet/node/NodeCrypto.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCrypto.java      2007-06-29 23:14:12 UTC 
(rev 13836)
+++ trunk/freenet/src/freenet/node/NodeCrypto.java      2007-06-29 23:35:54 UTC 
(rev 13837)
@@ -23,6 +23,7 @@
 import freenet.crypt.Global;
 import freenet.crypt.RandomSource;
 import freenet.crypt.SHA256;
+import freenet.io.comm.FreenetInetAddress;
 import freenet.io.comm.Peer;
 import freenet.io.comm.UdpSocketHandler;
 import freenet.keys.FreenetURI;
@@ -45,7 +46,7 @@
        /** The object which handles our specific UDP port, pulls messages from 
it, feeds them to the packet mangler for decryption etc */
        UdpSocketHandler socket;
        public FNPPacketMangler packetMangler;
-       final InetAddress bindto;
+       final FreenetInetAddress bindto;
        // FIXME: abstract out address stuff? Possibly to something like 
NodeReference?
        final int portNumber;
        byte[] myIdentity; // FIXME: simple identity block; should be unique
@@ -65,6 +66,7 @@
        long myARKNumber;
        static boolean logMINOR;
        final NodeCryptoConfig config;
+       final NodeIPPortDetector detector;

        // Noderef related
        /** The signature of the above fieldset */
@@ -103,7 +105,7 @@
                        for(int i=0;i<200000;i++) {
                                int portNo = 1024 + random.nextInt(65535-1024);
                                try {
-                                       u = new UdpSocketHandler(portNo, 
bindto, node);
+                                       u = new UdpSocketHandler(portNo, 
bindto.getAddress(), node);
                                        port = u.getPortNumber();
                                        break;
                                } catch (Exception e) {
@@ -117,7 +119,7 @@
                                throw new 
NodeInitException(NodeInitException.EXIT_NO_AVAILABLE_UDP_PORTS, "Could not 
find an available UDP port number for FNP (none specified)");
                } else {
                        try {
-                               u = new UdpSocketHandler(port, bindto, node);
+                               u = new UdpSocketHandler(port, 
bindto.getAddress(), node);
                        } catch (Exception e) {
                                throw new 
NodeInitException(NodeInitException.EXIT_IMPOSSIBLE_USM_PORT, "Could not bind 
to port: "+port+" (node already running?)");
                        }
@@ -132,6 +134,9 @@
                
((UdpSocketHandler)socket).setDropProbability(config.getDropProbability());

                socket.setLowLevelFilter(packetMangler = new 
FNPPacketMangler(node, this, socket));
+               
+               detector = new NodeIPPortDetector(node, node.ipDetector, this);
+               
                } catch (NodeInitException e) {
                        config.stopping(this);
                        throw e;
@@ -255,7 +260,7 @@
        SimpleFieldSet exportPublicFieldSet(boolean forSetup) {
                SimpleFieldSet fs = exportPublicCryptoFieldSet(forSetup);
                // IP addresses
-               Peer[] ips = node.ipDetector.getPrimaryIPAddress();
+               Peer[] ips = detector.detectPrimaryPeers();
                if(ips != null) {
                        for(int i=0;i<ips.length;i++)
                                fs.putAppend("physical.udp", 
ips[i].toString()); // Keep; important that node know all our IPs
@@ -376,5 +381,13 @@
                socket.close(true);
                config.stopping(this);
        }
+
+       public PeerNode[] getPeerNodes() {
+               if(node.peers == null) return null;
+               if(isOpennet)
+                       return node.peers.getOpennetPeers();
+               else
+                       return node.peers.getDarknetPeers();
+       }

 }

Modified: trunk/freenet/src/freenet/node/NodeCryptoConfig.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2007-06-29 
23:14:12 UTC (rev 13836)
+++ trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2007-06-29 
23:35:54 UTC (rev 13837)
@@ -3,7 +3,6 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

-import java.net.InetAddress;
 import java.net.UnknownHostException;

 import freenet.config.InvalidConfigValueException;
@@ -26,7 +25,7 @@
        private int portNumber;

        /** Bind address. 0.0.0.0 = all addresses. */
-       private InetAddress bindTo;
+       private FreenetInetAddress bindTo;

        /** If nonzero, 1/dropProbability = probability of UdpSocketHandler 
dropping a packet (for debugging
         * purposes; not static as we may need to simulate some nodes with more 
loss than others). */
@@ -79,7 +78,8 @@
                config.register("bindTo", "0.0.0.0", sortOrder++, true, true, 
"Node.bindTo", "Node.bindToLong", new NodeBindtoCallback());

                try {
-                       bindTo = 
InetAddress.getByName(config.getString("bindTo"));
+                       bindTo = new 
FreenetInetAddress(config.getString("bindTo"), false);
+                       
                } catch (UnknownHostException e) {
                        throw new 
NodeInitException(NodeInitException.EXIT_COULD_NOT_BIND_USM, "Invalid bindTo: 
"+config.getString("bindTo"));
                }
@@ -137,7 +137,7 @@
        class NodeBindtoCallback implements StringCallback {

                public String get() {
-                       return FreenetInetAddress.getHostName(bindTo);
+                       return bindTo.toString();
                }

                public void set(String val) throws InvalidConfigValueException {
@@ -147,7 +147,7 @@
                }
        }

-       public InetAddress getBindTo() {
+       public FreenetInetAddress getBindTo() {
                return bindTo;
        }


Modified: trunk/freenet/src/freenet/node/NodeIPDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPDetector.java  2007-06-29 23:14:12 UTC 
(rev 13836)
+++ trunk/freenet/src/freenet/node/NodeIPDetector.java  2007-06-29 23:35:54 UTC 
(rev 13837)
@@ -11,7 +11,6 @@
 import freenet.config.SubConfig;
 import freenet.io.comm.FreenetInetAddress;
 import freenet.io.comm.Peer;
-import freenet.io.comm.UdpSocketHandler;
 import freenet.l10n.L10n;
 import freenet.node.useralerts.IPUndetectedUserAlert;
 import freenet.node.useralerts.SimpleUserAlert;
@@ -24,11 +23,14 @@
 import freenet.support.transport.ip.IPAddressDetector;
 import freenet.support.transport.ip.IPUtil;

+/**
+ * Detect the IP address of the node. Doesn't return port numbers, doesn't 
have access to per-port
+ * information (NodeCrypto - UdpSocketHandler etc).
+ */
 public class NodeIPDetector {

        /** Parent node */
        final Node node;
-       final NodeCrypto crypto;
        /** Ticker */
        final Ticker ticker;
        /** Explicit forced IP address */
@@ -38,70 +40,68 @@
        /** Detected IP's and their NAT status from plugins */
        DetectedIP[] pluginDetectedIPs;
        /** Last detected IP address */
-       Peer[] lastIPAddress;
+       FreenetInetAddress[] lastIPAddress;
        /** The minimum reported MTU on all detected interfaces */
        private int minimumMTU;
        /** IP address detector */
        private final IPAddressDetector ipDetector;
        /** Plugin manager for plugin IP address detectors e.g. STUN */
-       private final IPDetectorPluginManager ipDetectorManager;
+       final IPDetectorPluginManager ipDetectorManager;
        /** UserAlert shown when we can't detect an IP address */
        private static IPUndetectedUserAlert primaryIPUndetectedAlert;
        // FIXME redundant? see lastIPAddress
-       Peer[] lastIP;
+       FreenetInetAddress[] lastIP;
        /** If true, include local addresses on noderefs */
        public boolean includeLocalAddressesInNoderefs;
-       /** ARK inserter. */
-       private final NodeARKInserter arkPutter;
        /** Set when we have grounds to believe that we may be behind a 
symmetric NAT. */
        boolean maybeSymmetric;
        private boolean hasDetectedPM;
        private boolean hasDetectedIAD;
+       /** Subsidiary detectors: NodeIPPortDetector's which rely on this 
object */
+       private NodeIPPortDetector[] portDetectors;

        SimpleUserAlert maybeSymmetricAlert;

-       public NodeIPDetector(Node node, NodeCrypto crypto) {
+       public NodeIPDetector(Node node) {
                this.node = node;
-               this.crypto = crypto;
                this.ticker = node.ps;
                ipDetectorManager = new IPDetectorPluginManager(node, this);
                ipDetector = new IPAddressDetector(10*1000, this);
                primaryIPUndetectedAlert = new IPUndetectedUserAlert(node);
-               arkPutter = new NodeARKInserter(node, crypto, this);
+               portDetectors = new NodeIPPortDetector[0];
        }

+       public synchronized void addPortDetector(NodeIPPortDetector detector) {
+               NodeIPPortDetector[] newDetectors = new 
NodeIPPortDetector[portDetectors.length+1];
+               System.arraycopy(portDetectors, 0, newDetectors, 0, 
portDetectors.length);
+               newDetectors[portDetectors.length] = detector;
+               portDetectors = newDetectors;
+       }
+       
        /**
-        * @return Our current main IP address.
-        * FIXME - we should support more than 1, and we should do the
-        * detection properly with NetworkInterface, and we should use
-        * third parties if available and UP&P if available.
+        * What is my IP address? Use all globally available information 
(everything which isn't
+        * specific to a given port i.e. opennet or darknet) to determine our 
current IP addresses.
+        * Will include more than one IP in many cases when we are not strictly 
multi-homed. For 
+        * example, if we have a DNS name set, we will usually return an IP as 
well; if we are 
+        * behind a NAT we may return both a rewritten port number and the 
original; etc.
+        * 
+        * Will warn the user with a UserAlert if we don't have sufficient 
information.
         */
-       Peer[] detectPrimaryIPAddress() {
+       FreenetInetAddress[] detectPrimaryIPAddress() {
                boolean addedValidIP = false;
-               int portNumber = crypto.portNumber;
                Logger.minor(this, "Redetecting IPs...");
                Vector addresses = new Vector();
                if(overrideIPAddress != null) {
                        // If the IP is overridden, the override has to be the 
first element.
-                       Peer p = new Peer(overrideIPAddress, portNumber);
-                       addresses.add(p);
-                       if(p.getFreenetAddress().isRealInternetAddress(false, 
true))
+                       addresses.add(overrideIPAddress);
+                       if(overrideIPAddress.isRealInternetAddress(false, true))
                                addedValidIP = true;
                }
-               boolean dontDetect = false;
-               UdpSocketHandler sock = crypto.socket;
-               if(sock != null) {
-                       InetAddress addr = sock.getBindTo();
-                       if(addr != null && (IPUtil.isValidAddress(addr, 
false))) {
-                               dontDetect = true;
-                               Peer p = new Peer(addr, portNumber);
-                               if(!addresses.contains(p)) addresses.add(p);
-                               dontDetect = true;
-                       }
+               
+               if(!node.dontDetect()) {
+                       addedValidIP |= innerDetect(addresses);
                }
-               if(!dontDetect) {
-                       addedValidIP = innerDetect(addresses, addedValidIP, 
portNumber);
-               }
+               
                if(node.clientCore != null) {
                        if (addedValidIP) {
                                
node.clientCore.alerts.unregister(primaryIPUndetectedAlert);
@@ -109,24 +109,29 @@
                                
node.clientCore.alerts.register(primaryIPUndetectedAlert);
                        }
                }
-               lastIPAddress = (Peer[]) addresses.toArray(new 
Peer[addresses.size()]);
+               lastIPAddress = (FreenetInetAddress[]) addresses.toArray(new 
FreenetInetAddress[addresses.size()]);
                return lastIPAddress;
        }

-       private boolean innerDetect(Vector addresses, boolean addedValidIP, int 
portNumber) {
-               boolean setMaybeSymmetric = false;
+       /**
+        * Core of the IP detection algorithm.
+        * @param addresses
+        * @param addedValidIP
+        * @return
+        */
+       private boolean innerDetect(Vector addresses) {
+               boolean addedValidIP = false;
                InetAddress[] detectedAddrs = ipDetector.getAddress();
                assert(detectedAddrs != null);
                synchronized(this) {
                        hasDetectedIAD = true;
                }
-               
                for(int i=0;i<detectedAddrs.length;i++) {
-                       Peer p = new Peer(detectedAddrs[i], portNumber);
-                       if(!addresses.contains(p)) {
-                               Logger.normal(this, "Detected IP address: "+p);
-                               addresses.add(p);
-                               
if(p.getFreenetAddress().isRealInternetAddress(false, false))
+                       FreenetInetAddress addr = new 
FreenetInetAddress(detectedAddrs[i]);
+                       if(!addresses.contains(addr)) {
+                               Logger.normal(this, "Detected IP address: 
"+addr);
+                               addresses.add(addr);
+                               if(addr.isRealInternetAddress(false, false))
                                        addedValidIP = true;
                        }
                }
@@ -135,7 +140,7 @@
                        for(int i=0;i<pluginDetectedIPs.length;i++) {
                                InetAddress addr = 
pluginDetectedIPs[i].publicAddress;
                                if(addr == null) continue;
-                               Peer a = new Peer(new FreenetInetAddress(addr), 
portNumber);
+                               FreenetInetAddress a = new 
FreenetInetAddress(addr);
                                if(!addresses.contains(a)) {
                                        Logger.normal(this, "Plugin detected IP 
address: "+a);
                                        addresses.add(a);
@@ -143,8 +148,10 @@
                                }
                        }
                }
+               
                if(addresses.isEmpty() && (oldIPAddress != null) && 
!oldIPAddress.equals(overrideIPAddress))
-                       addresses.add(new Peer(oldIPAddress, portNumber));
+                       addresses.add(oldIPAddress);
+               
                // Try to pick it up from our connections
                if(node.peers != null) {
                        PeerNode[] peerList = node.peers.connectedPeers;
@@ -152,36 +159,38 @@
                        // FIXME use a standard mutable int object, we have one 
somewhere
                        for(int i=0;i<peerList.length;i++) {
                                Peer p = peerList[i].getRemoteDetectedPeer();
-                               if((p == null) || p.isNull()) continue;
+                               if(p == null || p.isNull()) continue;
+                               FreenetInetAddress addr = p.getFreenetAddress();
+                               if(addr == null) continue;
                                // DNSRequester doesn't deal with our own node
-                               if(!IPUtil.isValidAddress(p.getAddress(true), 
false)) continue;
-                               Logger.normal(this, "Peer 
"+peerList[i].getPeer()+" thinks we are "+p);
-                               if(countsByPeer.containsKey(p)) {
-                                       Integer count = (Integer) 
countsByPeer.get(p);
+                               
if(!IPUtil.isValidAddress(addr.getAddress(false), false)) continue;
+                               Logger.normal(this, "Peer 
"+peerList[i].getPeer()+" thinks we are "+addr);
+                               if(countsByPeer.containsKey(addr)) {
+                                       Integer count = (Integer) 
countsByPeer.get(addr);
                                        Integer newCount = new 
Integer(count.intValue()+1);
-                                       countsByPeer.put(p, newCount);
+                                       countsByPeer.put(addr, newCount);
                                } else {
-                                       countsByPeer.put(p, new Integer(1));
+                                       countsByPeer.put(addr, new Integer(1));
                                }
                        }
                        if(countsByPeer.size() == 1) {
                                Iterator it = countsByPeer.keySet().iterator();
-                               Peer p = (Peer) (it.next());
-                               Logger.minor(this, "Everyone agrees we are "+p);
-                               if(!addresses.contains(p)) {
-                                       
if(p.getFreenetAddress().isRealInternetAddress(false, false))
+                               FreenetInetAddress addr = (FreenetInetAddress) 
(it.next());
+                               Logger.minor(this, "Everyone agrees we are 
"+addr);
+                               if(!addresses.contains(addr)) {
+                                       if(addr.isRealInternetAddress(false, 
false))
                                                addedValidIP = true;
-                                       addresses.add(p);
+                                       addresses.add(addr);
                                }
                        } else if(countsByPeer.size() > 1) {
                                Iterator it = countsByPeer.keySet().iterator();
                                // Take two most popular addresses.
-                               Peer best = null;
-                               Peer secondBest = null;
+                               FreenetInetAddress best = null;
+                               FreenetInetAddress secondBest = null;
                                int bestPopularity = 0;
                                int secondBestPopularity = 0;
                                while(it.hasNext()) {
-                                       Peer cur = (Peer) (it.next());
+                                       FreenetInetAddress cur = 
(FreenetInetAddress) (it.next());
                                        int curPop = ((Integer) 
(countsByPeer.get(cur))).intValue();
                                        Logger.normal(this, "Detected peer: 
"+cur+" popularity "+curPop);
                                        if(curPop >= bestPopularity) {
@@ -196,46 +205,24 @@
                                                if(!addresses.contains(best)) {
                                                        Logger.normal(this, 
"Adding best peer "+best+" ("+bestPopularity+ ')');
                                                        addresses.add(best);
-                                                       
if(best.getFreenetAddress().isRealInternetAddress(false, false))
+                                                       
if(best.isRealInternetAddress(false, false))
                                                                addedValidIP = 
true;
                                                }
                                                if((secondBest != null) && 
(secondBestPopularity > 1)) {
                                                        
if(!addresses.contains(secondBest)) {
                                                                
Logger.normal(this, "Adding second best peer "+secondBest+" ("+secondBest+ ')');
                                                                
addresses.add(secondBest);
-                                                               
if(secondBest.getFreenetAddress().isRealInternetAddress(false, false))
+                                                               
if(secondBest.isRealInternetAddress(false, false))
                                                                        
addedValidIP = true;
                                                        }
-                                                       
if(best.getAddress().equals(secondBest.getAddress()) && bestPopularity == 1) {
-                                                               
Logger.error(this, "Hrrrm, maybe this is a symmetric NAT? Expect trouble 
connecting!");
-                                                               
System.err.println("Hrrrm, maybe this is a symmetric NAT? Expect trouble 
connecting!");
-                                                               
setMaybeSymmetric = true;
-                                                               
-                                                               
if(ipDetectorManager != null && ipDetectorManager.isEmpty()) {
-                                                                       
if(maybeSymmetricAlert == null) {
-                                                                               
maybeSymmetricAlert = new SimpleUserAlert(true, l10n("maybeSymmetricTitle"), 
-                                                                               
                l10n("maybeSymmetric"), UserAlert.ERROR);
-                                                                       }
-                                                                       
if(node.clientCore != null && node.clientCore.alerts != null)
-                                                                               
node.clientCore.alerts.register(maybeSymmetricAlert);
-                                                               } else {
-                                                                       
if(maybeSymmetricAlert != null)
-                                                                               
node.clientCore.alerts.unregister(maybeSymmetricAlert);
-                                                               }
-                                                               
-                                                               Peer p = new 
Peer(best.getFreenetAddress(), portNumber);
-                                                               
if(!addresses.contains(p))
-                                                                       
addresses.add(p);
-                                                       }
                                                }
                                        }
                                }
                        }
                }
-               this.maybeSymmetric = setMaybeSymmetric;
                return addedValidIP;
        }
-
+       
        private String l10n(String key) {
                return L10n.getString("NodeIPDetector."+key);
        }
@@ -244,7 +231,7 @@
                return L10n.getString("NodeIPDetector."+key, pattern, value);
        }

-       Peer[] getPrimaryIPAddress() {
+       FreenetInetAddress[] getPrimaryIPAddress() {
                if(lastIPAddress == null) return detectPrimaryIPAddress();
                return lastIPAddress;
        }
@@ -277,16 +264,18 @@
                        }
                }
                redetectAddress();
-               arkPutter.update();
        }

        public void redetectAddress() {
-               Peer[] newIP = detectPrimaryIPAddress();
+               FreenetInetAddress[] newIP = detectPrimaryIPAddress();
+               NodeIPPortDetector[] detectors;
                synchronized(this) {
                        if(Arrays.equals(newIP, lastIP)) return;
                        lastIP = newIP;
+                       detectors = portDetectors;
                }
-               arkPutter.update();
+               for(int i=0;i<detectors.length;i++)
+                       detectors[i].update();
                node.writeNodeFile();
        }

@@ -411,7 +400,12 @@
                // 60 second delay for inserting ARK to avoid reinserting more 
than necessary if we don't detect IP on startup.
                ticker.queueTimedJob(new FastRunnable() {
                        public void run() {
-                               arkPutter.start();
+                               NodeIPPortDetector[] detectors;
+                               synchronized(this) {
+                                       detectors = portDetectors;
+                               }
+                               for(int i=0;i<detectors.length;i++)
+                                       detectors[i].startARK();
                        }
                }, 60*1000);
        }
@@ -437,5 +431,19 @@
        public int getMinimumDetectedMTU() {
                return minimumMTU > 0 ? minimumMTU : 1500;
        }
+
+       public void setMaybeSymmetric() {
+               if(ipDetectorManager != null && ipDetectorManager.isEmpty()) {
+                       if(maybeSymmetricAlert == null) {
+                               maybeSymmetricAlert = new SimpleUserAlert(true, 
l10n("maybeSymmetricTitle"), 
+                                               l10n("maybeSymmetric"), 
UserAlert.ERROR);
+                       }
+                       if(node.clientCore != null && node.clientCore.alerts != 
null)
+                               
node.clientCore.alerts.register(maybeSymmetricAlert);
+               } else {
+                       if(maybeSymmetricAlert != null)
+                               
node.clientCore.alerts.unregister(maybeSymmetricAlert);
+               }
+       }

 }

Added: trunk/freenet/src/freenet/node/NodeIPPortDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPPortDetector.java                      
        (rev 0)
+++ trunk/freenet/src/freenet/node/NodeIPPortDetector.java      2007-06-29 
23:35:54 UTC (rev 13837)
@@ -0,0 +1,156 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Vector;
+
+import freenet.io.comm.FreenetInetAddress;
+import freenet.io.comm.Peer;
+import freenet.support.Logger;
+import freenet.support.transport.ip.IPUtil;
+
+/**
+ * Combine the detected IP address with the NodeCrypto's port number and the 
port numbers we have
+ * on connections in the given class to get a list of Peer's.
+ * @author toad
+ */
+public class NodeIPPortDetector {
+
+       /** The Node object */
+       final Node node;
+       /** The NodeIPDetector which determines the node's IP address but not 
its port number */
+       final NodeIPDetector ipDetector;
+       /** The NodeCrypto with the node's port number */
+       final NodeCrypto crypto;
+       /** ARK inserter. */
+       private final NodeARKInserter arkPutter;
+       /** Last detected IP address */
+       Peer[] lastPeers;
+       
+       NodeIPPortDetector(Node node, NodeIPDetector ipDetector, NodeCrypto 
crypto) {
+               this.node = node;
+               this.ipDetector = ipDetector;
+               this.crypto = crypto;
+               arkPutter = new NodeARKInserter(node, crypto, this);
+       }
+
+       /**
+        * Combine the NodeIPDetector's output with any per-port information we 
may have to get a definitive
+        * (for that port/NodeCrypto) list of IP addresses (still without port 
numbers).
+        */
+       FreenetInetAddress[] detectPrimaryIPAddress() {
+               FreenetInetAddress[] addresses = 
ipDetector.detectPrimaryIPAddress();
+               FreenetInetAddress addr = crypto.bindto;
+               if(addr.isRealInternetAddress(false, true)) {
+                       for(int i=0;i<addresses.length;i++) {
+                               if(addresses[i] == addr) return addresses;
+                       }
+                       FreenetInetAddress[] newAddresses = new 
FreenetInetAddress[addresses.length+1];
+                       System.arraycopy(addresses, 0, newAddresses, 0, 
addresses.length);
+                       return newAddresses;
+               }
+               return addresses;
+       }
+
+       Peer[] detectPrimaryPeers() {
+               Vector addresses = new Vector();
+               FreenetInetAddress[] addrs = detectPrimaryIPAddress();
+               for(int i=0;i<addrs.length;i++) {
+                       addresses.add(new Peer(addrs[i], crypto.portNumber));
+               }
+               // Now try to get the rewritten port number from our peers.
+               // Only considering those within this crypto port, this time.
+               
+               PeerNode[] peerList = crypto.getPeerNodes();
+               
+               if(peerList != null) {
+                       HashMap countsByPeer = new HashMap();
+                       // FIXME use a standard mutable int object, we have one 
somewhere
+                       for(int i=0;i<peerList.length;i++) {
+                               Peer p = peerList[i].getRemoteDetectedPeer();
+                               if((p == null) || p.isNull()) continue;
+                               // DNSRequester doesn't deal with our own node
+                               if(!IPUtil.isValidAddress(p.getAddress(true), 
false)) continue;
+                               Logger.normal(this, "Peer 
"+peerList[i].getPeer()+" thinks we are "+p);
+                               if(countsByPeer.containsKey(p)) {
+                                       Integer count = (Integer) 
countsByPeer.get(p);
+                                       Integer newCount = new 
Integer(count.intValue()+1);
+                                       countsByPeer.put(p, newCount);
+                               } else {
+                                       countsByPeer.put(p, new Integer(1));
+                               }
+                       }
+                       if(countsByPeer.size() == 1) {
+                               Iterator it = countsByPeer.keySet().iterator();
+                               Peer p = (Peer) (it.next());
+                               Logger.minor(this, "Everyone agrees we are "+p);
+                               if(!addresses.contains(p)) {
+                                       addresses.add(p);
+                               }
+                       } else if(countsByPeer.size() > 1) {
+                               Iterator it = countsByPeer.keySet().iterator();
+                               // Take two most popular addresses.
+                               Peer best = null;
+                               Peer secondBest = null;
+                               int bestPopularity = 0;
+                               int secondBestPopularity = 0;
+                               while(it.hasNext()) {
+                                       Peer cur = (Peer) (it.next());
+                                       int curPop = ((Integer) 
(countsByPeer.get(cur))).intValue();
+                                       Logger.normal(this, "Detected peer: 
"+cur+" popularity "+curPop);
+                                       if(curPop >= bestPopularity) {
+                                               secondBestPopularity = 
bestPopularity;
+                                               bestPopularity = curPop;
+                                               secondBest = best;
+                                               best = cur;
+                                       }
+                               }
+                               if(best != null) {
+                                       if((bestPopularity > 1) || 
(addrs.length == 0)) {
+                                               if(!addresses.contains(best)) {
+                                                       Logger.normal(this, 
"Adding best peer "+best+" ("+bestPopularity+ ')');
+                                                       addresses.add(best);
+                                               }
+                                               if((secondBest != null) && 
(secondBestPopularity > 1)) {
+                                                       
if(!addresses.contains(secondBest)) {
+                                                               
Logger.normal(this, "Adding second best peer "+secondBest+" ("+secondBest+ ')');
+                                                               
addresses.add(secondBest);
+                                                       }
+                                                       
if(best.getAddress().equals(secondBest.getAddress()) && bestPopularity == 1) {
+                                                               
Logger.error(this, "Hrrrm, maybe this is a symmetric NAT? Expect trouble 
connecting!");
+                                                               
System.err.println("Hrrrm, maybe this is a symmetric NAT? Expect trouble 
connecting!");
+                                                               
+                                                               
ipDetector.setMaybeSymmetric();
+                                                               
+                                                               Peer p = new 
Peer(best.getFreenetAddress(), crypto.portNumber);
+                                                               
if(!addresses.contains(p))
+                                                                       
addresses.add(p);
+
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               lastPeers = (Peer[]) addresses.toArray(new 
Peer[addresses.size()]);
+               return lastPeers;
+       }
+       
+       void update() {
+               arkPutter.update();
+       }
+
+       void startARK() {
+               arkPutter.start();
+       }
+
+       public Peer[] getPrimaryPeers() {
+               if(lastPeers == null)
+                       return detectPrimaryPeers();
+               else
+                       return lastPeers;
+       }
+}

Modified: trunk/freenet/src/freenet/node/OutgoingPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/OutgoingPacketMangler.java   2007-06-29 
23:14:12 UTC (rev 13836)
+++ trunk/freenet/src/freenet/node/OutgoingPacketMangler.java   2007-06-29 
23:35:54 UTC (rev 13837)
@@ -5,6 +5,7 @@

 import freenet.io.comm.AsyncMessageCallback;
 import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.Peer;
 import freenet.io.comm.PeerContext;
 import freenet.io.comm.SocketHandler;
 import freenet.support.WouldBlockException;
@@ -90,4 +91,8 @@
         */
        public SocketHandler getSocketHandler();

+       /**
+        * Get our addresses, as peers.
+        */
+       public Peer[] getPrimaryIPAddress();
 }

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2007-06-29 23:14:12 UTC 
(rev 13836)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2007-06-29 23:35:54 UTC 
(rev 13837)
@@ -749,8 +749,7 @@

        // Hack for two nodes on the same IP that can't talk over inet for 
routing reasons
        FreenetInetAddress localhost = node.fLocalhostAddress;
-       Peer[] nodePeers = node.ipDetector.getPrimaryIPAddress();
-//     FreenetInetAddress nodeAddr = node.getPrimaryIPAddress();
+       Peer[] nodePeers = outgoingMangler.getPrimaryIPAddress();

        Vector peers = null;
        synchronized(this) {


Reply via email to