Author: toad
Date: 2006-08-24 01:09:58 +0000 (Thu, 24 Aug 2006)
New Revision: 10249

Modified:
   trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeIPDetector.java
   trunk/freenet/src/freenet/transport/IPAddressDetector.java
Log:
Lots of work on IP address detection.

Modified: trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
===================================================================
--- trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2006-08-23 
22:37:23 UTC (rev 10248)
+++ trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2006-08-24 
01:09:58 UTC (rev 10249)
@@ -6,6 +6,8 @@
 import java.util.Vector;

 import freenet.io.comm.Peer;
+import freenet.node.useralerts.SimpleUserAlert;
+import freenet.node.useralerts.UserAlert;
 import freenet.pluginmanager.DetectedIP;
 import freenet.pluginmanager.FredPluginIPDetector;
 import freenet.support.Logger;
@@ -21,12 +23,34 @@
        private final Ticker ticker;
        private final Node node;
        FredPluginIPDetector[] plugins;
+       private SimpleUserAlert noConnectionAlert;
+       private SimpleUserAlert symmetricAlert;
+       private SimpleUserAlert portRestrictedAlert;
+       private SimpleUserAlert restrictedAlert;
+       private SimpleUserAlert connectedAlert;

        IPDetectorPluginManager(Node node, NodeIPDetector detector) {
                plugins = new FredPluginIPDetector[0];
                this.node = node;
                this.ticker = node.ps;
                this.detector = detector;
+               noConnectionAlert = new SimpleUserAlert(false, "No UDP 
connectivity", 
+                               "Your internet connection does not appear to 
support UDP. " +
+                               "Unless this detection is wrong, it is unlikely 
that Freenet will work on your computer at present.",
+                               UserAlert.CRITICAL_ERROR);
+               symmetricAlert = new SimpleUserAlert(false, "Symmetric firewall 
detected",
+                               "Your internet connection appears to be behind 
a symmetric NAT or firewall. " +
+                               "You will probably only be able to connect to 
users directly connected to the internet or behind " +
+                               "restricted cone NATs.", UserAlert.ERROR);
+               portRestrictedAlert = new SimpleUserAlert(true, "Port 
restricted cone NAT detected",
+                               "Your internet connection appears to be behind 
a port-restricted NAT (router). "+
+                               "You will be able to connect to most other 
users, but not those behind symmetric NATs.", UserAlert.MINOR);
+               restrictedAlert = new SimpleUserAlert(true, "Restricted cone 
NAT detected",
+                               "Your internet connection appears to be behind 
a \"restricted cone\" NAT (router). "+
+                               "You should be able to connect to most other 
users.", UserAlert.WARNING);
+               connectedAlert = new SimpleUserAlert(true, "Direct internet 
connection detected",
+                               "You appear to be directly connected to the 
internet. Congratulations, you should be able to connect "+
+                               "to any other freenet node.", 
UserAlert.WARNING);
        }

        void start() {
@@ -121,7 +145,7 @@
        public void maybeRun() {
                Logger.minor(this, "Maybe running IP detection plugins", new 
Exception("debug"));
                PeerNode[] peers = node.getPeerNodes();
-               PeerNode[] conns = node.getDarknetConnections();
+               PeerNode[] conns = node.getConnectedPeers();
                Peer[] nodeAddrs = detector.getPrimaryIPAddress();
                long now = System.currentTimeMillis();
                synchronized(this) {
@@ -226,6 +250,9 @@
                                        }
                                }

+                               if(detector.maybeSymmetric && 
lastDetectAttemptEndedTime <= 0) // If it appears to be an SNAT, do a detection 
at least once
+                                       maybeUrgent = true;
+                               
                                if(maybeUrgent) {
                                        if(firstTimeUrgent <= 0)
                                                firstTimeUrgent = now;
@@ -260,6 +287,7 @@
                                                        }
                                                }
                                                if(count > 2) {
+                                                       Logger.minor(this, 
"Recently connected peers count: "+count);
                                                        maybeFake = true;
                                                }
                                        }
@@ -375,10 +403,49 @@
                                }
                        }
                        DetectedIP[] list = (DetectedIP[]) 
map.values().toArray(new DetectedIP[map.size()]);
+                       int countOpen = 0;
+                       int countRestricted = 0;
+                       int countPortRestricted = 0;
+                       int countSymmetric = 0;
+                       int countClosed = 0;
                        for(int i=0;i<list.length;i++) {
                                Logger.minor(this, "Detected IP: 
"+list[i].publicAddress+ " : type "+list[i].natType);
                                System.out.println("Detected IP: 
"+list[i].publicAddress+ " : type "+list[i].natType);
+                               switch(list[i].natType) {
+                               case DetectedIP.FULL_CONE_NAT:
+                               case DetectedIP.FULL_INTERNET:
+                                       countOpen++;
+                                       break;
+                               case DetectedIP.NO_UDP:
+                                       countClosed++;
+                                       break;
+                               case DetectedIP.NOT_SUPPORTED:
+                                       // Ignore
+                                       break;
+                               case DetectedIP.RESTRICTED_CONE_NAT:
+                                       countRestricted++;
+                                       break;
+                               case DetectedIP.PORT_RESTRICTED_NAT:
+                                       countPortRestricted++;
+                                       break;
+                               case DetectedIP.SYMMETRIC_NAT:
+                               case DetectedIP.SYMMETRIC_UDP_FIREWALL:
+                                       countSymmetric++;
+                                       break;
+                               }
                        }
+                       
+                       if(countClosed > 0 && (countOpen + countRestricted + 
countPortRestricted + countSymmetric) == 0) {
+                               
node.clientCore.alerts.register(noConnectionAlert);
+                       } else if(countSymmetric > 0 && (countOpen + 
countRestricted + countPortRestricted == 0)) {
+                               node.clientCore.alerts.register(symmetricAlert);
+                       } else if(countPortRestricted > 0 && (countOpen + 
countRestricted == 0)) {
+                               
node.clientCore.alerts.register(portRestrictedAlert);
+                       } else if(countRestricted > 0 && (countOpen == 0)) {
+                               
node.clientCore.alerts.register(restrictedAlert);
+                       } else if(countOpen > 0) {
+                               node.clientCore.alerts.register(connectedAlert);
+                       }
                        detector.processDetectedIPs(list);
                        } finally {
                                runner = null;
@@ -387,4 +454,8 @@

        }

+       public boolean isEmpty() {
+               return plugins.length == 0;
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-08-23 22:37:23 UTC (rev 
10248)
+++ trunk/freenet/src/freenet/node/Node.java    2006-08-24 01:09:58 UTC (rev 
10249)
@@ -2775,10 +2775,13 @@
        }

        public PeerNode[] getPeerNodes() {
-               PeerManager pm = peers;
-               return pm.myPeers;
+               return peers.myPeers;
        }

+       public PeerNode[] getConnectedPeers() {
+               return peers.connectedPeers;
+       }
+       
        public PeerNodeStatus[] getPeerNodeStatuses() {
                PeerNodeStatus[] peerNodeStatuses = new 
PeerNodeStatus[peers.myPeers.length];
                for (int peerIndex = 0, peerCount = peers.myPeers.length; 
peerIndex < peerCount; peerIndex++) {

Modified: trunk/freenet/src/freenet/node/NodeIPDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPDetector.java  2006-08-23 22:37:23 UTC 
(rev 10248)
+++ trunk/freenet/src/freenet/node/NodeIPDetector.java  2006-08-24 01:09:58 UTC 
(rev 10249)
@@ -14,6 +14,9 @@
 import freenet.io.comm.FreenetInetAddress;
 import freenet.io.comm.Peer;
 import freenet.node.useralerts.IPUndetectedUserAlert;
+import freenet.node.useralerts.SimpleUserAlert;
+import freenet.node.useralerts.UserAlert;
+import freenet.node.useralerts.UserAlertManager;
 import freenet.pluginmanager.DetectedIP;
 import freenet.pluginmanager.FredPluginIPDetector;
 import freenet.support.Logger;
@@ -46,7 +49,11 @@
        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;

+       SimpleUserAlert maybeSymmetricAlert;
+       
        public NodeIPDetector(Node node) {
                this.node = node;
                this.ticker = node.ps;
@@ -63,6 +70,7 @@
         * third parties if available and UP&P if available.
         */
        Peer[] detectPrimaryIPAddress() {
+               boolean setMaybeSymmetric = false;
                Vector addresses = new Vector();
                if(overrideIPAddress != null) {
                        // If the IP is overridden, the override has to be the 
first element.
@@ -102,6 +110,7 @@
                                // DNSRequester doesn't deal with our own node
                                InetAddress ip = p.getAddress(true);
                                if(!IPUtil.checkAddress(ip)) continue;
+                               Logger.normal(this, "Peer 
"+peerList[i].getPeer()+" thinks we are "+p);
                                if(countsByPeer.containsKey(ip)) {
                                        Integer count = (Integer) 
countsByPeer.get(p);
                                        Integer newCount = new 
Integer(count.intValue()+1);
@@ -143,6 +152,27 @@
                                                                
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!");
+                                                               
setMaybeSymmetric = true;
+                                                               
+                                                               
if(ipDetectorManager != null && ipDetectorManager.isEmpty()) {
+                                                                       
if(maybeSymmetricAlert == null) {
+                                                                               
maybeSymmetricAlert = new SimpleUserAlert(true, "Connection problems", 
+                                                                               
                "It looks like your node may be behind a symmetric NAT. You may 
have connection " +
+                                                                               
                "problems; if you are behind a symmetric NAT you will probably 
only be able to " +
+                                                                               
                "connect to peers which are open to the internet.", 
UserAlert.ERROR);
+                                                                       }
+                                                                       
if(node.clientCore != null && node.clientCore.alerts != null)
+                                                                               
node.clientCore.alerts.register(maybeSymmetricAlert);
+                                                               } else {
+                                                                       
if(maybeSymmetricAlert != null)
+                                                                               
node.clientCore.alerts.unregister(maybeSymmetricAlert);
+                                                               }
+                                                               
+                                                               
addresses.add(new Peer(best.getFreenetAddress(), node.portNumber));
+                                                       }
                                                }
                                        }
                                }
@@ -156,6 +186,7 @@
                        }
                }
                lastIPAddress = (Peer[]) addresses.toArray(new 
Peer[addresses.size()]);
+               this.maybeSymmetric = setMaybeSymmetric;
                return lastIPAddress;
        }

@@ -166,7 +197,14 @@

        public boolean hasDirectlyDetectedIP() {
                InetAddress[] addrs = ipDetector.getAddress();
-               return (addrs != null && addrs.length > 0);
+               if(addrs == null || addrs.length == 0) return false;
+               for(int i=0;i<addrs.length;i++) {
+                       if(IPAddressDetector.isValidAddress(addrs[i], false)) {
+                               Logger.minor(this, "Has a directly detected IP: 
"+addrs[i]);
+                               return true;
+                       }
+               }
+               return false;
        }

        /**

Modified: trunk/freenet/src/freenet/transport/IPAddressDetector.java
===================================================================
--- trunk/freenet/src/freenet/transport/IPAddressDetector.java  2006-08-23 
22:37:23 UTC (rev 10248)
+++ trunk/freenet/src/freenet/transport/IPAddressDetector.java  2006-08-24 
01:09:58 UTC (rev 10249)
@@ -189,6 +189,9 @@
                                                Logger.debug(
                                                        this,
                                                        "Address " + x + ": " + 
i);
+                                       if(isValidAddress(i, 
detector.includeLocalAddressesInNoderefs)) {
+                                               output.add(i);
+                                       }
                                        if(i.isAnyLocalAddress()) {
                                                // Wildcard address, 0.0.0.0, 
ignore.
                                        } else if(i.isLinkLocalAddress() || 
i.isLoopbackAddress() ||
@@ -207,6 +210,23 @@
                lastAddressList = (InetAddress[]) output.toArray(new 
InetAddress[output.size()]);
        }

+       public static boolean isValidAddress(InetAddress i, boolean 
includeLocalAddressesInNoderefs) {
+               if(i.isAnyLocalAddress()) {
+                       // Wildcard address, 0.0.0.0, ignore.
+                       return false;
+               } else if(i.isLinkLocalAddress() || i.isLoopbackAddress() ||
+                               i.isSiteLocalAddress()) {
+                       if(includeLocalAddressesInNoderefs) {
+                               return true;
+                       } else return false;
+               } else if(i.isMulticastAddress()) {
+                       // Ignore
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+
        protected boolean isInternetAddress(InetAddress addr) {
                return detector.includeLocalAddressesInNoderefs() || 
IPUtil.checkAddress(addr);
        }


Reply via email to