Search in sources :

Example 1 with RandomIterator

use of net.i2p.router.util.RandomIterator in project i2p.i2p by i2p.

the class UDPTransport method pickTestPeer.

/**
 *  Pick a Bob (if we are Alice) or a Charlie (if we are Bob).
 *
 *  For Bob (as called from PeerTestEvent below), returns an established IPv4/v6 peer.
 *  While the protocol allows Alice to select an unestablished Bob, we don't support that.
 *
 *  For Charlie (as called from PeerTestManager), returns an established IPv4 or IPv6 peer.
 *  (doesn't matter how Bob and Charlie communicate)
 *
 *  Any returned peer must advertise an IPv4 address to prove it is IPv4-capable.
 *  Ditto for v6.
 *
 *  @param peerRole The role of the peer we are looking for, BOB or CHARLIE only (NOT our role)
 *  @param isIPv6 true to get a v6-capable peer back
 *  @param dontInclude may be null
 *  @return IPv4 peer or null
 */
PeerState pickTestPeer(PeerTestState.Role peerRole, boolean isIPv6, RemoteHostId dontInclude) {
    if (peerRole == ALICE)
        throw new IllegalArgumentException();
    List<PeerState> peers = new ArrayList<PeerState>(_peersByIdent.values());
    for (Iterator<PeerState> iter = new RandomIterator<PeerState>(peers); iter.hasNext(); ) {
        PeerState peer = iter.next();
        if ((dontInclude != null) && (dontInclude.equals(peer.getRemoteHostId())))
            continue;
        // enforce IPv4/v6 connection if we are ALICE looking for a BOB
        byte[] ip = peer.getRemoteIP();
        if (peerRole == BOB) {
            if (isIPv6) {
                if (ip.length != 16)
                    continue;
            } else {
                if (ip.length != 4)
                    continue;
            }
        }
        // enforce IPv4/v6 advertised for all
        RouterInfo peerInfo = _context.netDb().lookupRouterInfoLocally(peer.getRemotePeer());
        if (peerInfo == null)
            continue;
        if (isIPv6) {
            String v = peerInfo.getVersion();
            if (VersionComparator.comp(v, MIN_V6_PEER_TEST_VERSION) < 0)
                continue;
        }
        ip = null;
        List<RouterAddress> addrs = getTargetAddresses(peerInfo);
        for (RouterAddress addr : addrs) {
            byte[] rip = addr.getIP();
            if (rip != null) {
                if (isIPv6) {
                    if (rip.length != 16)
                        continue;
                } else {
                    if (rip.length != 4)
                        continue;
                }
                // as of 0.9.27, we trust the 'B' cap for IPv6
                String caps = addr.getOption(UDPAddress.PROP_CAPACITY);
                if (caps != null && caps.contains(CAP_TESTING)) {
                    ip = rip;
                    break;
                }
            }
        }
        if (ip == null)
            continue;
        if (isTooClose(ip))
            continue;
        return peer;
    }
    return null;
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) RouterAddress(net.i2p.data.router.RouterAddress) RandomIterator(net.i2p.router.util.RandomIterator)

Example 2 with RandomIterator

use of net.i2p.router.util.RandomIterator in project i2p.i2p by i2p.

the class ProfileOrganizer method locked_selectPeers.

/**
 * @param randomKey used for deterministic random partitioning into subtiers
 * @param subTierMode 2-7:
 *<pre>
 *    2: return only from group 0 or 1
 *    3: return only from group 2 or 3
 *    4: return only from group 0
 *    5: return only from group 1
 *    6: return only from group 2
 *    7: return only from group 3
 *</pre>
 */
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches, Hash randomKey, Slice subTierMode) {
    List<Hash> all = new ArrayList<Hash>(peers.keySet());
    // use RandomIterator to avoid shuffling the whole thing
    for (Iterator<Hash> iter = new RandomIterator<Hash>(all); (matches.size() < howMany) && iter.hasNext(); ) {
        Hash peer = iter.next();
        if (toExclude != null && toExclude.contains(peer))
            continue;
        if (matches.contains(peer))
            continue;
        if (_us.equals(peer))
            continue;
        int subTier = getSubTier(peer, randomKey);
        if ((subTier & subTierMode.mask) != subTierMode.val)
            continue;
        boolean ok = isSelectable(peer);
        if (ok)
            matches.add(peer);
        else
            matches.remove(peer);
    }
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) RandomIterator(net.i2p.router.util.RandomIterator)

Example 3 with RandomIterator

use of net.i2p.router.util.RandomIterator in project i2p.i2p by i2p.

the class ProfileOrganizer method locked_selectPeers.

/**
 * As of 0.9.24, checks for a netdb family match as well, unless mask == 0.
 *
 * @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
 *             not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
 */
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches, int mask) {
    List<Hash> all = new ArrayList<Hash>(peers.keySet());
    MaskedIPSet IPSet = new MaskedIPSet(16);
    // use RandomIterator to avoid shuffling the whole thing
    for (Iterator<Hash> iter = new RandomIterator<Hash>(all); (matches.size() < howMany) && iter.hasNext(); ) {
        Hash peer = iter.next();
        if (toExclude != null && toExclude.contains(peer))
            continue;
        if (matches.contains(peer))
            continue;
        if (_us.equals(peer))
            continue;
        boolean ok = isSelectable(peer);
        if (ok) {
            ok = mask <= 0 || notRestricted(peer, IPSet, mask);
            if ((!ok) && _log.shouldLog(Log.WARN))
                _log.warn("IP restriction prevents " + peer + " from joining " + matches);
        }
        if (ok)
            matches.add(peer);
        else
            matches.remove(peer);
    }
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) MaskedIPSet(net.i2p.router.util.MaskedIPSet) RandomIterator(net.i2p.router.util.RandomIterator)

Example 4 with RandomIterator

use of net.i2p.router.util.RandomIterator in project i2p.i2p by i2p.

the class ProfileOrganizer method selectAllNotFailingPeers.

/**
 * @param mask ignored, should call locked_selectPeers, to be fixed
 */
private void selectAllNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, boolean onlyNotFailing, int mask) {
    if (matches.size() < howMany) {
        int orig = matches.size();
        int needed = howMany - orig;
        List<Hash> selected = new ArrayList<Hash>(needed);
        getReadLock();
        try {
            // use RandomIterator to avoid shuffling the whole thing
            for (Iterator<Hash> iter = new RandomIterator<Hash>(_notFailingPeersList); (selected.size() < needed) && iter.hasNext(); ) {
                Hash cur = iter.next();
                if (matches.contains(cur) || (exclude != null && exclude.contains(cur))) {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("matched? " + matches.contains(cur) + " exclude: " + exclude + " cur=" + cur.toBase64());
                    continue;
                } else if (onlyNotFailing && _highCapacityPeers.containsKey(cur)) {
                    // we dont want the good peers, just random ones
                    continue;
                } else {
                    if (isSelectable(cur))
                        selected.add(cur);
                    else if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Not selectable: " + cur.toBase64());
                }
            }
        } finally {
            releaseReadLock();
        }
        if (_log.shouldLog(Log.INFO))
            _log.info("Selecting all not failing (strict? " + onlyNotFailing + ") found " + selected.size() + " new peers: " + selected + " all=" + _notFailingPeersList.size() + " strict=" + _strictCapacityOrder.size());
        matches.addAll(selected);
    }
    if (matches.size() < howMany) {
        if (_log.shouldLog(Log.INFO))
            _log.info("selectAllNotFailing(" + howMany + "), not enough (" + matches.size() + ") going on to failing");
        selectFailingPeers(howMany, exclude, matches);
    } else {
        if (_log.shouldLog(Log.INFO))
            _log.info("selectAllNotFailing(" + howMany + "), enough (" + matches.size() + ")");
    }
    return;
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) RandomIterator(net.i2p.router.util.RandomIterator)

Example 5 with RandomIterator

use of net.i2p.router.util.RandomIterator in project i2p.i2p by i2p.

the class IterativeSearchJob method runJob.

@Override
public void runJob() {
    if (_facade.isNegativeCached(_key)) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Negative cached, not searching: " + _key);
        failed();
        return;
    }
    // pick some floodfill peers and send out the searches
    List<Hash> floodfillPeers;
    KBucketSet<Hash> ks = _facade.getKBuckets();
    if (ks != null) {
        // Ideally we would add the key to an exclude list, so we don't try to query a ff peer for itself,
        // but we're passing the rkey not the key, so we do it below instead in certain cases.
        floodfillPeers = ((FloodfillPeerSelector) _facade.getPeerSelector()).selectFloodfillParticipants(_rkey, _totalSearchLimit + EXTRA_PEERS, ks);
    } else {
        floodfillPeers = new ArrayList<Hash>(_totalSearchLimit);
    }
    // For testing or local networks... we will
    // pretend that the specified router is floodfill, and always closest-to-the-key.
    // May be set after startup but can't be changed or unset later.
    // Warning - experts only!
    String alwaysQuery = getContext().getProperty("netDb.alwaysQuery");
    if (alwaysQuery != null) {
        if (_alwaysQueryHash == null) {
            byte[] b = Base64.decode(alwaysQuery);
            if (b != null && b.length == Hash.HASH_LENGTH)
                _alwaysQueryHash = Hash.create(b);
        }
    }
    if (floodfillPeers.isEmpty()) {
        // so this situation should be temporary
        if (_log.shouldLog(Log.WARN))
            _log.warn("Running netDb searches against the floodfill peers, but we don't know any");
        List<Hash> all = new ArrayList<Hash>(_facade.getAllRouters());
        if (all.isEmpty()) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("We don't know any peers at all");
            failed();
            return;
        }
        Iterator<Hash> iter = new RandomIterator<Hash>(all);
        // so once we get some FFs we want to be sure to query them
        for (int i = 0; iter.hasNext() && i < MAX_NON_FF; i++) {
            floodfillPeers.add(iter.next());
        }
    }
    final boolean empty;
    // outside sync to avoid deadlock
    final Hash us = getContext().routerHash();
    synchronized (this) {
        _toTry.addAll(floodfillPeers);
        // don't ask ourselves or the target
        _toTry.remove(us);
        _toTry.remove(_key);
        empty = _toTry.isEmpty();
    }
    if (empty) {
        if (_log.shouldLog(Log.WARN))
            _log.warn(getJobId() + ": ISJ for " + _key + " had no peers to send to");
        // no floodfill peers, fail
        failed();
        return;
    }
    // This OutNetMessage is never used or sent (setMessage() is never called), it's only
    // so we can register a reply selector.
    MessageSelector replySelector = new IterativeLookupSelector(getContext(), this);
    ReplyJob onReply = new FloodOnlyLookupMatchJob(getContext(), this);
    Job onTimeout = new FloodOnlyLookupTimeoutJob(getContext(), this);
    _out = getContext().messageRegistry().registerPending(replySelector, onReply, onTimeout);
    if (_log.shouldLog(Log.INFO))
        _log.info(getJobId() + ": New ISJ for " + (_isLease ? "LS " : "RI ") + _key + " (rkey " + _rkey + ") timeout " + DataHelper.formatDuration(_timeoutMs) + " toTry: " + DataHelper.toString(_toTry));
    retry();
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) ReplyJob(net.i2p.router.ReplyJob) MessageSelector(net.i2p.router.MessageSelector) ReplyJob(net.i2p.router.ReplyJob) Job(net.i2p.router.Job) RandomIterator(net.i2p.router.util.RandomIterator)

Aggregations

ArrayList (java.util.ArrayList)5 RandomIterator (net.i2p.router.util.RandomIterator)5 Hash (net.i2p.data.Hash)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 RouterAddress (net.i2p.data.router.RouterAddress)1 RouterInfo (net.i2p.data.router.RouterInfo)1 Job (net.i2p.router.Job)1 MessageSelector (net.i2p.router.MessageSelector)1 ReplyJob (net.i2p.router.ReplyJob)1 MaskedIPSet (net.i2p.router.util.MaskedIPSet)1