Author: toad
Date: 2007-12-07 13:16:04 +0000 (Fri, 07 Dec 2007)
New Revision: 16392

Modified:
   trunk/freenet/src/freenet/io/comm/PacketSocketHandler.java
   trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java
   trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
   trunk/freenet/src/freenet/node/DarknetPeerNode.java
   trunk/freenet/src/freenet/node/FNPPacketMangler.java
   trunk/freenet/src/freenet/node/NodeCryptoConfig.java
   trunk/freenet/src/freenet/node/OutgoingPacketMangler.java
   trunk/freenet/src/freenet/node/PeerNode.java
Log:
Use burst-only automatically if we are fairly sure we are port forwarded.
Can be turned off by node.assumedNATed = true (new option), which is on by 
default.
Please tell me if your NAT or firewall is detected as definitely port forwarded.

Modified: trunk/freenet/src/freenet/io/comm/PacketSocketHandler.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/PacketSocketHandler.java  2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/io/comm/PacketSocketHandler.java  2007-12-07 
13:16:04 UTC (rev 16392)
@@ -32,4 +32,7 @@
        /** How big must the pending data be before we send a packet? 
*Includes* transport layer headers. */
        public int getPacketSendThreshold();

+       /** Does this port appear to be port forwarded? @see AddressTracker */
+       int getDetectedConnectivityStatus();
+
 }

Modified: trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java     2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java     2007-12-07 
13:16:04 UTC (rev 16392)
@@ -414,4 +414,8 @@
                tracker.setBrokenDetector(detector);
        }

+       public int getDetectedConnectivityStatus() {
+               return tracker.getPortForwardStatus();
+       }
+
 }

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-12-07 
13:16:04 UTC (rev 16392)
@@ -552,6 +552,8 @@
 N2NTMUserAlert.title=Node to Node Text Message ${number} from ${peername} 
(${peer})
 Node.alwaysAllowLocalAddresses=Always allow connecting to nodes via local 
addresses?
 Node.alwaysAllowLocalAddressesLong=If true, the node will attempt to connect 
to nodes via their local (localhost, LAN) addresses as well as their public 
IPs. If this is not set, you can still enable it for specific darknet peers 
(but not opennet peers). Set this if you want to connect to other nodes on the 
same LAN or computer, and don't mind that bogus references can cause your node 
to send UDP packets to machines on your LAN.
+Node.assumeNATed=Assume the port is not forwarded.
+Node.assumeNATedLong=Should the node assume the port is NATed and not 
forwarded, and always send handshakes aggressively (every 10-30 seconds), 
regardless of any evidence to the contrary?
 Node.bandwidthLimitMustBePositiveOrMinusOne=Bandwidth limit must be positive 
or -1
 Node.bindTo=IP address to bind to
 Node.bindToLong=IP address to bind to

Modified: trunk/freenet/src/freenet/node/DarknetPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/DarknetPeerNode.java 2007-12-07 12:32:11 UTC 
(rev 16391)
+++ trunk/freenet/src/freenet/node/DarknetPeerNode.java 2007-12-07 13:16:04 UTC 
(rev 16392)
@@ -57,9 +57,6 @@
     /** True if we send handshake requests to this peer in infrequent bursts */
     private boolean isBurstOnly;

-    /** True if we are currently sending this peer a burst of handshake 
requests */
-    private boolean isBursting;
-
     /** True if we want to ignore the source port of the node's sent packets.
      * This is normally set when dealing with an Evil Corporate Firewall which 
rewrites the port on outgoing
      * packets but does not redirect incoming packets destined to the 
rewritten port.
@@ -82,12 +79,6 @@
     /** Queued-to-send N2NTM extra peer data file numbers */
     private LinkedHashSet queuedToSendN2NTMExtraPeerDataFileNumbers;

-    /** Number of handshake attempts (while in ListenOnly mode) since the 
beginning of this burst */
-    private int listeningHandshakeBurstCount;
-    
-    /** Total number of handshake attempts (while in ListenOnly mode) to be in 
this burst */
-    private int listeningHandshakeBurstSize;
-    
     private static boolean logMINOR;

     /**
@@ -100,8 +91,6 @@

        logMINOR = Logger.shouldLog(Logger.MINOR, this);

-       long now = System.currentTimeMillis();
-       
         String name = fs.get("myName");
         if(name == null) throw new FSParseException("No name");
         myName = name;
@@ -117,13 +106,6 @@
                allowLocalAddresses = 
Fields.stringToBool(metadata.get("allowLocalAddresses"), false);
         }

-        listeningHandshakeBurstCount = 0;
-        listeningHandshakeBurstSize = Node.MIN_BURSTING_HANDSHAKE_BURST_SIZE
-               + 
node.random.nextInt(Node.RANDOMIZED_BURSTING_HANDSHAKE_BURST_SIZE);
-        if(isBurstOnly) {
-               Logger.minor(this, "First BurstOnly mode handshake in 
"+(sendHandshakeTime - now)+"ms for "+getName()+" (count: 
"+listeningHandshakeBurstCount+", size: "+listeningHandshakeBurstSize+ ')');
-        }
-
                // Setup the private darknet comment note
         privateDarknetComment = "";
         privateDarknetCommentFileNumber = -1;
@@ -168,13 +150,7 @@
                if(isDisabled) return false;
                if(isListenOnly) return false;
                if(!super.shouldSendHandshake()) return false;
-               if(isBurstOnly())
-                       isBursting = true;
-               else
-                       return true;
        }
-       // Might have changed from burst only to bursting
-               setPeerNodeStatus(System.currentTimeMillis());
                return true;
     }

@@ -231,8 +207,6 @@
                        return status;
                if(isListenOnly)
                        return PeerManager.PEER_NODE_STATUS_LISTEN_ONLY;
-               if(isBursting)
-                       return PeerManager.PEER_NODE_STATUS_BURSTING;
                if(isBurstOnly)
                        return PeerManager.PEER_NODE_STATUS_LISTENING;
                return status;
@@ -341,8 +315,11 @@
                return ignoreSourcePort;
        }

-       public synchronized boolean isBurstOnly() {
-               return isBurstOnly;
+       public boolean isBurstOnly() {
+               synchronized(this) {
+                       if(isBurstOnly) return true;
+               }
+               return super.isBurstOnly();
        }

        public boolean allowLocalAddresses() {
@@ -1516,31 +1493,6 @@
                return ""+getPeer()+" : "+getName();
        }

-       protected synchronized boolean innerCalcNextHandshake(boolean 
successfulHandshakeSend, boolean dontFetchARK, long now) {
-               if(isBurstOnly) {
-                       boolean fetchARKFlag = false;
-                       listeningHandshakeBurstCount++;
-                       if(listeningHandshakeBurstCount >= 
listeningHandshakeBurstSize) {
-                               listeningHandshakeBurstCount = 0;
-                               fetchARKFlag = true;
-                       }
-                       if(listeningHandshakeBurstCount == 0) {  // 0 only if 
we just reset it above
-                               sendHandshakeTime = now + 
Node.MIN_TIME_BETWEEN_BURSTING_HANDSHAKE_BURSTS
-                                       + 
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_BURSTING_HANDSHAKE_BURSTS);
-                               listeningHandshakeBurstSize = 
Node.MIN_BURSTING_HANDSHAKE_BURST_SIZE
-                                               + 
node.random.nextInt(Node.RANDOMIZED_BURSTING_HANDSHAKE_BURST_SIZE);
-                               isBursting = false;
-                       } else {
-                               sendHandshakeTime = now + 
Node.MIN_TIME_BETWEEN_HANDSHAKE_SENDS
-                                       + 
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_HANDSHAKE_SENDS);
-                       }
-                       if(logMINOR) Logger.minor(this, "Next BurstOnly mode 
handshake in "+(sendHandshakeTime - now)+"ms for "+getName()+" (count: 
"+listeningHandshakeBurstCount+", size: "+listeningHandshakeBurstSize+ ')', new 
Exception("double-called debug"));
-                       return fetchARKFlag;
-               } else {
-                       return 
super.innerCalcNextHandshake(successfulHandshakeSend, dontFetchARK, now);
-               }
-       }
-
        public PeerNodeStatus getStatus() {
                return new DarknetPeerNodeStatus(this);
        }

Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java        2007-12-07 
13:16:04 UTC (rev 16392)
@@ -4,6 +4,7 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

+import freenet.io.AddressTracker;
 import freenet.io.comm.SocketHandler;

 import java.security.MessageDigest;
@@ -2757,4 +2758,10 @@
                return data;
        }

+       public int getConnectivityStatus() {
+               if(crypto.config.alwaysHandshakeAggressively())
+                       return AddressTracker.DEFINITELY_NATED;
+               return sock.getDetectedConnectivityStatus();
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/NodeCryptoConfig.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2007-12-07 
13:16:04 UTC (rev 16392)
@@ -46,6 +46,10 @@
         * regardless of any per-peer setting. */
        private boolean alwaysAllowLocalAddresses;

+       /** If true, assume we are NATed regardless of the evidence, and 
therefore always send
+        * aggressive handshakes (every 10-30 seconds). */
+       private boolean assumeNATed;
+       
        NodeCryptoConfig(SubConfig config, int sortOrder, boolean onePerIP) 
throws NodeInitException {

                config.register("listenPort", -1 /* means random */, 
sortOrder++, true, true, "Node.port", "Node.portLong",     new IntCallback() {
@@ -149,6 +153,18 @@
                                        }
                });
                alwaysAllowLocalAddresses = 
config.getBoolean("alwaysAllowLocalAddresses");
+               
+               config.register("assumeNATed", true, sortOrder++, true, false, 
"Node.assumeNATed", "Node.assumeNATedLong", new BooleanCallback() {
+
+                       public boolean get() {
+                               return assumeNATed;
+                       }
+
+                       public void set(boolean val) throws 
InvalidConfigValueException {
+                               assumeNATed = val;
+                       }
+               });
+               assumeNATed = config.getBoolean("assumeNATed");
        }

        /** The number of config options i.e. the amount to increment sortOrder 
by */
@@ -211,4 +227,9 @@
        public synchronized boolean alwaysAllowLocalAddresses() {
                return alwaysAllowLocalAddresses;
        }
+
+       public boolean alwaysHandshakeAggressively() {
+               // TODO Auto-generated method stub
+               return false;
+       }
 }

Modified: trunk/freenet/src/freenet/node/OutgoingPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/OutgoingPacketMangler.java   2007-12-07 
12:32:11 UTC (rev 16391)
+++ trunk/freenet/src/freenet/node/OutgoingPacketMangler.java   2007-12-07 
13:16:04 UTC (rev 16392)
@@ -105,4 +105,10 @@
         * Always allow local addresses?
         */
        public boolean alwaysAllowLocalAddresses();
+
+       /**
+        * Port forwarding status.
+        * @return A status code from AddressTracker. FIXME make this more 
generic when we need to.
+        */
+       public int getConnectivityStatus();
 }

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2007-12-07 12:32:11 UTC 
(rev 16391)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2007-12-07 13:16:04 UTC 
(rev 16392)
@@ -33,6 +33,7 @@
 import freenet.crypt.SHA256;
 import freenet.crypt.UnsupportedCipherException;
 import freenet.crypt.ciphers.Rijndael;
+import freenet.io.AddressTracker;
 import freenet.io.comm.AsyncMessageCallback;
 import freenet.io.comm.ByteCounter;
 import freenet.io.comm.DMT;
@@ -282,6 +283,15 @@
     /** Previous time of disconnection */
     long timePrevDisconnect;

+    // Burst-only mode
+    /** True if we are currently sending this peer a burst of handshake 
requests */
+    private boolean isBursting;
+    /** Number of handshake attempts (while in ListenOnly mode) since the 
beginning of this burst */
+    private int listeningHandshakeBurstCount;
+    /** Total number of handshake attempts (while in ListenOnly mode) to be in 
this burst */
+    private int listeningHandshakeBurstSize;
+    
+    
        /**
         * For FNP link setup:
         *  The initiator has to ensure that nonces send back by the
@@ -590,6 +600,14 @@
                lastAttemptedHandshakeIPUpdateTime = 0;
                maybeUpdateHandshakeIPs(true);

+        listeningHandshakeBurstCount = 0;
+        listeningHandshakeBurstSize = Node.MIN_BURSTING_HANDSHAKE_BURST_SIZE
+               + 
node.random.nextInt(Node.RANDOMIZED_BURSTING_HANDSHAKE_BURST_SIZE);
+               
+        if(isBurstOnly()) {
+               Logger.minor(this, "First BurstOnly mode handshake in 
"+(sendHandshakeTime - now)+"ms for "+shortToString()+" (count: 
"+listeningHandshakeBurstCount+", size: "+listeningHandshakeBurstSize+ ')');
+        }
+
                if(fromLocal)
                        innerCalcNextHandshake(false, false, now); // Let them 
connect so we can recognise we are NATed

@@ -1143,6 +1161,15 @@
                }
                if(tempShouldSendHandshake && (hasLiveHandshake(now)))
                        tempShouldSendHandshake = false;
+               if(tempShouldSendHandshake) {
+               if(isBurstOnly()) {
+                       synchronized(this) {
+                               isBursting = true;
+                       }
+                       setPeerNodeStatus(System.currentTimeMillis());
+               } else
+                       return true;
+               }
                return tempShouldSendHandshake;
        }

@@ -1165,6 +1192,8 @@
         * Set sendHandshakeTime, and return whether to fetch the ARK.
         */
        protected synchronized boolean innerCalcNextHandshake(boolean 
successfulHandshakeSend, boolean dontFetchARK, long now) {
+               if(isBurstOnly())
+                       return calcNextHandshakeBurstOnly(now);
                if(verifiedIncompatibleOlderVersion || 
verifiedIncompatibleNewerVersion || disableRouting) {
                        // Let them know we're here, but have no hope of 
connecting
                        sendHandshakeTime = now + 
Node.MIN_TIME_BETWEEN_VERSION_SENDS + 
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_SENDS);
@@ -1180,6 +1209,29 @@
                return ((handshakeCount == MAX_HANDSHAKE_COUNT) && 
!(verifiedIncompatibleOlderVersion || verifiedIncompatibleNewerVersion));
        }

+       private synchronized boolean calcNextHandshakeBurstOnly(long now) {
+               boolean fetchARKFlag = false;
+               listeningHandshakeBurstCount++;
+               if(isBurstOnly()) {
+                       if(listeningHandshakeBurstCount >= 
listeningHandshakeBurstSize) {
+                               listeningHandshakeBurstCount = 0;
+                               fetchARKFlag = true;
+                       }
+               }
+               if(listeningHandshakeBurstCount == 0) {  // 0 only if we just 
reset it above
+                       sendHandshakeTime = now + 
Node.MIN_TIME_BETWEEN_BURSTING_HANDSHAKE_BURSTS
+                               + 
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_BURSTING_HANDSHAKE_BURSTS);
+                       listeningHandshakeBurstSize = 
Node.MIN_BURSTING_HANDSHAKE_BURST_SIZE
+                                       + 
node.random.nextInt(Node.RANDOMIZED_BURSTING_HANDSHAKE_BURST_SIZE);
+                       isBursting = false;
+               } else {
+                       sendHandshakeTime = now + 
Node.MIN_TIME_BETWEEN_HANDSHAKE_SENDS
+                               + 
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_HANDSHAKE_SENDS);
+               }
+               if(logMINOR) Logger.minor(this, "Next BurstOnly mode handshake 
in "+(sendHandshakeTime - now)+"ms for "+shortToString()+" (count: 
"+listeningHandshakeBurstCount+", size: "+listeningHandshakeBurstSize+ ')', new 
Exception("double-called debug"));
+               return fetchARKFlag;
+       }
+
        protected void calcNextHandshake(boolean successfulHandshakeSend, 
boolean dontFetchARK) {
                long now = System.currentTimeMillis();
                boolean fetchARKFlag = false;
@@ -1195,6 +1247,30 @@
                }
        }

+       /** If the outgoingMangler allows bursting, we still don't want to 
burst *all the time*, because it may be mistaken
+        * in its detection of a port forward. So from time to time we will 
aggressively handshake anyway. This flag is set
+        * once every UPDATE_BURST_NOW_PERIOD. */
+       private boolean burstNow;
+       private long timeSetBurstNow;
+       static final int UPDATE_BURST_NOW_PERIOD = 5*60*1000;
+       /** Burst only 19 in 20 times if definitely port forwarded. Save 
entropy by writing this as 20 not 0.95. */
+       static final int P_BURST_IF_DEFINITELY_FORWARDED = 20;
+       
+       public boolean isBurstOnly() {
+               int status = outgoingMangler.getConnectivityStatus();
+               if(status == AddressTracker.DONT_KNOW) return false;
+               if(status == AddressTracker.DEFINITELY_NATED) return false;
+               
+               // For now. FIXME try it with a lower probability when we're 
sure that the packet-deltas mechanisms works.
+               if(status == AddressTracker.MAYBE_PORT_FORWARDED) return false;
+               long now = System.currentTimeMillis();
+               if(now - timeSetBurstNow > UPDATE_BURST_NOW_PERIOD) {
+                       burstNow = 
(node.random.nextInt(P_BURST_IF_DEFINITELY_FORWARDED) == 0);
+                       timeSetBurstNow = now;
+               }
+               return burstNow;
+       }
+
        /**
        * Call this method when a handshake request has been
        * sent.
@@ -2606,6 +2682,8 @@
                        peerNodeStatus = 
PeerManager.PEER_NODE_STATUS_CLOCK_PROBLEM;
                else if(neverConnected)
                        peerNodeStatus = 
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED;
+               else if(isBursting)
+                       return PeerManager.PEER_NODE_STATUS_BURSTING;
                else
                        peerNodeStatus = 
PeerManager.PEER_NODE_STATUS_DISCONNECTED;
                if(!isConnected && (previousRoutingBackoffReason != null)) {


Reply via email to