diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 2d22b54bc..4875c8f0b 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -23,6 +23,7 @@ import net.i2p.client.streaming.I2PSocketOptions; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; import net.i2p.util.EventDispatcher; +import net.i2p.util.FileUtil; import net.i2p.util.Log; /** @@ -70,7 +71,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable "wrong BASE64 I2P Destination or the link you are following is "+ "bad. The host (or the WWW proxy, if you're using one) could also "+ "be temporarily offline. You may want to retry. "+ - "Could not find the following Destination:

") + "Could not find the following Destination:

") .getBytes(); private final static byte[] ERR_TIMEOUT = @@ -190,6 +191,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "ISO-8859-1")); String line, method = null, protocol = null, host = null, destination = null; StringBuffer newRequest = new StringBuffer(); + int ahelper = 0; while ((line = br.readLine()) != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix(requestId) + "Line=[" + line + "]"); @@ -282,6 +284,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable if (addressHelper != null) { destination = addressHelper; host = getHostName(destination); + ahelper = 1; } } line = method + " " + request.substring(pos); @@ -403,7 +406,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable l.log("Could not resolve " + destination + "."); if (_log.shouldLog(Log.WARN)) _log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest); - writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, destination); + String str; + byte[] header; + if (usingWWWProxy) + str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true); + else if(ahelper != 0) + str = FileUtil.readTextFile("docs/dnfb-header.ht", 100, true); + else + str = FileUtil.readTextFile("docs/dnf-header.ht", 100, true); + if (str != null) + header = str.getBytes(); + else + header = ERR_DESTINATION_UNKNOWN; + writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination); s.close(); return; } @@ -476,10 +491,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable if (out != null) { out.write(errMessage); if (targetRequest != null) { - out.write(targetRequest.getBytes()); + int protopos = targetRequest.indexOf(" "); + String uri = targetRequest.substring(0, protopos); + out.write("http://".getBytes()); + out.write(uri.getBytes()); + out.write("".getBytes()); if (usingWWWProxy) out.write(("
WWW proxy: " + wwwProxy).getBytes()); } - out.write("

Generated on: ".getBytes()); + out.write("

I2P HTTP Proxy Server
Generated on: ".getBytes()); out.write(new Date().toString().getBytes()); out.write("
\n".getBytes()); out.flush(); @@ -493,7 +514,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable _log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex); if (out != null) { try { - writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy); + String str; + byte[] header; + if (usingWWWProxy) + str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true); + else + str = FileUtil.readTextFile("docs/dnf-header.ht", 100, true); + if (str != null) + header = str.getBytes(); + else + header = ERR_DESTINATION_UNKNOWN; + writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy); } catch (IOException ioe) { _log.warn(getPrefix(requestId) + "Error writing out the 'destination was unknown' " + "message", ioe); } diff --git a/build.xml b/build.xml index 674ed2d20..d93e2e795 100644 --- a/build.xml +++ b/build.xml @@ -228,6 +228,9 @@ + + + @@ -274,6 +277,9 @@ + + + diff --git a/history.txt b/history.txt index 824113629..c49f4563e 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,13 @@ -$Id: history.txt,v 1.192 2005/04/12 10:22:11 jrandom Exp $ +$Id: history.txt,v 1.193 2005/04/16 19:59:51 jrandom Exp $ + +2005-04-17 zzz + * Added new user-editable eepproxy error page templates. + +2005-04-17 jrandom + * Revamp the tunnel building throttles, fixing a situation where the + rebuild may not recover, and defaulting it to unthrottled (users with + slow CPUs may want to set "router.tunnel.shouldThrottle=true" in their + advanced router config) 2005-04-16 jrandom * Migrated to Bouncycastle's SHA256 and HMAC implementations for efficiency diff --git a/installer/resources/dnf-header.ht b/installer/resources/dnf-header.ht new file mode 100644 index 000000000..3550daa07 --- /dev/null +++ b/installer/resources/dnf-header.ht @@ -0,0 +1,41 @@ +HTTP/1.1 504 Gateway Timeout +Content-Type: text/html; charset=iso-8859-1 +Cache-control: no-cache + + +Eepsite not reachable + + + +

+
+The eepsite was not reachable. Perhaps +the link you are following is +bad. The eepsite could also +be temporarily offline. You may want to +retry. +

Could not find the following destination:

diff --git a/installer/resources/dnfb-header.ht b/installer/resources/dnfb-header.ht new file mode 100644 index 000000000..f33e9c025 --- /dev/null +++ b/installer/resources/dnfb-header.ht @@ -0,0 +1,42 @@ +HTTP/1.1 400 Destination Not Found +Content-Type: text/html; charset=iso-8859-1 +Cache-control: no-cache + + +Invalid eepsite destination + + + + +
+The eepsite destination specified was not valid, or was +otherwise unreachable. Perhaps you pasted in the +wrong BASE64 string or the link you are following is +bad. The I2P host could also +be temporarily offline. You may want to +retry. +

Could not find the following destination:

diff --git a/installer/resources/dnfp-header.ht b/installer/resources/dnfp-header.ht new file mode 100644 index 000000000..fcffb765a --- /dev/null +++ b/installer/resources/dnfp-header.ht @@ -0,0 +1,46 @@ +HTTP/1.1 504 Gateway Timeout +Content-Type: text/html; charset=iso-8859-1 +Cache-control: no-cache + + +Outproxy Not Found + + + + + +
+The WWW Outproxy was not found. +It could +be temporarily offline. You may want to +retry +as this will randomly reselect an outproxy from the pool you have defined +here +(if you have more than one configured). +If you continue to have trouble you may want to edit your outproxy list +here. +

Could not find the following destination:

diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 8f59afd63..352ae7679 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.184 $ $Date: 2005/04/12 10:22:12 $"; + public final static String ID = "$Revision: 1.185 $ $Date: 2005/04/16 19:59:51 $"; public final static String VERSION = "0.5.0.6"; - public final static long BUILD = 2; + public final static long BUILD = 3; 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/tunnel/pool/TunnelBuilder.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java index ec9caebda..2655fa204 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelBuilder.java @@ -38,7 +38,7 @@ public class TunnelBuilder { return; } OnCreatedJob onCreated = new OnCreatedJob(ctx, pool, cfg); - RetryJob onFailed= (zeroHop ? null : new RetryJob(ctx, pool)); + RetryJob onFailed= new RetryJob(ctx, pool); // queue up a job to request the endpoint to join the tunnel, which then // requeues up another job for earlier hops, etc, until it reaches the // gateway. after the gateway is confirmed, onCreated is fired diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java index faab7b5af..457848b4d 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java @@ -41,7 +41,7 @@ public class TunnelPool { * etc. On overflow, the necessary additional tunnels are built by the * RefreshJob */ - private static final int MAX_BUILDS_PER_MINUTE = 5; + private static final int MAX_BUILDS_PER_MINUTE = 10; public TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel, TunnelBuilder builder) { _context = ctx; diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java index 1691ec1a4..4367b437a 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -41,6 +41,12 @@ public class TunnelPoolManager implements TunnelManagerFacade { /** max # of concurrent build requests */ private int _maxOutstandingBuilds; + private static final String PROP_MAX_OUTSTANDING_BUILDS = "router.tunnel.maxConcurrentBuilds"; + private static final int DEFAULT_MAX_OUTSTANDING_BUILDS = 20; + + private static final String PROP_THROTTLE_CONCURRENT_TUNNELS = "router.tunnel.shouldThrottle"; + private static final boolean DEFAULT_THROTTLE_CONCURRENT_TUNNELS = false; + public TunnelPoolManager(RouterContext ctx) { _context = ctx; _log = ctx.logManager().getLog(TunnelPoolManager.class); @@ -54,13 +60,13 @@ public class TunnelPoolManager implements TunnelManagerFacade { _clientInboundPools = new HashMap(4); _clientOutboundPools = new HashMap(4); _outstandingBuilds = 0; - _maxOutstandingBuilds = 20; - String max = ctx.getProperty("router.tunnel.maxConcurrentBuilds", "20"); + _maxOutstandingBuilds = DEFAULT_MAX_OUTSTANDING_BUILDS; + String max = ctx.getProperty(PROP_MAX_OUTSTANDING_BUILDS, String.valueOf(DEFAULT_MAX_OUTSTANDING_BUILDS)); if (max != null) { try { _maxOutstandingBuilds = Integer.parseInt(max); } catch (NumberFormatException nfe) { - _maxOutstandingBuilds = 20; + _maxOutstandingBuilds = DEFAULT_MAX_OUTSTANDING_BUILDS; } } @@ -266,6 +272,9 @@ public class TunnelPoolManager implements TunnelManagerFacade { * @return how many are allowed to be built */ int allocateBuilds(int wanted) { + boolean shouldThrottle = shouldThrottleTunnels(); + if (!shouldThrottle) return wanted; + synchronized (this) { if (_outstandingBuilds >= _maxOutstandingBuilds) { // ok, as a failsafe, always let one through @@ -284,6 +293,11 @@ public class TunnelPoolManager implements TunnelManagerFacade { } } } + + private boolean shouldThrottleTunnels() { + Boolean rv = Boolean.valueOf(_context.getProperty(PROP_THROTTLE_CONCURRENT_TUNNELS, ""+DEFAULT_THROTTLE_CONCURRENT_TUNNELS)); + return rv.booleanValue(); + } void buildComplete() { synchronized (this) {