Tunnels: Count consecutive build timeouts per-pool

Use exploratory paired tunnel after too many timeouts
This commit is contained in:
zzz
2021-12-03 06:10:21 -05:00
parent 83b959c4a1
commit cfbdf8385d
2 changed files with 35 additions and 10 deletions

View File

@@ -77,6 +77,8 @@ abstract class BuildRequestor {
/** some randomization is added on to this */
private static final int BUILD_MSG_TIMEOUT = 60*1000;
private static final int MAX_CONSECUTIVE_CLIENT_BUILD_FAILS = 6;
/**
* "paired tunnels" means using a client's own inbound tunnel to receive the
* reply for an outbound build request, and using a client's own outbound tunnel
@@ -160,18 +162,27 @@ abstract class BuildRequestor {
}
} else {
// building a client tunnel
Hash from = settings.getDestination();
if (isInbound) {
pairedTunnel = mgr.selectOutboundTunnel(from, farEnd);
} else {
pairedTunnel = mgr.selectInboundTunnel(from, farEnd);
if (pairedTunnel != null) {
replySKM = ctx.clientManager().getClientSessionKeyManager(from);
if (replySKM == null && cfg.getGarlicReplyKeys() != null) {
// no client SKM, fall back to expl.
pairedTunnel = null;
int fails = pool.getConsecutiveBuildTimeouts();
if (fails < MAX_CONSECUTIVE_CLIENT_BUILD_FAILS) {
Hash from = settings.getDestination();
if (isInbound) {
pairedTunnel = mgr.selectOutboundTunnel(from, farEnd);
} else {
pairedTunnel = mgr.selectInboundTunnel(from, farEnd);
if (pairedTunnel != null) {
replySKM = ctx.clientManager().getClientSessionKeyManager(from);
if (replySKM == null && cfg.getGarlicReplyKeys() != null) {
// no client SKM, fall back to expl.
pairedTunnel = null;
}
}
}
} else {
// Force using an expl. tunnel as the paired tunnel
// This prevents us from being stuck for 10 minutes if the client pool
// has exactly one tunnel in the other direction and it's bad
if (log.shouldWarn())
log.warn(fails + " consecutive build timeouts for " + cfg + ", using exploratory tunnel");
}
if (pairedTunnel == null) {
if (isInbound) {

View File

@@ -10,6 +10,7 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
@@ -47,6 +48,7 @@ public class TunnelPool {
private long _lastLifetimeProcessed;
private final String _rateName;
private final long _firstInstalled;
private final AtomicInteger _consecutiveBuildTimeouts = new AtomicInteger();
private static final int TUNNEL_LIFETIME = 10*60*1000;
/** if less than one success in this many, reduce quantity (exploratory only) */
@@ -127,6 +129,7 @@ public class TunnelPool {
synchronized (_inProgress) {
_inProgress.clear();
}
_consecutiveBuildTimeouts.set(0);
}
/**
@@ -1200,6 +1203,7 @@ public class TunnelPool {
/**
* Remove from the _inprogress list and call addTunnel() if result is SUCCESS.
* Updates consecutive build timeout count.
*
* @since 0.9.53 added result parameter
*/
@@ -1213,15 +1217,18 @@ public class TunnelPool {
switch (result) {
case SUCCESS:
_consecutiveBuildTimeouts.set(0);
addTunnel(cfg);
break;
case REJECT:
case BAD_RESPONSE:
case DUP_ID:
_consecutiveBuildTimeouts.set(0);
break;
case TIMEOUT:
_consecutiveBuildTimeouts.incrementAndGet();
break;
case OTHER_FAILURE:
@@ -1230,6 +1237,13 @@ public class TunnelPool {
}
}
/**
* @since 0.9.53
*/
int getConsecutiveBuildTimeouts() {
return _consecutiveBuildTimeouts.get();
}
@Override
public String toString() {
if (_settings.isExploratory()) {