diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java index f71a19d424fd2cdbedc9dedbfe8ea2ef4b236f47..95eef4687a81f862b87a6faaab32c753c21fd09c 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java @@ -100,6 +100,8 @@ class ConnectionOptions extends I2PSocketOptionsImpl { private static final boolean DEFAULT_ANSWER_PINGS = true; private static final int DEFAULT_INACTIVITY_TIMEOUT = 90*1000; private static final int DEFAULT_INACTIVITY_ACTION = INACTIVITY_ACTION_SEND; + private static final int DEFAULT_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR = 1; + private static final int DEFAULT_SLOW_START_GROWTH_RATE_FACTOR = 1; /** @@ -327,8 +329,10 @@ class ConnectionOptions extends I2PSocketOptionsImpl { setInactivityTimeout(getInt(opts, PROP_INACTIVITY_TIMEOUT, DEFAULT_INACTIVITY_TIMEOUT)); setInactivityAction(getInt(opts, PROP_INACTIVITY_ACTION, DEFAULT_INACTIVITY_ACTION)); setInboundBufferSize(getMaxMessageSize() * (Connection.MAX_WINDOW_SIZE + 2)); - setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, 1)); - setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, 1)); + setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, + DEFAULT_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR)); + setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, + DEFAULT_SLOW_START_GROWTH_RATE_FACTOR)); // overrides default in super() setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT)); setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS)); @@ -378,9 +382,11 @@ class ConnectionOptions extends I2PSocketOptionsImpl { setInactivityAction(getInt(opts, PROP_INACTIVITY_ACTION, DEFAULT_INACTIVITY_ACTION)); setInboundBufferSize(getMaxMessageSize() * (Connection.MAX_WINDOW_SIZE + 2)); if (opts.contains(PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR)) - setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, 2)); + setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, + DEFAULT_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR)); if (opts.contains(PROP_SLOW_START_GROWTH_RATE_FACTOR)) - setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, 2)); + setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, + DEFAULT_SLOW_START_GROWTH_RATE_FACTOR)); if (opts.containsKey(PROP_CONNECT_TIMEOUT)) // wow 5 minutes!!! FIXME!! // overrides default in super() diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java index 250dae808b256443e7a7574b03e77a3c06ff27c7..9d353075cb0c1fb79e5bb4225094b176edc95d1e 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java @@ -23,6 +23,8 @@ import net.i2p.util.SimpleTimer; class ConnectionPacketHandler { private final I2PAppContext _context; private final Log _log; + + public static final int MAX_SLOW_START_WINDOW = 24; public ConnectionPacketHandler(I2PAppContext context) { _context = context; @@ -367,9 +369,16 @@ class ConnectionPacketHandler { // grow acked/N times (where N = the slow start factor) // always grow at least 1 int factor = con.getOptions().getSlowStartGrowthRateFactor(); - if (factor <= 1) - newWindowSize += acked; - else if (acked < factor) + if (factor <= 1) { + // above a certain point, don't grow exponentially + // as it often leads to a big packet loss (30-50) all at once that + // takes quite a while (a minute or more) to recover from, + // especially if crypto tags are lost + if (newWindowSize >= MAX_SLOW_START_WINDOW) + newWindowSize++; + else + newWindowSize = Math.min(MAX_SLOW_START_WINDOW, newWindowSize + acked); + } else if (acked < factor) newWindowSize++; else newWindowSize += acked / factor; diff --git a/apps/streaming/java/src/net/i2p/client/streaming/TCBShare.java b/apps/streaming/java/src/net/i2p/client/streaming/TCBShare.java index 15b8e937e727dfd02ffa9c73e79d494b2001ae21..d412aa36a16e6bf9245578fc664e31481aea3c10 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/TCBShare.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/TCBShare.java @@ -31,7 +31,7 @@ class TCBShare { private static final double RTT_DAMPENING = 0.75; private static final double WDW_DAMPENING = 0.75; private static final int MAX_RTT = ((int) Connection.MAX_RESEND_DELAY) / 2; - private static final int MAX_WINDOW_SIZE = Connection.MAX_WINDOW_SIZE / 4; + private static final int MAX_WINDOW_SIZE = ConnectionPacketHandler.MAX_SLOW_START_WINDOW; public TCBShare(I2PAppContext ctx, SimpleTimer2 timer) { _context = ctx; @@ -45,6 +45,7 @@ class TCBShare { _cleaner.cancel(); } + /** retrieve from cache */ public void updateOptsFromShare(Connection con) { Destination dest = con.getRemotePeer(); if (dest == null) @@ -65,6 +66,7 @@ class TCBShare { opts.setWindowSize(e.getWindowSize()); } + /** store to cache */ public void updateShareOpts(Connection con) { Destination dest = con.getRemotePeer(); if (dest == null)