Search in sources :

Example 1 with MaskedIPSet

use of net.i2p.router.util.MaskedIPSet 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 2 with MaskedIPSet

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

the class FloodfillVerifyStoreJob method pickTarget.

/**
 *  Pick a responsive floodfill close to the key, but not the one we sent to
 */
private Hash pickTarget() {
    Hash rkey = getContext().routingKeyGenerator().getRoutingKey(_key);
    FloodfillPeerSelector sel = (FloodfillPeerSelector) _facade.getPeerSelector();
    Certificate keyCert = null;
    if (!_isRouterInfo) {
        Destination dest = _facade.lookupDestinationLocally(_key);
        if (dest != null) {
            Certificate cert = dest.getCertificate();
            if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY)
                keyCert = cert;
        }
    }
    if (keyCert != null) {
        while (true) {
            List<Hash> peers = sel.selectFloodfillParticipants(rkey, 1, _ignore, _facade.getKBuckets());
            if (peers.isEmpty())
                break;
            Hash peer = peers.get(0);
            RouterInfo ri = _facade.lookupRouterInfoLocally(peer);
            // if (ri != null && StoreJob.supportsCert(ri, keyCert)) {
            if (ri != null && StoreJob.shouldStoreTo(ri)) {
                Set<String> peerIPs = new MaskedIPSet(getContext(), ri, IP_CLOSE_BYTES);
                if (!_ipSet.containsAny(peerIPs)) {
                    _ipSet.addAll(peerIPs);
                    return peer;
                } else {
                    if (_log.shouldLog(Log.INFO))
                        _log.info(getJobId() + ": Skipping verify w/ router too close to the store " + peer);
                }
            } else {
                if (_log.shouldLog(Log.INFO))
                    _log.info(getJobId() + ": Skipping verify w/ router that is too old " + peer);
            }
            _ignore.add(peer);
        }
    } else {
        List<Hash> peers = sel.selectFloodfillParticipants(rkey, 1, _ignore, _facade.getKBuckets());
        if (!peers.isEmpty())
            return peers.get(0);
    }
    if (_log.shouldLog(Log.WARN))
        _log.warn("No other peers to verify floodfill with, using the one we sent to");
    return _sentTo;
}
Also used : Destination(net.i2p.data.Destination) RouterInfo(net.i2p.data.router.RouterInfo) Hash(net.i2p.data.Hash) MaskedIPSet(net.i2p.router.util.MaskedIPSet) Certificate(net.i2p.data.Certificate)

Example 3 with MaskedIPSet

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

the class IterativeSearchJob method retry.

/**
 *  Send lookups to one or more peers, up to the configured concurrent and total limits
 */
private void retry() {
    long now = getContext().clock().now();
    if (_expiration < now) {
        failed();
        return;
    }
    if (_expiration - 500 < now) {
        // not enough time left to bother
        return;
    }
    while (true) {
        Hash peer = null;
        final int done, pend;
        synchronized (this) {
            if (_dead)
                return;
            pend = _unheardFrom.size();
            if (pend >= _maxConcurrent)
                return;
            done = _failedPeers.size();
        }
        if (done >= _totalSearchLimit) {
            failed();
            return;
        }
        // coming via newPeerToTry()
        if (done + pend >= _totalSearchLimit)
            return;
        synchronized (this) {
            if (_alwaysQueryHash != null && !_unheardFrom.contains(_alwaysQueryHash) && !_failedPeers.contains(_alwaysQueryHash)) {
                // 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!
                peer = _alwaysQueryHash;
            } else {
                if (_toTry.isEmpty())
                    return;
                for (Iterator<Hash> iter = _toTry.iterator(); iter.hasNext(); ) {
                    Hash h = iter.next();
                    iter.remove();
                    Set<String> peerIPs = new MaskedIPSet(getContext(), h, IP_CLOSE_BYTES);
                    if (!_ipSet.containsAny(peerIPs)) {
                        _ipSet.addAll(peerIPs);
                        peer = h;
                        break;
                    }
                    if (_log.shouldLog(Log.INFO))
                        _log.info(getJobId() + ": Skipping query w/ router too close to others " + h);
                    _skippedPeers.add(h);
                // go around again
                }
                if (peer == null)
                    return;
            }
            _unheardFrom.add(peer);
        }
        sendQuery(peer);
    }
}
Also used : Hash(net.i2p.data.Hash) MaskedIPSet(net.i2p.router.util.MaskedIPSet)

Example 4 with MaskedIPSet

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

the class FloodfillPeerSelector method selectFloodfillParticipantsIncludingUs.

/**
 *  See above for description
 *  List MAY CONTAIN our own hash unless included in toIgnore
 *  @param key the ROUTING key (NOT the original key)
 *  @param toIgnore can be null
 *  @param kbuckets now unused
 */
private List<Hash> selectFloodfillParticipantsIncludingUs(Hash key, int howMany, Set<Hash> toIgnore, KBucketSet<Hash> kbuckets) {
    List<Hash> ffs = selectFloodfillParticipants(toIgnore, kbuckets);
    TreeSet<Hash> sorted = new TreeSet<Hash>(new XORComparator<Hash>(key));
    sorted.addAll(ffs);
    List<Hash> rv = new ArrayList<Hash>(howMany);
    List<Hash> okff = new ArrayList<Hash>(ffs.size());
    List<Hash> badff = new ArrayList<Hash>(ffs.size());
    int found = 0;
    long now = _context.clock().now();
    long installed = _context.getProperty("router.firstInstalled", 0L);
    boolean enforceHeard = installed > 0 && (now - installed) > INSTALL_AGE;
    double maxFailRate = 100;
    if (_context.router().getUptime() > 60 * 60 * 1000) {
        RateStat rs = _context.statManager().getRate("peer.failedLookupRate");
        if (rs != null) {
            Rate r = rs.getRate(60 * 60 * 1000);
            if (r != null) {
                double currentFailRate = r.getAverageValue();
                maxFailRate = Math.max(0.20d, 1.5d * currentFailRate);
            }
        }
    }
    // 5 == FNDF.MAX_TO_FLOOD + 1
    int limit = Math.max(5, howMany);
    limit = Math.min(limit, ffs.size());
    MaskedIPSet maskedIPs = new MaskedIPSet(limit * 3);
    // split sorted list into 3 sorted lists
    for (int i = 0; found < howMany && i < limit; i++) {
        Hash entry = sorted.first();
        if (entry == null)
            // shouldn't happen
            break;
        sorted.remove(entry);
        // put anybody in the same /16 at the end
        RouterInfo info = _context.netDb().lookupRouterInfoLocally(entry);
        MaskedIPSet entryIPs = new MaskedIPSet(_context, entry, info, 2);
        boolean sameIP = false;
        for (String ip : entryIPs) {
            if (!maskedIPs.add(ip))
                sameIP = true;
        }
        if (sameIP) {
            badff.add(entry);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Same /16, family, or port: " + entry);
        } else if (info != null && now - info.getPublished() > 3 * 60 * 60 * 1000) {
            badff.add(entry);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Old: " + entry);
        } else if (info != null && _context.commSystem().isInBadCountry(info)) {
            badff.add(entry);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Bad country: " + entry);
        } else if (info != null && info.getBandwidthTier().equals("L")) {
            badff.add(entry);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Slow: " + entry);
        } else {
            PeerProfile prof = _context.profileOrganizer().getProfile(entry);
            double maxGoodRespTime = MAX_GOOD_RESP_TIME;
            RateStat ttst = _context.statManager().getRate("tunnel.testSuccessTime");
            if (ttst != null) {
                Rate tunnelTestTime = ttst.getRate(10 * 60 * 1000);
                if (tunnelTestTime != null && tunnelTestTime.getAverageValue() > 500)
                    maxGoodRespTime = 2 * tunnelTestTime.getAverageValue();
            }
            if (prof != null) {
                if (enforceHeard && prof.getFirstHeardAbout() > now - HEARD_AGE) {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Bad (new): " + entry);
                    badff.add(entry);
                } else if (prof.getDBHistory() != null) {
                    if (prof.getDbResponseTime().getRate(10 * 60 * 1000).getAverageValue() < maxGoodRespTime && prof.getDBHistory().getLastStoreFailed() < now - NO_FAIL_STORE_GOOD && prof.getDBHistory().getLastLookupFailed() < now - NO_FAIL_LOOKUP_GOOD && prof.getDBHistory().getFailedLookupRate().getRate(60 * 60 * 1000).getAverageValue() < maxFailRate) {
                        // good
                        if (_log.shouldLog(Log.DEBUG))
                            _log.debug("Good: " + entry);
                        rv.add(entry);
                        found++;
                    } else if (prof.getDBHistory().getLastStoreFailed() <= prof.getDBHistory().getLastStoreSuccessful() || prof.getDBHistory().getLastLookupFailed() <= prof.getDBHistory().getLastLookupSuccessful() || (prof.getDBHistory().getLastStoreFailed() < now - NO_FAIL_STORE_OK && prof.getDBHistory().getLastLookupFailed() < now - NO_FAIL_LOOKUP_OK)) {
                        if (_log.shouldLog(Log.DEBUG))
                            _log.debug("OK: " + entry);
                        okff.add(entry);
                    } else {
                        if (_log.shouldLog(Log.DEBUG))
                            _log.debug("Bad (DB): " + entry);
                        badff.add(entry);
                    }
                } else {
                    // no DBHistory
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Bad (no hist): " + entry);
                    badff.add(entry);
                }
            } else {
                // no profile
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Bad (no prof): " + entry);
                badff.add(entry);
            }
        }
    }
    if (_log.shouldLog(Log.INFO))
        _log.info("Good: " + rv + " OK: " + okff + " Bad: " + badff);
    // Put the ok floodfills after the good floodfills
    for (int i = 0; found < howMany && i < okff.size(); i++) {
        rv.add(okff.get(i));
        found++;
    }
    // Put the "bad" floodfills after the ok floodfills
    for (int i = 0; found < howMany && i < badff.size(); i++) {
        rv.add(badff.get(i));
        found++;
    }
    return rv;
}
Also used : Rate(net.i2p.stat.Rate) RouterInfo(net.i2p.data.router.RouterInfo) ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) MaskedIPSet(net.i2p.router.util.MaskedIPSet) RateStat(net.i2p.stat.RateStat) TreeSet(java.util.TreeSet) PeerProfile(net.i2p.router.peermanager.PeerProfile)

Aggregations

Hash (net.i2p.data.Hash)4 MaskedIPSet (net.i2p.router.util.MaskedIPSet)4 ArrayList (java.util.ArrayList)2 RouterInfo (net.i2p.data.router.RouterInfo)2 TreeSet (java.util.TreeSet)1 Certificate (net.i2p.data.Certificate)1 Destination (net.i2p.data.Destination)1 PeerProfile (net.i2p.router.peermanager.PeerProfile)1 RandomIterator (net.i2p.router.util.RandomIterator)1 Rate (net.i2p.stat.Rate)1 RateStat (net.i2p.stat.RateStat)1