* Tunnels:

- Don't use fallback expl. tunnels as the paired tunnel
     for a client tunnel build.
     This will cause more client tunnel breakage but it's
     really bad to use a zero-hop for this.
   - Fix selection of an expl. tunnel close to a hash
   - Don't update build generation stat if the generation failed
   - log tweaks
This commit is contained in:
zzz
2013-10-26 20:52:56 +00:00
parent 4d24d65c1f
commit 7839c0fec3
5 changed files with 69 additions and 37 deletions

View File

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

View File

@ -471,7 +471,9 @@ class BuildExecutor implements Runnable {
cfg.setReplyMessageId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
} while (addToBuilding(cfg)); // if a dup, go araound again
}
BuildRequestor.request(_context, pool, cfg, this);
boolean ok = BuildRequestor.request(_context, pool, cfg, this);
if (!ok)
return;
long buildTime = System.currentTimeMillis() - beforeBuild;
if (cfg.getLength() <= 1)
_context.statManager().addRateData("tunnel.buildRequestZeroHopTime", buildTime, 0);

View File

@ -16,6 +16,7 @@ import net.i2p.router.JobImpl;
import net.i2p.router.OutNetMessage;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelInfo;
import net.i2p.router.TunnelManagerFacade;
import net.i2p.router.tunnel.BuildMessageGenerator;
import net.i2p.util.Log;
import net.i2p.util.VersionComparator;
@ -98,15 +99,19 @@ abstract class BuildRequestor {
}
/**
* Send out a build request message.
*
* @param cfg ReplyMessageId must be set
* @return success
*/
public static void request(RouterContext ctx, TunnelPool pool, PooledTunnelCreatorConfig cfg, BuildExecutor exec) {
public static boolean request(RouterContext ctx, TunnelPool pool,
PooledTunnelCreatorConfig cfg, BuildExecutor exec) {
// new style crypto fills in all the blanks, while the old style waits for replies to fill in the next hop, etc
prepare(ctx, cfg);
if (cfg.getLength() <= 1) {
buildZeroHop(ctx, pool, cfg, exec);
return;
return true;
}
Log log = ctx.logManager().getLog(BuildRequestor.class);
@ -114,49 +119,66 @@ abstract class BuildRequestor {
TunnelInfo pairedTunnel = null;
Hash farEnd = cfg.getFarEnd();
TunnelManagerFacade mgr = ctx.tunnelManager();
boolean isInbound = pool.getSettings().isInbound();
if (pool.getSettings().isExploratory() || !usePairedTunnels(ctx)) {
if (pool.getSettings().isInbound())
pairedTunnel = ctx.tunnelManager().selectOutboundExploratoryTunnel(farEnd);
if (isInbound)
pairedTunnel = mgr.selectOutboundExploratoryTunnel(farEnd);
else
pairedTunnel = ctx.tunnelManager().selectInboundExploratoryTunnel(farEnd);
pairedTunnel = mgr.selectInboundExploratoryTunnel(farEnd);
} else {
if (pool.getSettings().isInbound())
pairedTunnel = ctx.tunnelManager().selectOutboundTunnel(pool.getSettings().getDestination(), farEnd);
// building a client tunnel
if (isInbound)
pairedTunnel = mgr.selectOutboundTunnel(pool.getSettings().getDestination(), farEnd);
else
pairedTunnel = ctx.tunnelManager().selectInboundTunnel(pool.getSettings().getDestination(), farEnd);
}
if (pairedTunnel == null) {
if (log.shouldLog(Log.WARN))
log.warn("Couldn't find a paired tunnel for " + cfg + ", fall back on exploratory tunnels for pairing");
if (!pool.getSettings().isExploratory() && usePairedTunnels(ctx))
if (pool.getSettings().isInbound())
pairedTunnel = ctx.tunnelManager().selectOutboundExploratoryTunnel(farEnd);
else
pairedTunnel = ctx.tunnelManager().selectInboundExploratoryTunnel(farEnd);
pairedTunnel = mgr.selectInboundTunnel(pool.getSettings().getDestination(), farEnd);
if (pairedTunnel == null) {
if (log.shouldLog(Log.INFO))
log.info("Couldn't find a paired tunnel for " + cfg + ", fall back on exploratory tunnels for pairing");
if (isInbound) {
pairedTunnel = mgr.selectOutboundExploratoryTunnel(farEnd);
if (pairedTunnel != null &&
pairedTunnel.getLength() <= 1 &&
mgr.getOutboundSettings().getLength() + mgr.getOutboundSettings().getLengthVariance() > 0) {
// don't build using a zero-hop expl.,
// as it is both very bad for anonomyity,
// and it takes a build slot away from exploratory
pairedTunnel = null;
}
} else {
pairedTunnel = mgr.selectInboundExploratoryTunnel(farEnd);
if (pairedTunnel != null &&
pairedTunnel.getLength() <= 1 &&
mgr.getInboundSettings().getLength() + mgr.getInboundSettings().getLengthVariance() > 0) {
// ditto
pairedTunnel = null;
}
}
}
}
if (pairedTunnel == null) {
if (log.shouldLog(Log.ERROR))
log.error("Tunnel build failed, as we couldn't find a paired tunnel for " + cfg);
if (log.shouldLog(Log.WARN))
log.warn("Tunnel build failed, as we couldn't find a paired tunnel for " + cfg);
exec.buildComplete(cfg, pool);
// Not even a zero-hop exploratory tunnel? We are in big trouble.
// Not even an exploratory tunnel? We are in big trouble.
// Let's not spin through here too fast.
try { Thread.sleep(250); } catch (InterruptedException ie) {}
return;
return false;
}
long beforeCreate = System.currentTimeMillis();
//long beforeCreate = System.currentTimeMillis();
TunnelBuildMessage msg = createTunnelBuildMessage(ctx, pool, cfg, pairedTunnel, exec);
long createTime = System.currentTimeMillis()-beforeCreate;
//long createTime = System.currentTimeMillis()-beforeCreate;
if (msg == null) {
if (log.shouldLog(Log.WARN))
log.warn("Tunnel build failed, as we couldn't create the tunnel build message for " + cfg);
exec.buildComplete(cfg, pool);
return;
return false;
}
//cfg.setPairedTunnel(pairedTunnel);
long beforeDispatch = System.currentTimeMillis();
//long beforeDispatch = System.currentTimeMillis();
if (cfg.isInbound()) {
if (log.shouldLog(Log.INFO))
log.info("Sending the tunnel build request " + msg.getUniqueId() + " out the tunnel " + pairedTunnel + " to "
@ -182,15 +204,16 @@ abstract class BuildRequestor {
if (log.shouldLog(Log.WARN))
log.warn("Could not find the next hop to send the outbound request to: " + cfg);
exec.buildComplete(cfg, pool);
return;
return false;
}
OutNetMessage outMsg = new OutNetMessage(ctx, msg, ctx.clock().now() + FIRST_HOP_TIMEOUT, PRIORITY, peer);
outMsg.setOnFailedSendJob(new TunnelBuildFirstHopFailJob(ctx, pool, cfg, exec));
ctx.outNetMessagePool().add(outMsg);
}
if (log.shouldLog(Log.DEBUG))
log.debug("Tunnel build message " + msg.getUniqueId() + " created in " + createTime
+ "ms and dispatched in " + (System.currentTimeMillis()-beforeDispatch));
//if (log.shouldLog(Log.DEBUG))
// log.debug("Tunnel build message " + msg.getUniqueId() + " created in " + createTime
// + "ms and dispatched in " + (System.currentTimeMillis()-beforeDispatch));
return true;
}
private static final String MIN_VARIABLE_VERSION = "0.7.12";
@ -266,8 +289,8 @@ abstract class BuildRequestor {
if (useVariable) {
msg = new VariableTunnelBuildMessage(ctx, SHORT_RECORDS);
order = new ArrayList(SHORT_ORDER);
if (log.shouldLog(Log.INFO))
log.info("Using new VTBM");
//if (log.shouldLog(Log.INFO))
// log.info("Using new VTBM");
} else {
msg = new TunnelBuildMessage(ctx);
order = new ArrayList(ORDER);

View File

@ -177,11 +177,11 @@ public class TunnelPoolManager implements TunnelManagerFacade {
* @since 0.8.10
*/
public TunnelInfo selectInboundExploratoryTunnel(Hash closestTo) {
TunnelInfo info = _inboundExploratory.selectTunnel();
TunnelInfo info = _inboundExploratory.selectTunnel(closestTo);
if (info == null) {
_inboundExploratory.buildFallback();
// still can be null, but probably not
info = _inboundExploratory.selectTunnel(closestTo);
info = _inboundExploratory.selectTunnel();
}
return info;
}
@ -221,11 +221,11 @@ public class TunnelPoolManager implements TunnelManagerFacade {
* @since 0.8.10
*/
public TunnelInfo selectOutboundExploratoryTunnel(Hash closestTo) {
TunnelInfo info = _outboundExploratory.selectTunnel();
TunnelInfo info = _outboundExploratory.selectTunnel(closestTo);
if (info == null) {
_outboundExploratory.buildFallback();
// still can be null, but probably not
info = _outboundExploratory.selectTunnel(closestTo);
info = _outboundExploratory.selectTunnel();
}
return info;
}