diff --git a/history.txt b/history.txt index feead1f97..3ceeaf3b1 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,11 @@ -$Id: history.txt,v 1.142 2005/02/16 17:23:47 jrandom Exp $ +$Id: history.txt,v 1.143 2005/02/16 23:08:34 jrandom Exp $ + +2005-02-17 jrandom + * Fixed the braindead tunnel testing logic + * If a large number of tunnels are failing (within the last 5-10 minutes) + and the current tunnel pool's configuration allows it, randomly build a + zero hop tunnel to replace failed tunnels. + * Enable postman's POP3 and SMTP tunnels by default 2005-02-16 jrandom * Added some error handling when the number of session tags exceeds the diff --git a/installer/resources/i2ptunnel.config b/installer/resources/i2ptunnel.config index 4fd89778d..0933c074c 100644 --- a/installer/resources/i2ptunnel.config +++ b/installer/resources/i2ptunnel.config @@ -64,7 +64,7 @@ tunnel.4.name=smtp.postman.i2p tunnel.4.option.tunnels.depthInbound=2 tunnel.4.option.tunnels.numInbound=2 tunnel.4.option.i2p.streaming.connectDelay=1000 -tunnel.4.startOnLoad=false +tunnel.4.startOnLoad=true tunnel.4.targetDestination=smtp.postman.i2p tunnel.4.type=client @@ -78,6 +78,6 @@ tunnel.5.listenPort=7660 tunnel.5.option.tunnels.depthInbound=2 tunnel.5.option.tunnels.numInbound=2 tunnel.5.option.i2p.streaming.connectDelay=1000 -tunnel.5.startOnLoad=false +tunnel.5.startOnLoad=true tunnel.5.targetDestination=pop.postman.i2p tunnel.5.type=client diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 8648f12f0..dd422a13c 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.139 $ $Date: 2005/02/16 17:23:55 $"; + public final static String ID = "$Revision: 1.140 $ $Date: 2005/02/16 23:08:35 $"; public final static String VERSION = "0.5-pre"; - public final static long BUILD = 13; + public final static long BUILD = 14; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java index 8c2fbce5b..26d4fda13 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java @@ -54,5 +54,12 @@ class StoreMessageSelector implements MessageSelector { return false; } } + + public String toString() { + StringBuffer rv = new StringBuffer(64); + rv.append("Waiting for netDb confirm from ").append(_peer.toBase64()).append(", found? "); + rv.append(_found).append(" waiting for ").append(_waitingForId); + return rv.toString(); + } } diff --git a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java index 184acc4c0..ceeac0e88 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java @@ -26,6 +26,7 @@ class TestJob extends JobImpl { private TunnelPool _pool; private Object _buildToken; private PooledTunnelCreatorConfig _cfg; + private boolean _found; /** base to randomize the test delay on */ private static final int TEST_DELAY = 60*1000; @@ -48,6 +49,7 @@ class TestJob extends JobImpl { } public String getName() { return "Test tunnel"; } public void runJob() { + _found = false; // note: testing with exploratory tunnels always, even if the tested tunnel // is a client tunnel (per _cfg.getDestination()) TunnelInfo replyTunnel = null; @@ -150,7 +152,6 @@ class TestJob extends JobImpl { private RouterContext _context; private long _id; private long _expiration; - private boolean _found; public ReplySelector(RouterContext ctx, long id, long expiration) { _context = ctx; _id = id; @@ -158,7 +159,7 @@ class TestJob extends JobImpl { _found = false; } - public boolean continueMatching() { return _found && _context.clock().now() < _expiration; } + public boolean continueMatching() { return !_found && _context.clock().now() < _expiration; } public long getExpiration() { return _expiration; } public boolean isMatch(I2NPMessage message) { if (message instanceof DeliveryStatusMessage) { @@ -167,6 +168,12 @@ class TestJob extends JobImpl { return false; } + public String toString() { + StringBuffer rv = new StringBuffer(64); + rv.append("Testing tunnel ").append(_cfg.toString()).append(" waiting for "); + rv.append(_id).append(" found? ").append(_found); + return rv.toString(); + } } /** @@ -181,12 +188,19 @@ class TestJob extends JobImpl { testSuccessful((int)_successTime); else testFailed(_successTime); - + _found = true; } // who cares about the details... public void setMessage(I2NPMessage message) { _successTime = getContext().clock().now() - ((DeliveryStatusMessage)message).getArrival(); } + + public String toString() { + StringBuffer rv = new StringBuffer(64); + rv.append("Testing tunnel ").append(_cfg.toString()); + rv.append(" successful after ").append(_successTime); + return rv.toString(); + } } /** @@ -200,7 +214,15 @@ class TestJob extends JobImpl { } public String getName() { return "Tunnel test timeout"; } public void runJob() { - testFailed(getContext().clock().now() - _started); + if (!_found) + testFailed(getContext().clock().now() - _started); + } + + public String toString() { + StringBuffer rv = new StringBuffer(64); + rv.append("Testing tunnel ").append(_cfg.toString()); + rv.append(" timed out"); + return rv.toString(); } } } \ No newline at end of file diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java index 5f8a3cc5a..1c123cf09 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java @@ -6,6 +6,8 @@ import java.util.List; import net.i2p.data.Hash; import net.i2p.data.SessionKey; import net.i2p.data.SessionTag; +import net.i2p.stat.Rate; +import net.i2p.stat.RateStat; import net.i2p.router.RouterContext; import net.i2p.router.JobImpl; import net.i2p.router.tunnel.HopConfig; @@ -59,9 +61,17 @@ public class TunnelBuilder { TunnelPoolSettings settings = pool.getSettings(); long expiration = ctx.clock().now() + settings.getDuration(); List peers = null; - if (fake) { + + long failures = countFailures(ctx); + boolean failing = (failures > 5) && (pool.getSettings().getAllowZeroHop()); + boolean failsafe = false; + if (failing && (ctx.random().nextInt(100) < failures) ) + failsafe = true; + if (fake || failsafe) { peers = new ArrayList(1); peers.add(ctx.routerHash()); + if ( (failsafe) && (log.shouldLog(Log.WARN)) ) + log.warn("Building failsafe tunnel for " + pool); } else { peers = pool.getSelector().selectPeers(ctx, settings); } @@ -97,7 +107,18 @@ public class TunnelBuilder { l.debug("Config contains " + peers + ": " + cfg); return cfg; } - + + private long countFailures(RouterContext ctx) { + RateStat rs = ctx.statManager().getRate("tunnel.testFailedTime"); + if (rs == null) + return 0; + Rate r = rs.getRate(10*60*1000); + if (r == null) + return 0; + else + return r.getCurrentEventCount(); + } + /** * If the building fails, try, try again. *