diff --git a/apps/streaming/java/src/net/i2p/client/streaming/PacketQueue.java b/apps/streaming/java/src/net/i2p/client/streaming/PacketQueue.java index 5e7ae6acc..a41ecd012 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/PacketQueue.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/PacketQueue.java @@ -3,6 +3,7 @@ package net.i2p.client.streaming; import net.i2p.I2PAppContext; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; +import net.i2p.client.SendMessageOptions; import net.i2p.data.ByteArray; import net.i2p.util.ByteCache; import net.i2p.util.Log; @@ -22,6 +23,16 @@ class PacketQueue { private final ConnectionManager _connectionManager; private final ByteCache _cache = ByteCache.getInstance(64, 36*1024); + private static final int FLAGS_INITIAL_TAGS = Packet.FLAG_SYNCHRONIZE; + private static final int FLAGS_FINAL_TAGS = Packet.FLAG_CLOSE | + Packet.FLAG_RESET | + Packet.FLAG_ECHO; + private static final int INITIAL_TAGS_TO_SEND = 32; + private static final int MIN_TAG_THRESHOLD = 20; + private static final int TAG_WINDOW_FACTOR = 5; + private static final int FINAL_TAGS_TO_SEND = 4; + private static final int FINAL_TAG_THRESHOLD = 2; + public PacketQueue(I2PAppContext context, I2PSession session, ConnectionManager mgr) { _context = context; _session = session; @@ -88,24 +99,34 @@ class PacketQueue { // we want the router to expire it a little before we do, // so if we retransmit it will use a new tunnel/lease combo expires = rpe.getNextSendTime() - 500; + SendMessageOptions options = new SendMessageOptions(); if (expires > 0) - // I2PSessionImpl2 - //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires); - // I2PSessionMuxedImpl - //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires, - // I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); - // I2PSessionMuxedImpl no tags - sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, expires, - I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort()); - else - // I2PSessionImpl2 - //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, 0); - // I2PSessionMuxedImpl - //sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, - // I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); - // I2PSessionMuxedImpl no tags - sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, - I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort()); + options.setDate(expires); + if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) { + Connection con = packet.getConnection(); + if (con != null && con.isInbound()) + options.setSendLeaseSet(false); + options.setTagsToSend(INITIAL_TAGS_TO_SEND); + options.setTagThreshold(MIN_TAG_THRESHOLD); + } else if (packet.isFlagSet(FLAGS_FINAL_TAGS)) { + options.setSendLeaseSet(false); + options.setTagsToSend(FINAL_TAGS_TO_SEND); + options.setTagThreshold(FINAL_TAG_THRESHOLD); + } else { + Connection con = packet.getConnection(); + if (con != null) { + if (con.isInbound() && con.getLifetime() < 2*60*1000) + options.setSendLeaseSet(false); + // increase threshold with higher window sizes to prevent stalls + // after tag delivery failure + int wdw = con.getOptions().getWindowSize(); + int thresh = Math.max(MIN_TAG_THRESHOLD, wdw * TAG_WINDOW_FACTOR); + options.setTagThreshold(thresh); + } + } + sent = _session.sendMessage(packet.getTo(), buf, 0, size, + I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort(), + options); end = _context.clock().now(); if ( (end-begin > 1000) && (_log.shouldLog(Log.WARN)) ) diff --git a/core/java/src/net/i2p/client/SendMessageOptions.java b/core/java/src/net/i2p/client/SendMessageOptions.java index 8706a7659..996986495 100644 --- a/core/java/src/net/i2p/client/SendMessageOptions.java +++ b/core/java/src/net/i2p/client/SendMessageOptions.java @@ -21,39 +21,32 @@ public class SendMessageOptions extends DateAndFlags { /** * 1 means don't send, 0 means default */ - private static final int LS_MASK = 0x0001; + private static final int LS_MASK = 0x0100; /** * Tags to send field: - *
- * 000 - default - * 001 - 2 - * 010 - 4 - * 011 - 8 - * 100 - 16 - * 101 - 32 - * 110 - 64 - * 111 - 128 - *+ * see below for possible values */ - private static final int TAGS_SEND_MASK = 0x000e; - private static final int MAX_SEND_TAGS = 128; + private static final int TAGS_SEND_MASK = 0x000f; + /** + * Possible values. Configured values will be rounded down. + * Note that ElGamalAESEngine enforces a max of 200 on receive. + */ + private static final int[] TAGS_SEND = { + 0, 2, 4, 6, 8, 12, 16, 24, + 32, 40, 51, 64, 80, 100, 125, 160 + }; /** * Tags threshold field: - *
- * 000 - default - * 001 - 1 - * 010 - 2 - * 011 - 4 - * 100 - 8 - * 101 - 16 - * 110 - 32 - * 111 - 64 - *+ * see below for possible values */ - private static final int TAGS_REQD_MASK = 0x0070; - private static final int MAX_REQD_TAGS = 64; + private static final int TAGS_REQD_MASK = 0x00f0; + /** Possible values. Configured values will be rounded down. */ + private static final int[] TAGS_REQD = { + 0, 2, 3, 6, 9, 14, 20, 27, + 35, 45, 57, 72, 92, 117, 147, 192 + }; /** default true */ public void setSendLeaseSet(boolean yes) { @@ -76,19 +69,19 @@ public class SendMessageOptions extends DateAndFlags { /** * If we are low on tags, send this many. * Power of 2 recommended - rounds down. - * default 0, meaning unset + * default 0, meaning unset, use the SKM config (default 40) * @param tags 0 or 2 to 128 */ public void setTagsToSend(int tags) { if (tags < 0) throw new IllegalArgumentException(); _flags &= ~TAGS_SEND_MASK; - _flags |= linToExp(Math.min(tags, MAX_SEND_TAGS) / 2) << 1; + _flags |= valToCode(tags, TAGS_SEND); } /** * If we are low on tags, send this many. - * @return default 0, meaning unset + * @return default 0, meaning unset, use the SKM config (default 40) */ public int getTagsToSend() { return getTagsToSend(_flags); @@ -96,29 +89,29 @@ public class SendMessageOptions extends DateAndFlags { /** * If we are low on tags, send this many. - * @return default 0, meaning unset + * @return default 0, meaning unset, use the SKM config (default 40) */ public static int getTagsToSend(int flags) { - int exp = (flags & TAGS_SEND_MASK) >> 1; - return 2 * expToLin(exp); + int exp = (flags & TAGS_SEND_MASK); + return codeToVal(exp, TAGS_SEND); } /** * Low tag threshold. If less than this many, send more. * Power of 2 recommended - rounds down. - * default 0, meaning unset - * @param tags 0 to 64 + * default 0, meaning unset, use the SKM config (default 30) + * @param tags 0 to 90 */ public void setTagThreshold(int tags) { if (tags < 0) throw new IllegalArgumentException(); _flags &= ~TAGS_REQD_MASK; - _flags |= linToExp(Math.min(tags, MAX_REQD_TAGS)) << 4; + _flags |= valToCode(tags, TAGS_REQD) << 4; } /** * Low tag threshold. If less than this many, send more. - * @return default 0, meaning unset + * @return default 0, meaning unset, use the SKM config (default 30) */ public int getTagThreshold() { return getTagThreshold(_flags); @@ -126,26 +119,26 @@ public class SendMessageOptions extends DateAndFlags { /** * Low tag threshold. If less than this many, send more. - * @return default 0, meaning unset + * @return default 0, meaning unset, use the SKM config (default 30) */ public static int getTagThreshold(int flags) { int exp = (flags & TAGS_REQD_MASK) >> 4; - return expToLin(exp); + return codeToVal(exp, TAGS_REQD); } /** rounds down */ - private static int linToExp(int lin) { - int exp = 0; - while (lin > 0) { - exp++; - lin >>= 1; + private static int valToCode(int val, int[] codes) { + // special case, round up so we don't turn it into default + if (val > 0 && val <= codes[1]) + return 1; + for (int i = 1; i < codes.length; i++) { + if (val < codes[i]) + return i - 1; } - return exp; + return codes.length - 1; } - private static int expToLin(int exp) { - if (exp <= 0) - return 0; - return 1 << (exp - 1); + private static int codeToVal(int code, int[] codes) { + return codes[code]; } } diff --git a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java index e0ffff671..735a0d120 100644 --- a/core/java/src/net/i2p/crypto/ElGamalAESEngine.java +++ b/core/java/src/net/i2p/crypto/ElGamalAESEngine.java @@ -38,6 +38,8 @@ public class ElGamalAESEngine { private final Log _log; private final static int MIN_ENCRYPTED_SIZE = 80; // smallest possible resulting size private final I2PAppContext _context; + /** enforced since release 0.6 */ + public static final int MAX_TAGS_RECEIVED = 200; public ElGamalAESEngine(I2PAppContext ctx) { _context = ctx; @@ -328,7 +330,7 @@ public class ElGamalAESEngine { //ByteArrayInputStream bais = new ByteArrayInputStream(decrypted); int cur = 0; long numTags = DataHelper.fromLong(decrypted, cur, 2); - if ((numTags < 0) || (numTags > 200)) throw new Exception("Invalid number of session tags"); + if ((numTags < 0) || (numTags > MAX_TAGS_RECEIVED)) throw new Exception("Invalid number of session tags"); if (numTags > 0) tags = new ArrayList((int)numTags); cur += 2; //_log.debug("# tags: " + numTags); diff --git a/history.txt b/history.txt index a405276ee..aef4f4962 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,12 @@ +2012-08-26 zzz + * DataHelper: Trim trailing whitespace when loading properties + * NetDB: Increase floodfills, decrease flood redundancy + * SendMessageOptions: Increase tag fields to 4 bits and use + table lookup for more flexibility + * Streaming: Use packet type and current window size to adjust + number of tags sent and tag threshold, to improve + efficiency and reliability + 2012-08-25 kytv * Dutch and German translation updates from Transifex * Router console typo fixes (#701) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 80cfb9c84..5b1ba79e3 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 18; + public final static long BUILD = 19; /** for example "-test" */ public final static String EXTRA = "";