예제 #1
0
  private static void buildZeroHop(
      RouterContext ctx, TunnelPool pool, PooledTunnelCreatorConfig cfg, BuildExecutor exec) {
    Log log = ctx.logManager().getLog(BuildRequestor.class);
    if (log.shouldLog(Log.DEBUG)) log.debug("Build zero hop tunnel " + cfg);

    exec.buildComplete(cfg, pool);
    if (cfg.isInbound()) ctx.tunnelDispatcher().joinInbound(cfg);
    else ctx.tunnelDispatcher().joinOutbound(cfg);
    pool.addTunnel(cfg);
    exec.buildSuccessful(cfg);
    ExpireJob expireJob = new ExpireJob(ctx, cfg, pool);
    cfg.setExpireJob(expireJob);
    ctx.jobQueue().addJob(expireJob);
    // can it get much easier?
  }
예제 #2
0
  /**
   * Send out a build request message.
   *
   * @param cfg ReplyMessageId must be set
   * @return success
   */
  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 true;
    }

    Log log = ctx.logManager().getLog(BuildRequestor.class);
    cfg.setTunnelPool(pool);

    TunnelInfo pairedTunnel = null;
    Hash farEnd = cfg.getFarEnd();
    TunnelManagerFacade mgr = ctx.tunnelManager();
    boolean isInbound = pool.getSettings().isInbound();
    if (pool.getSettings().isExploratory() || !usePairedTunnels(ctx)) {
      if (isInbound) pairedTunnel = mgr.selectOutboundExploratoryTunnel(farEnd);
      else pairedTunnel = mgr.selectInboundExploratoryTunnel(farEnd);
    } else {
      // building a client tunnel
      if (isInbound)
        pairedTunnel = mgr.selectOutboundTunnel(pool.getSettings().getDestination(), farEnd);
      else pairedTunnel = mgr.selectInboundTunnel(pool.getSettings().getDestination(), farEnd);
      if (pairedTunnel == null) {
        if (isInbound) {
          // random more reliable than closest ??
          // pairedTunnel = mgr.selectOutboundExploratoryTunnel(farEnd);
          pairedTunnel = mgr.selectOutboundTunnel();
          if (pairedTunnel != null
              && pairedTunnel.getLength() <= 1
              && mgr.getOutboundSettings().getLength() > 0
              && 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 {
          // random more reliable than closest ??
          // pairedTunnel = mgr.selectInboundExploratoryTunnel(farEnd);
          pairedTunnel = mgr.selectInboundTunnel();
          if (pairedTunnel != null
              && pairedTunnel.getLength() <= 1
              && mgr.getInboundSettings().getLength() > 0
              && mgr.getInboundSettings().getLength() + mgr.getInboundSettings().getLengthVariance()
                  > 0) {
            // ditto
            pairedTunnel = null;
          }
        }
        if (pairedTunnel != null && log.shouldLog(Log.INFO))
          log.info("Couldn't find a paired tunnel for " + cfg + ", using exploratory tunnel");
      }
    }
    if (pairedTunnel == null) {
      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 an exploratory tunnel? We are in big trouble.
      // Let's not spin through here too fast.
      // But don't let a client tunnel waiting for exploratories slow things down too much,
      // as there may be other tunnel pools who can build
      int ms = pool.getSettings().isExploratory() ? 250 : 25;
      try {
        Thread.sleep(ms);
      } catch (InterruptedException ie) {
      }
      return false;
    }

    // long beforeCreate = System.currentTimeMillis();
    TunnelBuildMessage msg = createTunnelBuildMessage(ctx, pool, cfg, pairedTunnel, exec);
    // 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 false;
    }

    // cfg.setPairedTunnel(pairedTunnel);

    // 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 "
                + cfg.getPeer(0)
                + " for "
                + cfg
                + " waiting for the reply of "
                + cfg.getReplyMessageId());
      // send it out a tunnel targetting the first hop
      // TODO - would be nice to have a TunnelBuildFirstHopFailJob queued if the
      // pairedTunnel is zero-hop, but no way to do that?
      ctx.tunnelDispatcher().dispatchOutbound(msg, pairedTunnel.getSendTunnelId(0), cfg.getPeer(0));
    } else {
      if (log.shouldLog(Log.INFO))
        log.info(
            "Sending the tunnel build request directly to "
                + cfg.getPeer(1)
                + " for "
                + cfg
                + " waiting for the reply of "
                + cfg.getReplyMessageId()
                + " with msgId="
                + msg.getUniqueId());
      // send it directly to the first hop
      // Add some fuzz to the TBM expiration to make it harder to guess how many hops
      // or placement in the tunnel
      msg.setMessageExpiration(
          ctx.clock().now() + BUILD_MSG_TIMEOUT + ctx.random().nextLong(20 * 1000));
      // We set the OutNetMessage expiration much shorter, so that the
      // TunnelBuildFirstHopFailJob fires before the 13s build expiration.
      RouterInfo peer = ctx.netDb().lookupRouterInfoLocally(cfg.getPeer(1));
      if (peer == null) {
        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 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));
    return true;
  }