forked from I2P_Developers/i2p.i2p
Tunnels: Immediately fail outbound tunnels when
we can't connect to the first hop by attaching an onSendFailJob in OutboundSender. Check if failed in isValidTunnel()
This commit is contained in:
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Git";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 1;
|
||||
public final static long BUILD = 2;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.i2p.data.i2np.TunnelDataMessage;
|
||||
import net.i2p.router.JobImpl;
|
||||
import net.i2p.router.OutNetMessage;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.tunnel.pool.PooledTunnelCreatorConfig;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -18,19 +19,22 @@ import net.i2p.util.Log;
|
||||
class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final TunnelCreatorConfig _config;
|
||||
private final PooledTunnelCreatorConfig _config;
|
||||
private RouterInfo _nextHopCache;
|
||||
private final int _priority;
|
||||
// same job used for all messages
|
||||
private final JobImpl _sendFailJob;
|
||||
|
||||
private static final long MAX_LOOKUP_TIME = 15*1000;
|
||||
private static final int PRIORITY = OutNetMessage.PRIORITY_MY_DATA;
|
||||
|
||||
public OutboundReceiver(RouterContext ctx, TunnelCreatorConfig cfg) {
|
||||
public OutboundReceiver(RouterContext ctx, PooledTunnelCreatorConfig cfg) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(OutboundReceiver.class);
|
||||
_config = cfg;
|
||||
_nextHopCache = _context.netDb().lookupRouterInfoLocally(_config.getPeer(1));
|
||||
_priority = PRIORITY + cfg.getPriority();
|
||||
_sendFailJob = new SendFailedJob(ctx);
|
||||
// all createRateStat() in TunnelDispatcher
|
||||
}
|
||||
|
||||
@@ -42,10 +46,11 @@ class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("received encrypted, sending out " + _config + ": " + msg);
|
||||
RouterInfo ri = _nextHopCache;
|
||||
if (ri == null)
|
||||
if (ri == null) {
|
||||
ri = _context.netDb().lookupRouterInfoLocally(_config.getPeer(1));
|
||||
if (ri != null) {
|
||||
_nextHopCache = ri;
|
||||
}
|
||||
if (ri != null) {
|
||||
send(msg, ri);
|
||||
return msg.getUniqueId();
|
||||
} else {
|
||||
@@ -54,7 +59,7 @@ class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
_log.warn("lookup of " + _config.getPeer(1)
|
||||
+ " required for " + msg);
|
||||
_context.netDb().lookupRouterInfo(_config.getPeer(1), new SendJob(_context, msg),
|
||||
new FailedJob(_context), MAX_LOOKUP_TIME);
|
||||
new LookupFailedJob(_context), MAX_LOOKUP_TIME);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -72,6 +77,8 @@ class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("forwarding encrypted data out " + _config + ": " + msg.getUniqueId());
|
||||
OutNetMessage m = new OutNetMessage(_context, msg, msg.getMessageExpiration(), _priority, ri);
|
||||
// set a job to fail the tunnel if we can't send the message
|
||||
m.setOnFailedSendJob(_sendFailJob);
|
||||
_context.outNetMessagePool().add(m);
|
||||
_config.incrementProcessedMessages();
|
||||
}
|
||||
@@ -102,9 +109,13 @@ class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
_context.statManager().addRateData("tunnel.outboundLookupSuccess", stat);
|
||||
}
|
||||
}
|
||||
|
||||
private class FailedJob extends JobImpl {
|
||||
public FailedJob(RouterContext ctx) {
|
||||
|
||||
/**
|
||||
* Immediately fail the tunnel if the lookup fails.
|
||||
* This should be very rare, we should always have the RI locally.
|
||||
*/
|
||||
private class LookupFailedJob extends JobImpl {
|
||||
public LookupFailedJob(RouterContext ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@@ -115,6 +126,27 @@ class OutboundReceiver implements TunnelGateway.Receiver {
|
||||
_log.warn("lookup of " + _config.getPeer(1)
|
||||
+ " failed for " + _config);
|
||||
_context.statManager().addRateData("tunnel.outboundLookupSuccess", 0);
|
||||
_config.tunnelFailedFirstHop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately fail the tunnel if the send fails
|
||||
*
|
||||
* @since 0.9.53
|
||||
*/
|
||||
private class SendFailedJob extends JobImpl {
|
||||
public SendFailedJob(RouterContext ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
public String getName() { return "OBGW send fail"; }
|
||||
|
||||
public void runJob() {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("send to " + _config.getPeer(1)
|
||||
+ " failed for " + _config);
|
||||
_config.tunnelFailedFirstHop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
|
||||
// _peakThroughput[i] = kBps*60;
|
||||
}
|
||||
****/
|
||||
|
||||
|
||||
/**
|
||||
* The tunnel failed a test, so (maybe) stop using it
|
||||
*
|
||||
@@ -220,7 +220,22 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
|
||||
return _failures.incrementAndGet() <= MAX_CONSECUTIVE_TEST_FAILURES;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tunnel failed completely, so definitely stop using it
|
||||
*
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public void tunnelFailedCompletely() {
|
||||
_failures.addAndGet(MAX_CONSECUTIVE_TEST_FAILURES + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the tunnel failed completely?
|
||||
*
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public boolean getTunnelFailed() { return _failures.get() > MAX_CONSECUTIVE_TEST_FAILURES; }
|
||||
|
||||
public int getTunnelFailures() { return _failures.get(); }
|
||||
|
||||
public void testSuccessful(int ms) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.Service;
|
||||
import net.i2p.router.peermanager.PeerProfile;
|
||||
import net.i2p.router.tunnel.pool.PooledTunnelCreatorConfig;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -247,7 +248,7 @@ public class TunnelDispatcher implements Service {
|
||||
*
|
||||
* @return success; false if Tunnel ID is a duplicate
|
||||
*/
|
||||
public boolean joinOutbound(TunnelCreatorConfig cfg) {
|
||||
public boolean joinOutbound(PooledTunnelCreatorConfig cfg) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Outbound built successfully: " + cfg);
|
||||
TunnelGateway gw;
|
||||
|
||||
@@ -9,7 +9,7 @@ import net.i2p.router.tunnel.TunnelCreatorConfig;
|
||||
/**
|
||||
* Data about a tunnel we created
|
||||
*/
|
||||
class PooledTunnelCreatorConfig extends TunnelCreatorConfig {
|
||||
public class PooledTunnelCreatorConfig extends TunnelCreatorConfig {
|
||||
private final TunnelPool _pool;
|
||||
|
||||
/**
|
||||
@@ -47,6 +47,20 @@ class PooledTunnelCreatorConfig extends TunnelCreatorConfig {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* We failed to contact the first hop for an outbound tunnel,
|
||||
* so immediately stop using it.
|
||||
* For outbound non-zero-hop tunnels only.
|
||||
*
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public void tunnelFailedFirstHop() {
|
||||
if (isInbound() || getLength() <= 1)
|
||||
return;
|
||||
tunnelFailedCompletely();
|
||||
_pool.tunnelFailed(this, getPeer(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-null
|
||||
*/
|
||||
|
||||
@@ -536,8 +536,6 @@ public class TunnelPool {
|
||||
* Remove the tunnel.
|
||||
*/
|
||||
private void fail(TunnelInfo cfg) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(toString() + ": Tunnel failed: " + cfg);
|
||||
LeaseSet ls = null;
|
||||
synchronized (_tunnels) {
|
||||
boolean removed = _tunnels.remove(cfg);
|
||||
@@ -546,7 +544,9 @@ public class TunnelPool {
|
||||
if (_settings.isInbound() && !_settings.isExploratory())
|
||||
ls = locked_buildNewLeaseSet();
|
||||
}
|
||||
|
||||
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(toString() + ": Tunnel failed: " + cfg);
|
||||
_manager.tunnelFailed();
|
||||
|
||||
_lifetimeProcessed += cfg.getProcessedMessagesCount();
|
||||
|
||||
@@ -335,6 +335,8 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
}
|
||||
|
||||
public boolean isValidTunnel(Hash client, TunnelInfo tunnel) {
|
||||
if (tunnel.getTunnelFailed())
|
||||
return false;
|
||||
if (tunnel.getExpiration() < _context.clock().now())
|
||||
return false;
|
||||
TunnelPool pool;
|
||||
|
||||
Reference in New Issue
Block a user