Search in sources :

Example 1 with TunnelInfo

use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.

the class TunnelRenderer method renderPool.

private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException {
    List<TunnelInfo> tunnels = null;
    if (in == null)
        tunnels = new ArrayList<TunnelInfo>();
    else
        tunnels = in.listTunnels();
    if (outPool != null)
        tunnels.addAll(outPool.listTunnels());
    long processedIn = (in != null ? in.getLifetimeProcessed() : 0);
    long processedOut = (outPool != null ? outPool.getLifetimeProcessed() : 0);
    int live = 0;
    int maxLength = 1;
    for (int i = 0; i < tunnels.size(); i++) {
        TunnelInfo info = tunnels.get(i);
        int length = info.getLength();
        if (length > maxLength)
            maxLength = length;
    }
    out.write("<table class=\"tunneldisplay tunnels_client\"><tr><th title=\"" + _t("Inbound or outbound?") + ("\">") + _t("In/Out") + "</th><th>" + _t("Expiry") + "</th><th>" + _t("Usage") + "</th><th>" + _t("Gateway") + "</th>");
    if (maxLength > 3) {
        out.write("<th align=\"center\" colspan=\"" + (maxLength - 2));
        out.write("\">" + _t("Participants") + "</th>");
    } else if (maxLength == 3) {
        out.write("<th>" + _t("Participant") + "</th>");
    }
    if (maxLength > 1) {
        out.write("<th>" + _t("Endpoint") + "</th>");
    }
    out.write("</tr>\n");
    for (int i = 0; i < tunnels.size(); i++) {
        TunnelInfo info = tunnels.get(i);
        long timeLeft = info.getExpiration() - _context.clock().now();
        if (timeLeft <= 0)
            // don't display tunnels in their grace period
            continue;
        live++;
        boolean isInbound = info.isInbound();
        if (isInbound)
            out.write("<tr><td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"" + _t("Inbound") + "\"></td>");
        else
            out.write("<tr><td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"" + _t("Outbound") + "\"></td>");
        out.write("<td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>\n");
        int count = info.getProcessedMessagesCount() * 1024 / 1000;
        out.write("<td class=\"cells\" align=\"center\">" + count + " KB</td>\n");
        int length = info.getLength();
        for (int j = 0; j < length; j++) {
            Hash peer = info.getPeer(j);
            TunnelId id = (isInbound ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
            if (_context.routerHash().equals(peer)) {
                if (length < maxLength && length == 1 && isInbound) {
                    // pad before inbound zero hop
                    for (int k = 1; k < maxLength; k++) {
                        out.write("<td class=\"cells\" align=\"center\">&nbsp;</td>");
                    }
                }
                // Add empty content placeholders to force alignment.
                out.write(" <td class=\"cells\" align=\"center\"><span class=\"tunnel_peer tunnel_local\" title=\"" + _t("Locally hosted tunnel") + "\">" + _t("Local") + "</span>&nbsp;<span class=\"tunnel_id\" title=\"" + _t("Tunnel identity") + "\">" + (id == null ? "" : "" + id) + "</span><b class=\"tunnel_cap\" title=\"" + _t("Bandwidth tier") + "\"></b></td>");
            } else {
                String cap = getCapacity(peer);
                out.write(" <td class=\"cells\" align=\"center\"><span class=\"tunnel_peer\">" + netDbLink(peer) + "</span>&nbsp;<span class=\"nowrap\"><span class=\"tunnel_id\" title=\"" + _t("Tunnel identity") + "\">" + (id == null ? "" : " " + id) + "</span><b class=\"tunnel_cap\" title=\"" + _t("Bandwidth tier") + "\">" + cap + "</b></span></td>");
            }
            if (length < maxLength && ((length == 1 && !isInbound) || j == length - 2)) {
                // pad out outbound zero hop; non-zero-hop pads in middle
                for (int k = length; k < maxLength; k++) {
                    out.write("<td class=\"cells\" align=\"center\">&nbsp;</td>");
                }
            }
        }
        out.write("</tr>\n");
        if (info.isInbound())
            processedIn += count;
        else
            processedOut += count;
    }
    out.write("</table>\n");
    if (in != null) {
        // PooledTunnelCreatorConfig
        List<?> pending = in.listPending();
        if (!pending.isEmpty()) {
            out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("inbound") + "</b></center></div>\n");
            live += pending.size();
        }
    }
    if (outPool != null) {
        // PooledTunnelCreatorConfig
        List<?> pending = outPool.listPending();
        if (!pending.isEmpty()) {
            out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("outbound") + "</b></center></div>\n");
            live += pending.size();
        }
    }
    if (live <= 0)
        out.write("<div class=\"statusnotes\"><center><b>" + _t("No tunnels; waiting for the grace period to end.") + "</b></center></div>\n");
    out.write("<div class=\"statusnotes\"><center><b>" + _t("Lifetime bandwidth usage") + ":&nbsp;&nbsp;" + DataHelper.formatSize2Decimal(processedIn * 1024) + "B " + _t("in") + ", " + DataHelper.formatSize2Decimal(processedOut * 1024) + "B " + _t("out") + "</b></center></div>");
}
Also used : ArrayList(java.util.ArrayList) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 2 with TunnelInfo

use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.

the class BuildRequestor method request.

/**
 *  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;
    }
    // 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);
    }
    // + "ms and dispatched in " + (System.currentTimeMillis()-beforeDispatch));
    return true;
}
Also used : OutNetMessage(net.i2p.router.OutNetMessage) Log(net.i2p.util.Log) RouterInfo(net.i2p.data.router.RouterInfo) VariableTunnelBuildMessage(net.i2p.data.i2np.VariableTunnelBuildMessage) TunnelBuildMessage(net.i2p.data.i2np.TunnelBuildMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelManagerFacade(net.i2p.router.TunnelManagerFacade)

Example 3 with TunnelInfo

use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.

the class ExploratoryPeerSelector method selectPeers.

/**
 * Returns ENDPOINT FIRST, GATEWAY LAST!!!!
 * In: us .. closest .. middle .. IBGW
 * Out: OBGW .. middle .. closest .. us
 *
 * @return ordered list of Hash objects (one per peer) specifying what order
 *         they should appear in a tunnel (ENDPOINT FIRST).  This includes
 *         the local router in the list.  If there are no tunnels or peers
 *         to build through, and the settings reject 0 hop tunnels, this will
 *         return null.
 */
public List<Hash> selectPeers(TunnelPoolSettings settings) {
    int length = getLength(settings);
    if (length < 0) {
        if (log.shouldLog(Log.DEBUG))
            log.debug("Length requested is zero: " + settings);
        return null;
    }
    // if (false && shouldSelectExplicit(settings)) {
    // List<Hash> rv = selectExplicit(settings, length);
    // if (l.shouldLog(Log.DEBUG))
    // l.debug("Explicit peers selected: " + rv);
    // return rv;
    // }
    boolean isInbound = settings.isInbound();
    Set<Hash> exclude = getExclude(isInbound, true);
    exclude.add(ctx.routerHash());
    // special cases
    boolean nonzero = length > 0;
    boolean exploreHighCap = nonzero && shouldPickHighCap();
    boolean v6Only = nonzero && isIPv6Only();
    boolean ntcpDisabled = nonzero && isNTCPDisabled();
    boolean ssuDisabled = nonzero && isSSUDisabled();
    boolean checkClosestHop = v6Only || ntcpDisabled || ssuDisabled;
    boolean hidden = nonzero && (ctx.router().isHidden() || ctx.router().getRouterInfo().getAddressCount() <= 0);
    boolean hiddenInbound = hidden && isInbound;
    boolean hiddenOutbound = hidden && !isInbound;
    boolean lowOutbound = nonzero && !isInbound && !ctx.commSystem().haveHighOutboundCapacity();
    // closest-hop restrictions
    // Since we're applying orderPeers() later, we don't know
    // which will be the closest hop, so select the closest one here if necessary.
    Hash closestHop = null;
    if (v6Only || hiddenInbound || lowOutbound) {
        Set<Hash> closestExclude;
        if (checkClosestHop) {
            closestExclude = getClosestHopExclude(isInbound);
            if (closestExclude != null)
                closestExclude.addAll(exclude);
            else
                closestExclude = exclude;
        } else {
            closestExclude = exclude;
        }
        Set<Hash> closest = new HashSet<Hash>(1);
        if (hiddenInbound || lowOutbound) {
            // use only connected peers so we don't make more connections
            if (log.shouldLog(Log.INFO))
                log.info("EPS SANFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
            // SANFP adds all not-connected to exclude, so make a copy
            Set<Hash> SANFPExclude = new HashSet<Hash>(closestExclude);
            ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, closest);
            if (closest.isEmpty()) {
                // ANFP does not fall back to non-connected
                if (log.shouldLog(Log.INFO))
                    log.info("EPS SFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
                ctx.profileOrganizer().selectFastPeers(1, closestExclude, closest);
            }
        } else if (exploreHighCap) {
            if (log.shouldLog(Log.INFO))
                log.info("EPS SHCP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
            ctx.profileOrganizer().selectHighCapacityPeers(1, closestExclude, closest);
        } else {
            if (log.shouldLog(Log.INFO))
                log.info("EPS SNFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
            ctx.profileOrganizer().selectNotFailingPeers(1, closestExclude, closest, false);
        }
        if (!closest.isEmpty()) {
            closestHop = closest.iterator().next();
            exclude.add(closestHop);
            length--;
        }
    }
    // furthest-hop restrictions
    // Since we're applying orderPeers() later, we don't know
    // which will be the furthest hop, so select the furthest one here if necessary.
    Hash furthestHop = null;
    if (hiddenOutbound && length > 0) {
        // OBEP
        // check for hidden and outbound, and the paired (inbound) tunnel is zero-hop
        // if so, we need the OBEP to be connected to us, so we get the build reply back
        // This should be rare except at startup
        TunnelManagerFacade tmf = ctx.tunnelManager();
        TunnelPool tp = tmf.getInboundExploratoryPool();
        TunnelPoolSettings tps = tp.getSettings();
        int len = tps.getLength();
        boolean pickFurthest = true;
        if (len <= 0 || tps.getLengthOverride() == 0 || len + tps.getLengthVariance() <= 0) {
        // leave it true
        } else {
            for (TunnelInfo ti : tp.listTunnels()) {
                if (ti.getLength() > 1) {
                    pickFurthest = false;
                    break;
                }
            }
        }
        if (pickFurthest) {
            Set<Hash> furthest = new HashSet<Hash>(1);
            if (log.shouldLog(Log.INFO))
                log.info("EPS SANFP furthest OB exclude " + exclude.size());
            // ANFP adds all not-connected to exclude, so make a copy
            Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
            ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, furthest);
            if (furthest.isEmpty()) {
                // ANFP does not fall back to non-connected
                if (log.shouldLog(Log.INFO))
                    log.info("EPS SFP furthest OB exclude " + exclude.size());
                ctx.profileOrganizer().selectFastPeers(1, exclude, furthest);
            }
            if (!furthest.isEmpty()) {
                furthestHop = furthest.iterator().next();
                exclude.add(furthestHop);
                length--;
            }
        }
    }
    // Don't use ff peers for exploratory tunnels to lessen exposure to netDb searches and stores
    // Hmm if they don't get explored they don't get a speed/capacity rating
    // so they don't get used for client tunnels either.
    // FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)ctx.netDb();
    // exclude.addAll(fac.getFloodfillPeers());
    HashSet<Hash> matches = new HashSet<Hash>(length);
    if (length > 0) {
        // 
        if (exploreHighCap) {
            if (log.shouldLog(Log.INFO))
                log.info("EPS SHCP " + length + (isInbound ? " IB" : " OB") + " exclude " + exclude.size());
            ctx.profileOrganizer().selectHighCapacityPeers(length, exclude, matches);
        } else {
            // Peer org credits existing items in matches
            if (length > 2)
                ctx.profileOrganizer().selectHighCapacityPeers(length - 2, exclude, matches);
            if (log.shouldLog(Log.INFO))
                log.info("EPS SNFP " + length + (isInbound ? " IB" : " OB") + " exclude " + exclude.size());
            ctx.profileOrganizer().selectNotFailingPeers(length, exclude, matches, false);
        }
        matches.remove(ctx.routerHash());
    }
    ArrayList<Hash> rv = new ArrayList<Hash>(matches);
    if (rv.size() > 1)
        orderPeers(rv, settings.getRandomKey());
    if (closestHop != null) {
        if (isInbound)
            rv.add(0, closestHop);
        else
            rv.add(closestHop);
        length++;
    }
    if (furthestHop != null) {
        // always OBEP for now, nothing special for IBGW
        if (isInbound)
            rv.add(furthestHop);
        else
            rv.add(0, furthestHop);
        length++;
    }
    // log.debug("EPS result: " + DataHelper.toString(rv));
    if (isInbound)
        rv.add(0, ctx.routerHash());
    else
        rv.add(ctx.routerHash());
    if (rv.size() > 1) {
        if (!checkTunnel(isInbound, rv))
            rv = null;
    }
    return rv;
}
Also used : ArrayList(java.util.ArrayList) TunnelPoolSettings(net.i2p.router.TunnelPoolSettings) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) HashSet(java.util.HashSet) TunnelManagerFacade(net.i2p.router.TunnelManagerFacade)

Example 4 with TunnelInfo

use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.

the class FloodfillVerifyStoreJob method runJob.

/**
 *  Query a random floodfill for the leaseset or routerinfo
 *  that we just stored to a (hopefully different) floodfill peer.
 *
 *  If it fails (after a timeout period), resend the data.
 *  If the queried data is older than what we stored, that counts as a fail.
 */
public void runJob() {
    _target = pickTarget();
    if (_target == null) {
        _facade.verifyFinished(_key);
        return;
    }
    boolean isInboundExploratory;
    TunnelInfo replyTunnelInfo;
    if (_isRouterInfo || getContext().keyRing().get(_key) != null) {
        replyTunnelInfo = getContext().tunnelManager().selectInboundExploratoryTunnel(_target);
        isInboundExploratory = true;
    } else {
        replyTunnelInfo = getContext().tunnelManager().selectInboundTunnel(_key, _target);
        isInboundExploratory = false;
    }
    if (replyTunnelInfo == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("No inbound tunnels to get a reply from!");
        return;
    }
    DatabaseLookupMessage lookup = buildLookup(replyTunnelInfo);
    // If we are verifying a leaseset, use the destination's own tunnels,
    // to avoid association by the exploratory tunnel OBEP.
    // Unless it is an encrypted leaseset.
    TunnelInfo outTunnel;
    if (_isRouterInfo || getContext().keyRing().get(_key) != null)
        outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(_target);
    else
        outTunnel = getContext().tunnelManager().selectOutboundTunnel(_key, _target);
    if (outTunnel == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("No outbound tunnels to verify a store");
        _facade.verifyFinished(_key);
        return;
    }
    // garlic encrypt to hide contents from the OBEP
    RouterInfo peer = _facade.lookupRouterInfoLocally(_target);
    if (peer == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Fail finding target RI");
        _facade.verifyFinished(_key);
        return;
    }
    if (DatabaseLookupMessage.supportsEncryptedReplies(peer)) {
        // register the session with the right SKM
        MessageWrapper.OneTimeSession sess;
        if (isInboundExploratory) {
            sess = MessageWrapper.generateSession(getContext());
        } else {
            sess = MessageWrapper.generateSession(getContext(), _key);
            if (sess == null) {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("No SKM to reply to");
                _facade.verifyFinished(_key);
                return;
            }
        }
        if (_log.shouldLog(Log.INFO))
            _log.info("Requesting encrypted reply from " + _target + ' ' + sess.key + ' ' + sess.tag);
        lookup.setReplySession(sess.key, sess.tag);
    }
    Hash fromKey;
    if (_isRouterInfo)
        fromKey = null;
    else
        fromKey = _key;
    _wrappedMessage = MessageWrapper.wrap(getContext(), lookup, fromKey, peer);
    if (_wrappedMessage == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Fail Garlic encrypting");
        _facade.verifyFinished(_key);
        return;
    }
    I2NPMessage sent = _wrappedMessage.getMessage();
    if (_log.shouldLog(Log.INFO))
        _log.info("Starting verify (stored " + _key + " to " + _sentTo + "), asking " + _target);
    _sendTime = getContext().clock().now();
    _expiration = _sendTime + VERIFY_TIMEOUT;
    getContext().messageRegistry().registerPending(new VerifyReplySelector(), new VerifyReplyJob(getContext()), new VerifyTimeoutJob(getContext()));
    getContext().tunnelDispatcher().dispatchOutbound(sent, outTunnel.getSendTunnelId(0), _target);
}
Also used : DatabaseLookupMessage(net.i2p.data.i2np.DatabaseLookupMessage) RouterInfo(net.i2p.data.router.RouterInfo) I2NPMessage(net.i2p.data.i2np.I2NPMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash)

Example 5 with TunnelInfo

use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.

the class HandleFloodfillDatabaseStoreMessageJob method sendAck.

private void sendAck(Hash storedKey) {
    DeliveryStatusMessage msg = new DeliveryStatusMessage(getContext());
    msg.setMessageId(_message.getReplyToken());
    // Randomize for a little protection against clock-skew fingerprinting.
    // But the "arrival" isn't used for anything, right?
    // TODO just set to 0?
    // TODO we have no session to garlic wrap this with, needs new message
    msg.setArrival(getContext().clock().now() - getContext().random().nextInt(3 * 1000));
    // may be null
    TunnelId replyTunnel = _message.getReplyTunnel();
    // A store of our own RI, only if we are not FF
    DatabaseStoreMessage msg2;
    if ((getContext().netDb().floodfillEnabled() && !getContext().router().gracefulShutdownInProgress()) || storedKey.equals(getContext().routerHash())) {
        // don't send our RI if the store was our RI (from PeerTestJob)
        msg2 = null;
    } else {
        // we aren't ff, send a go-away message
        msg2 = new DatabaseStoreMessage(getContext());
        RouterInfo me = getContext().router().getRouterInfo();
        msg2.setEntry(me);
        if (_log.shouldWarn())
            _log.warn("Got a store w/ reply token, but we aren't ff: from: " + _from + " fromHash: " + _fromHash + " msg: " + _message, new Exception());
    }
    Hash toPeer = _message.getReplyGateway();
    boolean toUs = getContext().routerHash().equals(toPeer);
    // else through an exploratory tunnel.
    if (toUs && replyTunnel != null) {
        // if we are the gateway, act as if we received it
        TunnelGatewayMessage tgm = new TunnelGatewayMessage(getContext());
        tgm.setMessage(msg);
        tgm.setTunnelId(replyTunnel);
        tgm.setMessageExpiration(msg.getMessageExpiration());
        getContext().tunnelDispatcher().dispatch(tgm);
        if (msg2 != null) {
            TunnelGatewayMessage tgm2 = new TunnelGatewayMessage(getContext());
            tgm2.setMessage(msg2);
            tgm2.setTunnelId(replyTunnel);
            tgm2.setMessageExpiration(msg.getMessageExpiration());
            getContext().tunnelDispatcher().dispatch(tgm2);
        }
    } else if (toUs || getContext().commSystem().isEstablished(toPeer)) {
        Job send = new SendMessageDirectJob(getContext(), msg, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
        send.runJob();
        if (msg2 != null) {
            Job send2 = new SendMessageDirectJob(getContext(), msg2, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
            send2.runJob();
        }
    } else {
        // pick tunnel with endpoint closest to toPeer
        TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(toPeer);
        if (outTunnel == null) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("No outbound tunnel could be found");
            return;
        }
        getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
        if (msg2 != null)
            getContext().tunnelDispatcher().dispatchOutbound(msg2, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
    }
}
Also used : TunnelGatewayMessage(net.i2p.data.i2np.TunnelGatewayMessage) RouterInfo(net.i2p.data.router.RouterInfo) DatabaseStoreMessage(net.i2p.data.i2np.DatabaseStoreMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) SendMessageDirectJob(net.i2p.router.message.SendMessageDirectJob) Job(net.i2p.router.Job) TunnelId(net.i2p.data.TunnelId) SendMessageDirectJob(net.i2p.router.message.SendMessageDirectJob) DeliveryStatusMessage(net.i2p.data.i2np.DeliveryStatusMessage)

Aggregations

TunnelInfo (net.i2p.router.TunnelInfo)30 Hash (net.i2p.data.Hash)15 TunnelId (net.i2p.data.TunnelId)8 RouterInfo (net.i2p.data.router.RouterInfo)6 ArrayList (java.util.ArrayList)4 DatabaseLookupMessage (net.i2p.data.i2np.DatabaseLookupMessage)4 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)4 I2NPMessage (net.i2p.data.i2np.I2NPMessage)4 TunnelManagerFacade (net.i2p.router.TunnelManagerFacade)4 Job (net.i2p.router.Job)3 TunnelPoolSettings (net.i2p.router.TunnelPoolSettings)3 HashSet (java.util.HashSet)2 OutNetMessage (net.i2p.router.OutNetMessage)2 ReplyJob (net.i2p.router.ReplyJob)2 Date (java.util.Date)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1