Author: robert
Date: 2008-02-07 16:04:24 +0000 (Thu, 07 Feb 2008)
New Revision: 17663
Added:
trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
Modified:
trunk/freenet/src/freenet/node/NetworkIDManager.java
Log:
implement SecretPing testing environment
Modified: trunk/freenet/src/freenet/node/NetworkIDManager.java
===================================================================
--- trunk/freenet/src/freenet/node/NetworkIDManager.java 2008-02-07
15:00:50 UTC (rev 17662)
+++ trunk/freenet/src/freenet/node/NetworkIDManager.java 2008-02-07
16:04:24 UTC (rev 17663)
@@ -18,8 +18,8 @@
* @author robert
* @created 2008-02-06
*/
-class NetworkIDManager {
- private static boolean disableSecretPings=true;
+public class NetworkIDManager {
+ public static boolean disableSecretPings=true;
private static final int SECRETPONG_TIMEOUT=10000;
private final boolean logMINOR;
@@ -78,6 +78,7 @@
private boolean _handleSecretPing(Message m, PeerNode source, long uid,
short htl, short dawnHtl, int counter) throws NotConnectedException {
if (disableSecretPings || node.recentlyCompleted(uid)) {
+ Logger.normal(this, "recently complete/loop: "+uid);
source.sendAsync(DMT.createFNPRejectedLoop(uid), null,
0, null);
} else {
StoredSecret match;
Added: trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
(rev 0)
+++ trunk/freenet/src/freenet/node/simulator/RealNodeSecretPingTest.java
2008-02-07 16:04:24 UTC (rev 17663)
@@ -0,0 +1,235 @@
+/* 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.simulator;
+
+import java.io.File;
+
+import freenet.crypt.DummyRandomSource;
+import freenet.io.comm.DisconnectedException;
+import freenet.io.comm.DMT;
+import freenet.io.comm.Message;
+import freenet.io.comm.MessageFilter;
+import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.node.FSParseException;
+import freenet.node.Location;
+import freenet.node.LocationManager;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.node.NodeStarter;
+import freenet.node.PeerNode;
+import freenet.support.Executor;
+import freenet.support.Logger;
+import freenet.support.PooledExecutor;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.math.BootstrappingDecayingRunningAverage;
+import freenet.support.math.RunningAverage;
+import freenet.support.math.SimpleRunningAverage;
+
+/**
+ * @author amphibian
+ *
+ * Create a mesh of nodes
+ * Connect them in a s.w. network (rather than just letting them sort out
their locations)
+ * Then run some cross-peer challenge/response pings.
+ */
+public class RealNodeSecretPingTest {
+
+ //static final int NUMBER_OF_NODES = 150;
+ static final int NUMBER_OF_NODES = 15;
+ static final short MAX_HTL = (short)6;
+ static final int DEGREE = 5;
+
+ static final short PING_HTL = 6;
+ static final short DAWN_HTL = 4;
+ static final int SECRETPONG_TIMEOUT=5000;
+ static final long storeSize = 1024*1024;
+
+ public static void main(String[] args) throws FSParseException,
PeerParseException, InvalidThresholdException, NodeInitException,
ReferenceSignatureVerificationException {
+ //Logger.setupStdoutLogging(Logger.NORMAL,
"freenet.node.CPUAdjustingSwapRequestInterval:minor"
/*"freenet.node.LocationManager:debug,freenet.node.FNPPacketManager:normal,freenet.io.comm.MessageCore:debug"*/);
+ System.out.println("SecretPing (CRAM) test using real nodes:");
+ System.out.println();
+ String wd = "realNodeSecretPingTest";
+ new File(wd).mkdir();
+ //NOTE: globalTestInit returns in ignored random source
+ NodeStarter.globalTestInit(wd);
+ Logger.setupStdoutLogging(Logger.ERROR,
"freenet.node.Location:normal,freenet.node.simulator.RealNodeSecretPingTest:normal,freenet.node.NetworkIDManager:debug");
+ Logger.globalSetThreshold(Logger.ERROR);
+
+ DummyRandomSource random = new DummyRandomSource();
+ //DiffieHellman.init(random);
+ Node[] nodes = new Node[NUMBER_OF_NODES];
+ Logger.normal(RealNodeRoutingTest.class, "Creating nodes...");
+ Executor executor = new PooledExecutor();
+ for(int i=0;i<NUMBER_OF_NODES;i++) {
+ nodes[i] =
+ NodeStarter.createTestNode(5001+i, wd, false, true, true,
MAX_HTL, 0 /* no dropped packets */, random, executor, 500*NUMBER_OF_NODES,
storeSize, true);
+ Logger.normal(RealNodeRoutingTest.class, "Created node "+i);
+ }
+ Logger.normal(RealNodeRoutingTest.class, "Created "+NUMBER_OF_NODES+"
nodes");
+ // Now link them up
+ makeKleinbergNetwork(nodes);
+ Logger.normal(RealNodeRoutingTest.class, "Added small-world links");
+
+ for(int i=0;i<NUMBER_OF_NODES;i++)
+ nodes[i].start(false);
+
+ //In case they are hard-coded off, allow secret pings (this is
the test for them!)
+ freenet.node.NetworkIDManager.disableSecretPings=false;
+
+ // Now sit back and watch the fireworks!
+ int cycleNumber = 0;
+ int lastSwaps = 0;
+ int lastNoSwaps = 0;
+ int failures = 0;
+ int successes = 0;
+ RunningAverage avg2 = new BootstrappingDecayingRunningAverage(0.0,
0.0, 1.0, 100, null);
+ int pings = 0;
+ while(true) {
+ cycleNumber++;
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+
+ Node source = nodes[random.nextInt(NUMBER_OF_NODES)];
+ PeerNode verify = source.peers.getRandomPeer();
+ PeerNode pathway = source.peers.getRandomPeer(verify);
+
+ Logger.error(source, "verify ("+verify+") through:
"+pathway+"; so far "+avg2.currentValue());
+
+ long uid=random.nextLong();
+ long secret=random.nextLong();
+
+ if (verify==null) {
+ Logger.error(source, "verify peernode is null");
+ continue;
+ }
+
+ if (pathway==null) {
+ Logger.error(source, "pathway peernode is
null");
+ continue;
+ }
+
+ try {
+ //Send the FNPStoreSecret message to the
'verify' node
+ verify.sendSync(DMT.createFNPStoreSecret(uid,
secret), null);
+
+ if (!getAck(source, verify, uid)) {
+ Logger.error(source, "did not get
storesecret ack for "+uid);
+ avg2.report(0.0);
+ continue;
+ }
+
+ //Send the request for the secret through the
'pathway' node.
+ pathway.sendSync(DMT.createFNPSecretPing(uid,
verify.getLocation(), PING_HTL, DAWN_HTL, 0), null);
+
+ long result=getSecretPingResponse(source,
pathway, uid);
+ if (result!=secret) {
+ Logger.error(source, "not matched:
"+secret+" != "+result);
+ avg2.report(0.0);
+ } else {
+ Logger.error(source, "match: "+secret);
+ avg2.report(1.0);
+ }
+ } catch (NotConnectedException e) {
+ Logger.error(source, "what?",e);
+ avg2.report(0.0);
+ } catch (DisconnectedException e) {
+ Logger.error(source, "huh?",e);
+ avg2.report(0.0);
+ }
+ }
+ }
+
+ private static boolean getAck(Node source, PeerNode pathway, long uid)
throws DisconnectedException {
+ //wait for an accepted
+ MessageFilter mfAccepted =
MessageFilter.create().setSource(pathway).setField(DMT.UID,
uid).setTimeout(SECRETPONG_TIMEOUT).setType(DMT.FNPAccepted);
+ Message msg = source.getUSM().waitFor(mfAccepted, null);
+
+ if (msg==null) {
+ return false;
+ }
+
+ if (msg.getSpec() == DMT.FNPAccepted) {
+ return true;
+ }
+
+ Logger.error(source, "got "+msg);
+ return false;
+ }
+
+ private static long getSecretPingResponse(Node source, PeerNode
pathway, long uid) throws DisconnectedException {
+ //wait for a reject or pong
+ MessageFilter mfPong =
MessageFilter.create().setSource(pathway).setField(DMT.UID,
uid).setTimeout(SECRETPONG_TIMEOUT).setType(DMT.FNPSecretPong);
+ MessageFilter mfRejectLoop =
MessageFilter.create().setSource(pathway).setField(DMT.UID,
uid).setTimeout(SECRETPONG_TIMEOUT).setType(DMT.FNPRejectedLoop);
+ Message msg = source.getUSM().waitFor(mfPong.or(mfRejectLoop),
null);
+
+ if (msg==null) {
+ Logger.error(source, "fatal timeout in waiting for
secretpong from "+pathway);
+ return -2;
+ }
+
+ if (msg.getSpec() == DMT.FNPSecretPong) {
+ int suppliedCounter=msg.getInt(DMT.COUNTER);
+ long secret=msg.getLong(DMT.SECRET);
+ Logger.normal(source, "got secret,
counter="+suppliedCounter);
+ return secret;
+ }
+
+ if (msg.getSpec() == DMT.FNPRejectedLoop) {
+ Logger.error(source, "top level secret ping should not
reject!: "+source+" -> "+pathway);
+ return -1;
+ }
+
+ return -3;
+ }
+
+ /*
+ Borrowed from mrogers simulation code (February 6, 2008)
+ */
+ static void makeKleinbergNetwork (Node[] nodes)
+ {
+ for (int i=0; i<nodes.length; i++) {
+ Node a = nodes[i];
+ // Normalise the probabilities
+ double norm = 0.0;
+ for (int j=0; j<nodes.length; j++) {
+ Node b = nodes[j];
+ if (a.getLocation() == b.getLocation())
continue;
+ norm += 1.0 / distance (a, b);
+ }
+ // Create DEGREE/2 outgoing connections
+ for (int k=0; k<nodes.length; k++) {
+ Node b = nodes[k];
+ if (a.getLocation() == b.getLocation())
continue;
+ double p = 1.0 / distance (a, b) / norm;
+ for (int n = 0; n < DEGREE / 2; n++) {
+ if (Math.random() < p) {
+ try {
+ a.connect (b);
+ b.connect (a);
+ } catch (FSParseException e) {
+
Logger.error(RealNodeSecretPingTest.class, "cannot connect!!!!", e);
+ } catch (PeerParseException e) {
+
Logger.error(RealNodeSecretPingTest.class, "cannot connect #2!!!!", e);
+ } catch
(freenet.io.comm.ReferenceSignatureVerificationException e) {
+
Logger.error(RealNodeSecretPingTest.class, "cannot connect #3!!!!", e);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ static double distance(Node a, Node b) {
+ double aL=a.getLocation();
+ double bL=b.getLocation();
+ return Location.distance(aL, bL);
+ }
+}