Author: zothar
Date: 2006-05-18 03:33:53 +0000 (Thu, 18 May 2006)
New Revision: 8754
Added:
trunk/freenet/src/freenet/node/BuildOldAgeUserAlert.java
Modified:
trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/PeerNode.java
trunk/freenet/src/freenet/node/Version.java
Log:
Prepare for alerting the user when their build is older than the current
lastGoodVersion advertised by their peers. This commit should not change any
behavior.
Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
2006-05-18 00:15:09 UTC (rev 8753)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
2006-05-18 03:33:53 UTC (rev 8754)
@@ -100,12 +100,14 @@
final Integer CONNECTED = new Integer(0);
final Integer BACKED_OFF = new Integer(1);
- final Integer INCOMPATIBLE = new Integer(2);
- final Integer DISCONNECTED = new Integer(3);
+ final Integer TOO_NEW = new Integer(2);
+ final Integer INCOMPATIBLE = new Integer(3);
+ final Integer DISCONNECTED = new Integer(4);
int numberOfConnected = 0;
int numberOfBackedOff = 0;
int numberOfIncompatible = 0;
+ int numberOfTooNew = 0;
int numberOfDisconnected = 0;
// Create array
@@ -129,6 +131,8 @@
if(routingBackedOffNow) {
status = BACKED_OFF;
}
+ } else if(pn.hasCompletedHandshake() &&
pn.isVerifiedIncompatibleNewerVersion()) {
+ status = TOO_NEW;
} else if(pn.hasCompletedHandshake() &&
!Version.checkGoodVersion(pn.getVersion())) {
status = INCOMPATIBLE;
} else {
@@ -162,6 +166,10 @@
row[1] = "<span class=\"peer_backedoff\">BACKED
OFF</span>";
numberOfBackedOff++;
}
+ else if(x == TOO_NEW) {
+ row[1] = "<span class=\"peer_too_new\">TOO
NEW</span>";
+ numberOfTooNew++;
+ }
else if(x == INCOMPATIBLE) {
row[1] = "<span
class=\"peer_incompatible\">INCOMPATIBLE</span>";
numberOfIncompatible++;
@@ -228,6 +236,12 @@
buf.append("<span
class=\"peer_backedoff\">BACKED OFF: " + numberOfBackedOff + "</span>");
separatorNeeded = true;
}
+ if (numberOfTooNew != 0) {
+ if (separatorNeeded)
+ buf.append(" | ");
+ buf.append("<span class=\"peer_too_new\">TOO
NEW: " + numberOfTooNew + "</span>");
+ separatorNeeded = true;
+ }
if (numberOfIncompatible != 0) {
if (separatorNeeded)
buf.append(" | ");
Modified:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
2006-05-18 00:15:09 UTC (rev 8753)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
2006-05-18 03:33:53 UTC (rev 8754)
@@ -270,6 +270,10 @@
color: #ff0000;
}
+table.darknet_connections span.peer_too_new {
+ color: #d0a0a0;
+}
+
table.darknet_connections span.peer_incompatible {
color: #d0a0d0;
}
Added: trunk/freenet/src/freenet/node/BuildOldAgeUserAlert.java
===================================================================
--- trunk/freenet/src/freenet/node/BuildOldAgeUserAlert.java 2006-05-18
00:15:09 UTC (rev 8753)
+++ trunk/freenet/src/freenet/node/BuildOldAgeUserAlert.java 2006-05-18
03:33:53 UTC (rev 8754)
@@ -0,0 +1,39 @@
+package freenet.node;
+
+public class BuildOldAgeUserAlert implements UserAlert {
+ private boolean isValid=true;
+ int lastGoodVersion = 0;
+
+ public boolean userCanDismiss() {
+ return false;
+ }
+
+ public String getTitle() {
+ return "Build too old";
+ }
+
+ public String getText() {
+ if(lastGoodVersion == 0)
+ throw new IllegalArgumentException("Not valid");
+ String s;
+ s = "This node's software is older than the oldest version
(Build #"+lastGoodVersion+") allowed by the newest peers we " +
+ "try to connect to. Please update your node as
soon as possible as you will not be " +
+ "able to connect to peers labeled \"TOO NEW\"
until you do. " +
+ "(Freenet may leave your node in the dust of
the past if you don't upgrade.)";
+ return s;
+ }
+
+ public short getPriorityClass() {
+ return UserAlert.ERROR;
+ }
+
+ public boolean isValid() {
+ if(lastGoodVersion == 0)
+ return false;
+ return isValid;
+ }
+
+ public void isValid(boolean b){
+ if(userCanDismiss()) isValid=b;
+ }
+}
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-05-18 00:15:09 UTC (rev
8753)
+++ trunk/freenet/src/freenet/node/Node.java 2006-05-18 03:33:53 UTC (rev
8754)
@@ -297,6 +297,7 @@
private static IPUndetectedUserAlert primaryIPUndetectedAlert;
private static MeaningfulNodeNameUserAlert nodeNameUserAlert;
+ private static BuildOldAgeUserAlert buildOldAgeUserAlert;
public class NodeNameCallback implements StringCallback{
Node node;
@@ -390,6 +391,8 @@
public static final int RANDOMIZED_TIME_BETWEEN_HANDSHAKE_SENDS =
HANDSHAKE_TIMEOUT;
public static final int MIN_TIME_BETWEEN_VERSION_PROBES =
HANDSHAKE_TIMEOUT*4;
public static final int RANDOMIZED_TIME_BETWEEN_VERSION_PROBES =
HANDSHAKE_TIMEOUT*2; // 20-30 secs
+ public static final int MIN_TIME_BETWEEN_VERSION_SENDS =
HANDSHAKE_TIMEOUT*9;
+ public static final int RANDOMIZED_TIME_BETWEEN_VERSION_SENDS =
HANDSHAKE_TIMEOUT*2; // 45-55 secs
// If we don't receive any packets at all in this period, from any node,
tell the user
public static final long ALARM_TIME = 60*1000;
/** Sub-max ping time. If ping is greater than this, we reject some
requests. */
@@ -1072,6 +1075,8 @@
usm.setDispatcher(dispatcher=new NodeDispatcher(this));
usm.setLowLevelFilter(packetMangler = new FNPPacketMangler(this));
+
+ buildOldAgeUserAlert = new BuildOldAgeUserAlert();
// Temp files
@@ -2595,4 +2600,15 @@
public String getBindTo(){
return this.bindto;
}
+
+ public boolean setNewestPeerLastGoodVersion( int version ) {
+ if( version > buildOldAgeUserAlert.lastGoodVersion ) {
+ if( buildOldAgeUserAlert.lastGoodVersion == 0 ) {
+ alerts.register(buildOldAgeUserAlert);
+ }
+ buildOldAgeUserAlert.lastGoodVersion = version;
+ return true;
+ }
+ return false;
+ }
}
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2006-05-18 00:15:09 UTC
(rev 8753)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2006-05-18 03:33:53 UTC
(rev 8754)
@@ -63,6 +63,11 @@
private String lastGoodVersion;
+ /** Set to true based on a relevant incoming handshake from this peer
+ Set true if this peer has a incompatible newer build than we are
+ */
+ private boolean verifiedIncompatibleNewerVersion = false;
+
/** For debugging/testing, set this to true to stop the
* probabilistic decrement at the edges of the HTLs.
*/
@@ -466,6 +471,14 @@
}
/**
+ * Is this node too new for us? (i.e. our version if older than it's
lastGoodVersion)
+ *
+ */
+ public boolean isVerifiedIncompatibleNewerVersion() {
+ return verifiedIncompatibleNewerVersion;
+ }
+
+ /**
* Is this node currently connected?
*
* Note possible deadlocks! PeerManager calls this, we call
@@ -607,7 +620,12 @@
public synchronized void sentHandshake() {
Logger.debug(this, "sentHandshake(): "+this);
long now = System.currentTimeMillis();
- if(invalidVersion() && !firstHandshake) {
+ if(verifiedIncompatibleNewerVersion) {
+ // 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)
+ +
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_SENDS);
+ } else if(invalidVersion() && !firstHandshake) {
sendHandshakeTime = now + Node.MIN_TIME_BETWEEN_VERSION_PROBES
+
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_PROBES);
} else {
@@ -628,7 +646,12 @@
public synchronized void couldNotSendHandshake() {
Logger.minor(this, "couldNotSendHandshake(): "+this);
long now = System.currentTimeMillis();
- if(invalidVersion() && !firstHandshake) {
+ if(verifiedIncompatibleNewerVersion) {
+ // 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)
+ +
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_SENDS);
+ } else if(invalidVersion() && !firstHandshake) {
sendHandshakeTime = now + Node.MIN_TIME_BETWEEN_VERSION_PROBES
+
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_PROBES)
+
node.random.nextInt(Node.RANDOMIZED_TIME_BETWEEN_VERSION_PROBES);
@@ -943,6 +966,10 @@
private synchronized boolean invalidVersion() {
return bogusNoderef || (!Version.checkGoodVersion(version));
}
+
+ private synchronized boolean reverseInvalidVersion() {
+ return bogusNoderef ||
(!Version.checkArbitraryGoodVersion(Version.getVersionString(),lastGoodVersion));
+ }
/**
* Process a new nodereference, in compressed form.
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-05-18 00:15:09 UTC (rev
8753)
+++ trunk/freenet/src/freenet/node/Version.java 2006-05-18 03:33:53 UTC (rev
8754)
@@ -152,6 +152,77 @@
}
/**
+ * @return true if requests should be accepted from nodes brandishing
this
+ * version string, given an arbitrary lastGoodVersion
+ */
+ public static final boolean checkArbitraryGoodVersion(
+ String version, String lastGoodVersion) {
+ if(version == null) {
+ Logger.error(Version.class, "version == null!",
+ new Exception("error"));
+ return false;
+ }
+ if(lastGoodVersion == null) {
+ Logger.error(Version.class, "lastGoodVersion == null!",
+ new Exception("error"));
+ return false;
+ }
+ String[] v = Fields.commaList(version);
+ String[] lgv = Fields.commaList(lastGoodVersion);
+
+ if (v.length < 3 || !goodProtocol(v[2])) {
+ return false;
+ }
+ if (lgv.length < 3 || !goodProtocol(lgv[2])) {
+ return false;
+ }
+ if (sameArbitraryVersion(v,lgv)) {
+ try {
+ int build = Integer.parseInt(v[3]);
+ int min_build = Integer.parseInt(lgv[3]);
+ if (build < min_build) {
+ if(logDEBUG) Logger.debug(
+ Version.class,
+ "Not accepting unstable from
version: "
+ + version
+ + "(lastGoodVersion="
+ + lastGoodVersion
+ + ")");
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ Logger.minor(
+ Version.class,
+ "Not accepting (" + e + ") from " +
version + " and/or " + lastGoodVersion);
+ return false;
+ }
+ }
+ if (stableVersion(v)) {
+ try {
+ int build = Integer.parseInt(v[3]);
+ if(build < lastGoodStableBuild) {
+ if(logDEBUG) Logger.debug(
+ Version.class,
+ "Not accepting stable from
version"
+ + version
+ +
"(lastGoodStableBuild="
+ + lastGoodStableBuild
+ + ")");
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ Logger.minor(
+ Version.class,
+ "Not accepting (" + e + ") from " +
version);
+ return false;
+ }
+ }
+ if(logDEBUG)
+ Logger.minor(Version.class, "Accepting: " + version);
+ return true;
+ }
+
+ /**
* @return string explaining why a version string is rejected
*/
public static final String explainBadVersion(String version) {
@@ -186,6 +257,24 @@
}
/**
+ * @return the build number of an arbitrary version string
+ */
+ public static final int getArbitraryBuildNumber(
+ String version ) throws NumberFormatException {
+ if(version == null) {
+ Logger.error(Version.class, "version == null!",
+ new Exception("error"));
+ throw new NumberFormatException();
+ }
+ String[] v = Fields.commaList(version);
+
+ if (v.length < 3 || !goodProtocol(v[2])) {
+ throw new NumberFormatException();
+ }
+ return Integer.parseInt(v[3]);
+ }
+
+ /**
* Update static variable highestSeenBuild anytime we encounter
* a new node with a higher version than we've seen before
*/
@@ -225,6 +314,17 @@
}
/**
+ * @return true if the string describes the same node version as an
arbitrary one.
+ * Note that the build number may be different, and is ignored.
+ */
+ public static boolean sameArbitraryVersion(String[] v, String[] lgv) {
+ return v[0].equals(lgv[0])
+ && v[1].equals(lgv[1])
+ && v.length >= 4
+ && lgv.length >= 4;
+ }
+
+ /**
* @return true if the string describes a stable node version
*/
private static boolean stableVersion(String[] v) {