package net.i2p.router.tunnel.pool; import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.router.JobImpl; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.tunnel.TunnelCreatorConfig; /** * This runs twice for each tunnel. * The first time, remove it from the LeaseSet. * The second time, stop accepting data for it. */ class ExpireJob extends JobImpl { private final TunnelPool _pool; private final TunnelCreatorConfig _cfg; private final AtomicBoolean _leaseUpdated = new AtomicBoolean(false); private final long _dropAfter; private static final long OB_EARLY_EXPIRE = 30*1000; private static final long IB_EARLY_EXPIRE = OB_EARLY_EXPIRE + 7500; public ExpireJob(RouterContext ctx, TunnelCreatorConfig cfg, TunnelPool pool) { super(ctx); _pool = pool; _cfg = cfg; // we act as if this tunnel expires a random skew before it actually does // so we rebuild out of sync. otoh, we will honor tunnel messages on it // up through the full lifetime of the tunnel, plus a clock skew, since // others may be sending to the published lease expirations // Also skew the inbound away from the outbound long expire = cfg.getExpiration(); if (_pool.getSettings().isInbound()) { // wait extra long for IB so we don't drop msgs that // got all the way to us. _dropAfter = expire + (2 * Router.CLOCK_FUDGE_FACTOR); expire -= IB_EARLY_EXPIRE + ctx.random().nextLong(IB_EARLY_EXPIRE); } else { _dropAfter = expire + Router.CLOCK_FUDGE_FACTOR; expire -= OB_EARLY_EXPIRE + ctx.random().nextLong(OB_EARLY_EXPIRE); } // See comments in TunnelPool.locked_buildNewLeaseSet cfg.setExpiration(expire); getTiming().setStartAfter(expire); } public String getName() { return "Expire our tunnel"; } public void runJob() { if (_leaseUpdated.compareAndSet(false,true)) { // First run _pool.removeTunnel(_cfg); // noop for outbound _pool.refreshLeaseSet(); long timeToDrop = _dropAfter - getContext().clock().now(); requeue(timeToDrop); } else { // Second run // already removed/refreshed, but now lets make it // so we dont even honor the tunnel anymore getContext().tunnelDispatcher().remove(_cfg); } } }