Author: toad
Date: 2008-04-08 11:17:08 +0000 (Tue, 08 Apr 2008)
New Revision: 19070

Modified:
   trunk/freenet/src/freenet/node/LocationManager.java
   trunk/freenet/src/freenet/node/PeerNode.java
Log:
Prevent inter-node race condition causing excessive resets:
If our node and one of our peers have the same location, don't reset 
immediately but wait until this situation has existed for over 2 minutes on 
both sides.

Modified: trunk/freenet/src/freenet/node/LocationManager.java
===================================================================
--- trunk/freenet/src/freenet/node/LocationManager.java 2008-04-08 11:07:17 UTC 
(rev 19069)
+++ trunk/freenet/src/freenet/node/LocationManager.java 2008-04-08 11:17:08 UTC 
(rev 19070)
@@ -91,6 +91,7 @@
     }

     private double loc;
+    private long timeLocSet;
     private double locChangeSession = 0.0;

     int numberOfRemotePeerLocationsSeenInSwaps = 0;
@@ -167,15 +168,24 @@
                                 for(int i=0;i<peers.length;i++) {
                                     PeerNode pn = peers[i];
                                     if(pn.isRoutable()) {
+                                       synchronized(pn) {
                                         double ploc = pn.getLocation();
                                         if(Math.abs(ploc - myLoc) <= 
Double.MIN_VALUE) {
+                                               // Don't reset location unless 
we're SURE there is a problem.
+                                               // If the node has had its 
location equal to ours for at least 2 minutes, and ours has been likewise...
+                                               long now = 
System.currentTimeMillis();
+                                               if(now - pn.getLocSetTime() > 
120*1000 && now - timeLocSet > 120*1000) {
                                             myFlag = true;
                                             // Log an ERROR
                                             // As this is an ERROR, it results 
from either a bug or malicious action.
                                             // If it happens very frequently, 
it indicates either an attack or a serious bug.
                                             Logger.error(this, "Randomizing 
location: my loc="+myLoc+" but loc="+ploc+" for "+pn);
                                             break;
-                                        }
+                                               } else {
+                                                       Logger.normal(this, 
"Node "+pn+" has identical location to us, waiting until this has persisted for 
2 minutes...");
+                                               }
+                                       }
+                                       }
                                     }
                                 }
                                 if(myFlag) {

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2008-04-08 11:07:17 UTC 
(rev 19069)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2008-04-08 11:17:08 UTC 
(rev 19070)
@@ -169,6 +169,8 @@
        private static final int MAX_HANDSHAKE_COUNT = 2;
        /** Current location in the keyspace, or -1 if it is unknown */
        private double currentLocation;
+       /** Time the location was set */
+       private long locSetTime;
        /** Node identity; for now a block of data, in future a
        * public key (FIXME). Cannot be changed.
        */
@@ -371,6 +373,7 @@
                String locationString = fs.get("location");
                try {
                        currentLocation = Location.getLocation(locationString);
+                       locSetTime = System.currentTimeMillis();
                } catch(FSParseException e) {
                        // Wait for them to send us an FNPLocChangeNotification
                        currentLocation = -1.0;
@@ -902,6 +905,10 @@
                return currentLocation;
        }

+       public synchronized long getLocSetTime() {
+               return locSetTime;
+       }
+       
        /**
        * Returns a unique node identifier (usefull to compare two peernodes).
        */
@@ -1575,6 +1582,7 @@
                }
                synchronized(this) {
                        currentLocation = newLoc;
+                       locSetTime = System.currentTimeMillis();
                }
                node.peers.writePeers();
        }
@@ -2273,6 +2281,7 @@
                                if(!Location.equals(newLoc, currentLocation)) {
                                        changedAnything = true;
                                        currentLocation = newLoc;
+                                       locSetTime = System.currentTimeMillis();
                                }
                        } catch(FSParseException e) {
                                // Location is optional, we will wait for 
FNPLocChangeNotification. Until then we will use the last known location (or -1 
if we have never known).


Reply via email to