Search in sources :

Example 21 with TunnelInfo

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

the class TunnelPoolManager method selectOutboundExploratoryTunnel.

/**
 * Pick the outbound exploratory tunnel with the endpoint closest to the given hash.
 * By using this instead of the random selectTunnel(),
 * we force some locality in OBEP-IBGW connections to minimize
 * those connections network-wide.
 *
 * @param closestTo non-null
 * @return null if none
 * @since 0.8.10
 */
public TunnelInfo selectOutboundExploratoryTunnel(Hash closestTo) {
    TunnelInfo info = _outboundExploratory.selectTunnel(closestTo);
    if (info == null) {
        _outboundExploratory.buildFallback();
        // still can be null, but probably not
        info = _outboundExploratory.selectTunnel();
    }
    return info;
}
Also used : TunnelInfo(net.i2p.router.TunnelInfo)

Example 22 with TunnelInfo

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

the class ClientPeerSelector 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)
        return null;
    if ((length == 0) && (settings.getLength() + settings.getLengthVariance() > 0))
        return null;
    List<Hash> rv;
    boolean isInbound = settings.isInbound();
    if (length > 0) {
        // special cases
        boolean v6Only = isIPv6Only();
        boolean ntcpDisabled = isNTCPDisabled();
        boolean ssuDisabled = isSSUDisabled();
        boolean checkClosestHop = v6Only || ntcpDisabled || ssuDisabled;
        boolean hidden = ctx.router().isHidden() || ctx.router().getRouterInfo().getAddressCount() <= 0;
        boolean hiddenInbound = hidden && isInbound;
        boolean hiddenOutbound = hidden && !isInbound;
        if (shouldSelectExplicit(settings))
            return selectExplicit(settings, length);
        Set<Hash> exclude = getExclude(isInbound, false);
        Set<Hash> matches = new HashSet<Hash>(length);
        if (length == 1) {
            // closest-hop restrictions
            if (checkClosestHop) {
                Set<Hash> moreExclude = getClosestHopExclude(isInbound);
                if (moreExclude != null)
                    exclude.addAll(moreExclude);
            }
            if (hiddenInbound) {
                // SANFP adds all not-connected to exclude, so make a copy
                Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
                ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
            }
            if (matches.isEmpty()) {
                // ANFP does not fall back to non-connected
                ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
            }
            matches.remove(ctx.routerHash());
            rv = new ArrayList<Hash>(matches);
        } else {
            // build a tunnel using 4 subtiers.
            // For a 2-hop tunnel, the first hop comes from subtiers 0-1 and the last from subtiers 2-3.
            // For a longer tunnels, the first hop comes from subtier 0, the middle from subtiers 2-3, and the last from subtier 1.
            rv = new ArrayList<Hash>(length + 1);
            Hash randomKey = settings.getRandomKey();
            // OBEP or IB last hop
            // group 0 or 1 if two hops, otherwise group 0
            Set<Hash> lastHopExclude;
            if (isInbound) {
                // closest-hop restrictions
                if (checkClosestHop) {
                    Set<Hash> moreExclude = getClosestHopExclude(false);
                    if (moreExclude != null) {
                        moreExclude.addAll(exclude);
                        lastHopExclude = moreExclude;
                    } else {
                        lastHopExclude = exclude;
                    }
                } else {
                    lastHopExclude = exclude;
                }
            } else {
                lastHopExclude = exclude;
            }
            if (hiddenInbound) {
                // IB closest hop
                if (log.shouldInfo())
                    log.info("CPS SANFP closest IB exclude " + lastHopExclude.size());
                // SANFP adds all not-connected to exclude, so make a copy
                Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
                ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
                if (matches.isEmpty()) {
                    if (log.shouldInfo())
                        log.info("CPS SFP closest IB exclude " + lastHopExclude.size());
                    // ANFP does not fall back to non-connected
                    ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
                }
            } else if (hiddenOutbound) {
                // 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.getInboundPool(settings.getDestination());
                boolean pickFurthest;
                if (tp != null) {
                    pickFurthest = true;
                    TunnelPoolSettings tps = tp.getSettings();
                    int len = tps.getLength();
                    if (len <= 0 || tps.getLengthOverride() == 0 || len + tps.getLengthVariance() <= 0) {
                    // leave it true
                    } else {
                        List<TunnelInfo> tunnels = tp.listTunnels();
                        if (!tunnels.isEmpty()) {
                            for (TunnelInfo ti : tp.listTunnels()) {
                                if (ti.getLength() > 1) {
                                    pickFurthest = false;
                                    break;
                                }
                            }
                        } else {
                            // no tunnels in the paired tunnel pool
                            // BuildRequester will be using exploratory
                            tp = tmf.getInboundExploratoryPool();
                            tps = tp.getSettings();
                            len = tps.getLength();
                            if (len <= 0 || tps.getLengthOverride() == 0 || len + tps.getLengthVariance() <= 0) {
                            // leave it true
                            } else {
                                tunnels = tp.listTunnels();
                                if (!tunnels.isEmpty()) {
                                    for (TunnelInfo ti : tp.listTunnels()) {
                                        if (ti.getLength() > 1) {
                                            pickFurthest = false;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    // shouldn't happen
                    pickFurthest = false;
                }
                if (pickFurthest) {
                    if (log.shouldInfo())
                        log.info("CPS SANFP OBEP exclude " + lastHopExclude.size());
                    // SANFP adds all not-connected to exclude, so make a copy
                    Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
                    ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
                    if (matches.isEmpty()) {
                        // ANFP does not fall back to non-connected
                        if (log.shouldInfo())
                            log.info("CPS SFP OBEP exclude " + lastHopExclude.size());
                        ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
                    }
                } else {
                    ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
                }
            } else {
                // TODO exclude IPv6-only at OBEP? Caught in checkTunnel() below
                ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
            }
            matches.remove(ctx.routerHash());
            exclude.addAll(matches);
            rv.addAll(matches);
            matches.clear();
            if (length > 2) {
                // middle hop(s)
                // group 2 or 3
                ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, randomKey, SLICE_2_3);
                matches.remove(ctx.routerHash());
                if (matches.size() > 1) {
                    // order the middle peers for tunnels >= 4 hops
                    List<Hash> ordered = new ArrayList<Hash>(matches);
                    orderPeers(ordered, randomKey);
                    rv.addAll(ordered);
                } else {
                    rv.addAll(matches);
                }
                exclude.addAll(matches);
                matches.clear();
            }
            // group 2 or 3 if two hops, otherwise group 1
            if (!isInbound) {
                // closest-hop restrictions
                if (checkClosestHop) {
                    Set<Hash> moreExclude = getClosestHopExclude(true);
                    if (moreExclude != null)
                        exclude.addAll(moreExclude);
                }
            }
            // TODO exclude IPv6-only at IBGW? Caught in checkTunnel() below
            ctx.profileOrganizer().selectFastPeers(1, exclude, matches, randomKey, length == 2 ? SLICE_2_3 : SLICE_1);
            matches.remove(ctx.routerHash());
            rv.addAll(matches);
        }
    } else {
        rv = new ArrayList<Hash>(1);
    }
    // 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 : HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelManagerFacade(net.i2p.router.TunnelManagerFacade) TunnelPoolSettings(net.i2p.router.TunnelPoolSettings) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 23 with TunnelInfo

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

the class SearchJob method resend.

/**
 * Resend the leaseSet to the peer who had previously failed to
 * provide us with the data when we asked them.
 */
private boolean resend(RouterInfo toPeer, LeaseSet ls) {
    Hash to = toPeer.getIdentity().getHash();
    DatabaseStoreMessage msg = new DatabaseStoreMessage(getContext());
    msg.setEntry(ls);
    msg.setMessageExpiration(getContext().clock().now() + RESEND_TIMEOUT);
    TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to);
    if (outTunnel != null) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("resending leaseSet out to " + to + " through " + outTunnel + ": " + msg);
        // TODO pass a priority to the dispatcher
        getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), null, to);
        return true;
    } else {
        if (_log.shouldLog(Log.WARN))
            _log.warn("unable to resend a leaseSet - no outbound exploratory tunnels!");
        return false;
    }
}
Also used : DatabaseStoreMessage(net.i2p.data.i2np.DatabaseStoreMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash)

Example 24 with TunnelInfo

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

the class SearchJob method sendLeaseSearch.

/**
 * we're (probably) searching for a LeaseSet, so to be (overly) cautious, we're sending
 * the request out through a tunnel w/ reply back through another tunnel.
 */
protected void sendLeaseSearch(RouterInfo router) {
    Hash to = router.getIdentity().getHash();
    TunnelInfo inTunnel = getContext().tunnelManager().selectInboundExploratoryTunnel(to);
    if (inTunnel == null) {
        _log.warn("No tunnels to get search replies through!");
        getContext().jobQueue().addJob(new FailedJob(getContext(), router));
        return;
    }
    TunnelId inTunnelId = inTunnel.getReceiveTunnelId(0);
    // this will fail if we've banlisted our inbound gateway, but the gw may not necessarily
    // be banlisted by whomever needs to contact them, so we don't need to check this
    // RouterInfo inGateway = getContext().netDb().lookupRouterInfoLocally(inTunnel.getPeer(0));
    // if (inGateway == null) {
    // _log.error("We can't find the gateway to our inbound tunnel?!");
    // getContext().jobQueue().addJob(new FailedJob(getContext(), router));
    // return;
    // }
    int timeout = getPerPeerTimeoutMs(to);
    long expiration = getContext().clock().now() + timeout;
    I2NPMessage msg = buildMessage(inTunnelId, inTunnel.getPeer(0), expiration, router);
    if (msg == null) {
        getContext().jobQueue().addJob(new FailedJob(getContext(), router));
        return;
    }
    TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to);
    if (outTunnel == null) {
        _log.warn("No tunnels to send search out through! Impossible?");
        getContext().jobQueue().addJob(new FailedJob(getContext(), router));
        return;
    }
    TunnelId outTunnelId = outTunnel.getSendTunnelId(0);
    if (_log.shouldLog(Log.DEBUG))
        _log.debug(getJobId() + ": Sending search to " + to + " for " + getState().getTarget() + " w/ replies through " + inTunnel.getPeer(0) + " via tunnel " + inTunnelId);
    SearchMessageSelector sel = new SearchMessageSelector(getContext(), router, _expiration, _state);
    SearchUpdateReplyFoundJob reply = new SearchUpdateReplyFoundJob(getContext(), router, _state, _facade, this, outTunnel, inTunnel);
    if (FloodfillNetworkDatabaseFacade.isFloodfill(router))
        _floodfillSearchesOutstanding++;
    getContext().messageRegistry().registerPending(sel, reply, new FailedJob(getContext(), router));
    // TODO pass a priority to the dispatcher
    getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnelId, to);
}
Also used : I2NPMessage(net.i2p.data.i2np.I2NPMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 25 with TunnelInfo

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

the class SingleSearchJob method runJob.

@Override
public void runJob() {
    _onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout);
    DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true);
    TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundExploratoryTunnel(_to);
    TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(_to);
    if ((replyTunnel == null) || (outTunnel == null)) {
        failed();
        return;
    }
    dlm.setFrom(replyTunnel.getPeer(0));
    dlm.setMessageExpiration(getContext().clock().now() + 5 * 1000);
    dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0));
    dlm.setSearchKey(_key);
    dlm.setSearchType(DatabaseLookupMessage.Type.RI);
    if (_log.shouldLog(Log.INFO))
        _log.info(getJobId() + ": Single search for " + _key + " to " + _to);
    getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to);
    _lookupsRemaining.set(1);
}
Also used : DatabaseLookupMessage(net.i2p.data.i2np.DatabaseLookupMessage) TunnelInfo(net.i2p.router.TunnelInfo)

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