* 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
This commit is contained in:
zzz
2012-08-26 13:02:11 +00:00
parent 9ba6c293ed
commit b01cf32321
5 changed files with 91 additions and 66 deletions

View File

@ -3,6 +3,7 @@ package net.i2p.client.streaming;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.client.I2PSession; import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException; import net.i2p.client.I2PSessionException;
import net.i2p.client.SendMessageOptions;
import net.i2p.data.ByteArray; import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache; import net.i2p.util.ByteCache;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -22,6 +23,16 @@ class PacketQueue {
private final ConnectionManager _connectionManager; private final ConnectionManager _connectionManager;
private final ByteCache _cache = ByteCache.getInstance(64, 36*1024); 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) { public PacketQueue(I2PAppContext context, I2PSession session, ConnectionManager mgr) {
_context = context; _context = context;
_session = session; _session = session;
@ -88,24 +99,34 @@ class PacketQueue {
// we want the router to expire it a little before we do, // we want the router to expire it a little before we do,
// so if we retransmit it will use a new tunnel/lease combo // so if we retransmit it will use a new tunnel/lease combo
expires = rpe.getNextSendTime() - 500; expires = rpe.getNextSendTime() - 500;
SendMessageOptions options = new SendMessageOptions();
if (expires > 0) if (expires > 0)
// I2PSessionImpl2 options.setDate(expires);
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires); if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) {
// I2PSessionMuxedImpl Connection con = packet.getConnection();
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires, if (con != null && con.isInbound())
// I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); options.setSendLeaseSet(false);
// I2PSessionMuxedImpl no tags options.setTagsToSend(INITIAL_TAGS_TO_SEND);
sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, expires, options.setTagThreshold(MIN_TAG_THRESHOLD);
I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort()); } else if (packet.isFlagSet(FLAGS_FINAL_TAGS)) {
else options.setSendLeaseSet(false);
// I2PSessionImpl2 options.setTagsToSend(FINAL_TAGS_TO_SEND);
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, 0); options.setTagThreshold(FINAL_TAG_THRESHOLD);
// I2PSessionMuxedImpl } else {
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, Connection con = packet.getConnection();
// I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); if (con != null) {
// I2PSessionMuxedImpl no tags if (con.isInbound() && con.getLifetime() < 2*60*1000)
sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, options.setSendLeaseSet(false);
I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort()); // 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(); end = _context.clock().now();
if ( (end-begin > 1000) && (_log.shouldLog(Log.WARN)) ) if ( (end-begin > 1000) && (_log.shouldLog(Log.WARN)) )

View File

@ -21,39 +21,32 @@ public class SendMessageOptions extends DateAndFlags {
/** /**
* 1 means don't send, 0 means default * 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: * Tags to send field:
*<pre> * see below for possible values
* 000 - default
* 001 - 2
* 010 - 4
* 011 - 8
* 100 - 16
* 101 - 32
* 110 - 64
* 111 - 128
*</pre>
*/ */
private static final int TAGS_SEND_MASK = 0x000e; private static final int TAGS_SEND_MASK = 0x000f;
private static final int MAX_SEND_TAGS = 128; /**
* 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: * Tags threshold field:
*<pre> * see below for possible values
* 000 - default
* 001 - 1
* 010 - 2
* 011 - 4
* 100 - 8
* 101 - 16
* 110 - 32
* 111 - 64
*</pre>
*/ */
private static final int TAGS_REQD_MASK = 0x0070; private static final int TAGS_REQD_MASK = 0x00f0;
private static final int MAX_REQD_TAGS = 64; /** 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 */ /** default true */
public void setSendLeaseSet(boolean yes) { public void setSendLeaseSet(boolean yes) {
@ -76,19 +69,19 @@ public class SendMessageOptions extends DateAndFlags {
/** /**
* If we are low on tags, send this many. * If we are low on tags, send this many.
* Power of 2 recommended - rounds down. * 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 * @param tags 0 or 2 to 128
*/ */
public void setTagsToSend(int tags) { public void setTagsToSend(int tags) {
if (tags < 0) if (tags < 0)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
_flags &= ~TAGS_SEND_MASK; _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. * 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() { public int getTagsToSend() {
return getTagsToSend(_flags); return getTagsToSend(_flags);
@ -96,29 +89,29 @@ public class SendMessageOptions extends DateAndFlags {
/** /**
* If we are low on tags, send this many. * 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) { public static int getTagsToSend(int flags) {
int exp = (flags & TAGS_SEND_MASK) >> 1; int exp = (flags & TAGS_SEND_MASK);
return 2 * expToLin(exp); return codeToVal(exp, TAGS_SEND);
} }
/** /**
* Low tag threshold. If less than this many, send more. * Low tag threshold. If less than this many, send more.
* Power of 2 recommended - rounds down. * Power of 2 recommended - rounds down.
* default 0, meaning unset * default 0, meaning unset, use the SKM config (default 30)
* @param tags 0 to 64 * @param tags 0 to 90
*/ */
public void setTagThreshold(int tags) { public void setTagThreshold(int tags) {
if (tags < 0) if (tags < 0)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
_flags &= ~TAGS_REQD_MASK; _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. * 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() { public int getTagThreshold() {
return getTagThreshold(_flags); return getTagThreshold(_flags);
@ -126,26 +119,26 @@ public class SendMessageOptions extends DateAndFlags {
/** /**
* Low tag threshold. If less than this many, send more. * 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) { public static int getTagThreshold(int flags) {
int exp = (flags & TAGS_REQD_MASK) >> 4; int exp = (flags & TAGS_REQD_MASK) >> 4;
return expToLin(exp); return codeToVal(exp, TAGS_REQD);
} }
/** rounds down */ /** rounds down */
private static int linToExp(int lin) { private static int valToCode(int val, int[] codes) {
int exp = 0; // special case, round up so we don't turn it into default
while (lin > 0) { if (val > 0 && val <= codes[1])
exp++; return 1;
lin >>= 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) { private static int codeToVal(int code, int[] codes) {
if (exp <= 0) return codes[code];
return 0;
return 1 << (exp - 1);
} }
} }

View File

@ -38,6 +38,8 @@ public class ElGamalAESEngine {
private final Log _log; private final Log _log;
private final static int MIN_ENCRYPTED_SIZE = 80; // smallest possible resulting size private final static int MIN_ENCRYPTED_SIZE = 80; // smallest possible resulting size
private final I2PAppContext _context; private final I2PAppContext _context;
/** enforced since release 0.6 */
public static final int MAX_TAGS_RECEIVED = 200;
public ElGamalAESEngine(I2PAppContext ctx) { public ElGamalAESEngine(I2PAppContext ctx) {
_context = ctx; _context = ctx;
@ -328,7 +330,7 @@ public class ElGamalAESEngine {
//ByteArrayInputStream bais = new ByteArrayInputStream(decrypted); //ByteArrayInputStream bais = new ByteArrayInputStream(decrypted);
int cur = 0; int cur = 0;
long numTags = DataHelper.fromLong(decrypted, cur, 2); 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); if (numTags > 0) tags = new ArrayList((int)numTags);
cur += 2; cur += 2;
//_log.debug("# tags: " + numTags); //_log.debug("# tags: " + numTags);

View File

@ -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 2012-08-25 kytv
* Dutch and German translation updates from Transifex * Dutch and German translation updates from Transifex
* Router console typo fixes (#701) * Router console typo fixes (#701)

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 18; public final static long BUILD = 19;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";