diff --git a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java index 5d6b37a96c140a9bb26e072268077f4afed409bf..2a04de8e4edbc3526d921953af741063d9df086b 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java @@ -30,6 +30,37 @@ import net.i2p.util.Log; * */ public class GarlicMessageBuilder { + + /** + * This was 100 since 0.6.1.10 (50 before that). It's important because: + * - Tags are 32 bytes. So it previously added 3200 bytes to an initial message. + * - Too many tags adds a huge overhead to short-duration connections + * (like http, datagrams, etc.) + * - Large messages have a much higher chance of being dropped due to + * one of their 1KB fragments being discarded by a tunnel participant. + * - This reduces the effective maximum datagram size because the client + * doesn't know when tags will be bundled, so the tag size must be + * subtracted from the maximum I2NP size or transport limit. + * + * Issues with too small a value: + * - When tags are sent, a reply leaseset (~1KB) is always bundled. + * Maybe don't need to bundle more than every minute or so + * rather than every time? + * - Does the number of tags (and the threshold of 20) limit the effective + * streaming lib window size? Should the threshold and the number of + * sent tags be variable based on the message rate? + * + * We have to be very careful if we implement an adaptive scheme, + * since the key manager is per-router, not per-local-dest. + * Or maybe that's a bad idea, and we need to move to a per-dest manager. + * This needs further investigation. + * + * So a value somewhat higher than the low threshold + * seems appropriate. + */ + private static final int DEFAULT_TAGS = 40; + private static final int LOW_THRESHOLD = 20; + public static int estimateAvailableTags(RouterContext ctx, PublicKey key) { SessionKey curKey = ctx.sessionKeyManager().getCurrentKey(key); if (curKey == null) @@ -41,7 +72,7 @@ public class GarlicMessageBuilder { return buildMessage(ctx, config, new SessionKey(), new HashSet()); } public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags) { - return buildMessage(ctx, config, wrappedKey, wrappedTags, 100); + return buildMessage(ctx, config, wrappedKey, wrappedTags, DEFAULT_TAGS); } public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver) { return buildMessage(ctx, config, wrappedKey, wrappedTags, numTagsToDeliver, false); @@ -74,13 +105,13 @@ public class GarlicMessageBuilder { if (log.shouldLog(Log.DEBUG)) log.debug("Available tags for encryption to " + key + ": " + availTags); - if (availTags < 20) { // arbitrary threshold + if (availTags < LOW_THRESHOLD) { // arbitrary threshold for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true)); if (log.shouldLog(Log.INFO)) - log.info("Less than 20 tags are available (" + availTags + "), so we're including more"); + log.info("Too few are available (" + availTags + "), so we're including more"); } else if (ctx.sessionKeyManager().getAvailableTimeLeft(key, curKey) < 60*1000) { - // if we have > 20 tags, but they expire in under 30 seconds, we want more + // if we have enough tags, but they expire in under 30 seconds, we want more for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true)); if (log.shouldLog(Log.INFO))