Search in sources :

Example 16 with Hash

use of net.i2p.data.Hash in project i2p.i2p by i2p.

the class KRPC method getPeersAndAnnounce.

/**
 *  Get peers for a torrent, and announce to the closest annMax nodes we find.
 *  This is an iterative lookup in the DHT.
 *  Blocking!
 *  Caller should run in a thread.
 *
 *  @param ih the Info Hash (torrent)
 *  @param max maximum number of peers to return
 *  @param maxWait the maximum time to wait (ms) must be > 0
 *  @param annMax the number of peers to announce to
 *  @param annMaxWait the maximum total time to wait for announces, may be 0 to return immediately without waiting for acks
 *  @param isSeed true if seed, false if leech
 *  @param noSeeds true if we do not want seeds in the result
 *  @return possibly empty (never null)
 */
@SuppressWarnings("unchecked")
public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait, boolean isSeed, boolean noSeeds) {
    // check local tracker first
    InfoHash iHash = new InfoHash(ih);
    Collection<Hash> rv = _tracker.getPeers(iHash, max, noSeeds);
    rv.remove(_myNodeInfo.getHash());
    if (rv.size() >= max)
        return rv;
    rv = new HashSet<Hash>(rv);
    long endTime = _context.clock().now() + maxWait;
    // needs to be much higher than log(size) since many lookups will fail
    // at first and we will give up too early
    int maxNodes = 30;
    // Initial set to try, will get added to as we go
    List<NodeInfo> nodes = _knownNodes.findClosest(iHash, maxNodes);
    NodeInfoComparator comp = new NodeInfoComparator(iHash);
    SortedSet<NodeInfo> toTry = new TreeSet<NodeInfo>(comp);
    SortedSet<NodeInfo> heardFrom = new TreeSet<NodeInfo>(comp);
    toTry.addAll(nodes);
    SortedSet<NodeInfo> tried = new TreeSet<NodeInfo>(comp);
    if (_log.shouldLog(Log.INFO))
        _log.info("Starting getPeers for " + iHash + " (b64: " + new NID(ih) + ") " + " with " + nodes.size() + " to try");
    for (int i = 0; i < maxNodes; i++) {
        if (!_isRunning)
            break;
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Now to try: " + toTry);
        NodeInfo nInfo;
        try {
            nInfo = toTry.first();
        } catch (NoSuchElementException nsee) {
            break;
        }
        toTry.remove(nInfo);
        tried.add(nInfo);
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Try " + i + ": " + nInfo);
        ReplyWaiter waiter = sendGetPeers(nInfo, iHash, noSeeds);
        if (waiter == null)
            continue;
        synchronized (waiter) {
            try {
                waiter.wait(Math.max(30 * 1000, (Math.min(45 * 1000, endTime - _context.clock().now()))));
            } catch (InterruptedException ie) {
            }
        }
        int replyType = waiter.getReplyCode();
        if (replyType == REPLY_NONE) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Got no reply");
        } else if (replyType == REPLY_PONG) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Got pong");
        } else if (replyType == REPLY_PEERS) {
            heardFrom.add(waiter.getSentTo());
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Got peers");
            List<Hash> reply = (List<Hash>) waiter.getReplyObject();
            // 0.9.8.1 it will
            if (!reply.isEmpty()) {
                for (int j = 0; j < reply.size() && rv.size() < max; j++) {
                    Hash h = reply.get(j);
                    if (!h.equals(_myNodeInfo.getHash()))
                        rv.add(h);
                }
            }
            if (_log.shouldLog(Log.INFO))
                _log.info("Finished get Peers, got " + reply.size() + " from DHT, returning " + rv.size());
            break;
        } else if (replyType == REPLY_NODES) {
            heardFrom.add(waiter.getSentTo());
            List<NodeInfo> reply = (List<NodeInfo>) waiter.getReplyObject();
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Got " + reply.size() + " nodes");
            for (NodeInfo ni : reply) {
                if (!(ni.equals(_myNodeInfo) || tried.contains(ni) || toTry.contains(ni)))
                    toTry.add(ni);
            }
        } else if (replyType == REPLY_NETWORK_FAIL) {
            break;
        } else {
            if (_log.shouldLog(Log.INFO))
                _log.info("Got unexpected reply " + replyType + ": " + waiter.getReplyObject());
        }
        if (_context.clock().now() > endTime)
            break;
        if (!toTry.isEmpty() && !heardFrom.isEmpty() && comp.compare(toTry.first(), heardFrom.first()) >= 0) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Finished get Peers, nothing closer to try after " + (i + 1));
            break;
        }
    }
    // now announce
    if (!heardFrom.isEmpty()) {
        announce(ih, isSeed);
        // announce to the closest we've heard from
        int annCnt = 0;
        long start = _context.clock().now();
        for (Iterator<NodeInfo> iter = heardFrom.iterator(); iter.hasNext() && annCnt < annMax && _isRunning; ) {
            NodeInfo annTo = iter.next();
            if (_log.shouldLog(Log.INFO))
                _log.info("Announcing to closest from get peers: " + annTo);
            long toWait = annMaxWait > 0 ? Math.min(annMaxWait, 60 * 1000) : 0;
            if (announce(ih, annTo, toWait, isSeed))
                annCnt++;
            if (annMaxWait > 0) {
                annMaxWait -= _context.clock().now() - start;
                if (annMaxWait < 1000)
                    break;
            }
        }
    } else {
        // so this is essentially just a retry
        if (_log.shouldLog(Log.INFO))
            _log.info("Announcing to closest in kbuckets after get peers failed");
        announce(ih, annMax, annMaxWait, isSeed);
    }
    if (_log.shouldLog(Log.INFO)) {
        _log.info("Finished get Peers, returning " + rv.size());
        _log.info("Tried: " + tried);
        _log.info("Heard from: " + heardFrom);
        _log.info("Not tried: " + toTry);
    }
    return rv;
}
Also used : Hash(net.i2p.data.Hash) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) List(java.util.List) NoSuchElementException(java.util.NoSuchElementException)

Example 17 with Hash

use of net.i2p.data.Hash in project i2p.i2p by i2p.

the class KRPC method announce.

/**
 *  Announce somebody else we know about to ourselves.
 *  Non-blocking.
 *
 *  @param ih the Info Hash (torrent)
 *  @param peerHash the peer's Hash
 */
public void announce(byte[] ih, byte[] peerHash, boolean isSeed) {
    InfoHash iHash = new InfoHash(ih);
    _tracker.announce(iHash, new Hash(peerHash), isSeed);
// Do NOT do this, corrupts the Hash cache and the Peer ID
// _tracker.announce(iHash, Hash.create(peerHash));
}
Also used : Hash(net.i2p.data.Hash)

Example 18 with Hash

use of net.i2p.data.Hash in project i2p.i2p by i2p.

the class KRPC method receiveGetPeers.

/**
 *  Handle and respond to the query
 */
private void receiveGetPeers(MsgID msgID, NodeInfo nInfo, InfoHash ih, boolean noSeeds) throws InvalidBEncodingException {
    if (_log.shouldLog(Log.INFO))
        _log.info("Rcvd get_peers from: " + nInfo + " for: " + ih + " noseeds? " + noSeeds);
    // generate and save random token
    Token token = new Token(_context);
    _outgoingTokens.put(token, nInfo);
    if (_log.shouldLog(Log.INFO))
        _log.info("Stored new OB token: " + token + " for: " + nInfo);
    List<Hash> peers = _tracker.getPeers(ih, MAX_WANT, noSeeds);
    // Check this before removing him, so we don't needlessly send nodes
    // if he's the only one on the torrent.
    boolean noPeers = peers.isEmpty();
    // him
    peers.remove(nInfo.getHash());
    if (noPeers) {
        // similar to find node, but with token
        // get closest from DHT
        List<NodeInfo> nodes = _knownNodes.findClosest(ih, K);
        // him
        nodes.remove(nInfo);
        // me
        nodes.remove(_myNodeInfo);
        byte[] nodeArray = new byte[nodes.size() * NodeInfo.LENGTH];
        for (int i = 0; i < nodes.size(); i++) {
            System.arraycopy(nodes.get(i).getData(), 0, nodeArray, i * NodeInfo.LENGTH, NodeInfo.LENGTH);
        }
        sendNodes(nInfo, msgID, token, nodeArray);
    } else {
        List<byte[]> hashes;
        if (peers.isEmpty()) {
            hashes = Collections.emptyList();
        } else {
            hashes = new ArrayList<byte[]>(peers.size());
            for (Hash peer : peers) {
                hashes.add(peer.getData());
            }
        }
        sendPeers(nInfo, msgID, token, hashes);
    }
}
Also used : Hash(net.i2p.data.Hash)

Example 19 with Hash

use of net.i2p.data.Hash in project i2p.i2p by i2p.

the class KRPC method receivePeers.

/**
 *  rcv 32 byte Hashes, return as a List
 *  @throws NPE, IllegalArgumentException, and others too
 */
private List<Hash> receivePeers(NodeInfo nInfo, List<BEValue> peers) throws InvalidBEncodingException {
    if (_log.shouldLog(Log.INFO))
        _log.info("Rcvd peers from: " + nInfo);
    int max = Math.min(MAX_WANT * 2, peers.size());
    List<Hash> rv = new ArrayList<Hash>(max);
    for (BEValue bev : peers) {
        byte[] b = bev.getBytes();
        if (b.length != Hash.HASH_LENGTH) {
            if (_log.shouldWarn())
                _log.info("Bad peers entry from: " + nInfo);
            continue;
        }
        // Hash h = new Hash(b);
        Hash h = Hash.create(b);
        rv.add(h);
        if (rv.size() >= max)
            break;
    }
    if (_log.shouldLog(Log.INFO))
        _log.info("Rcvd " + peers.size() + " peers from: " + nInfo + ": " + DataHelper.toString(rv));
    return rv;
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) BEValue(org.klomp.snark.bencode.BEValue)

Example 20 with Hash

use of net.i2p.data.Hash in project i2p.i2p by i2p.

the class NewsFetcher method processBlocklistEntries.

/**
 *  Process blocklist entries
 *
 *  @since 0.9.28
 */
private void processBlocklistEntries(BlocklistEntries ble) {
    long oldTime = _context.getProperty(PROP_BLOCKLIST_TIME, 0L);
    if (ble.updated <= oldTime) {
        if (_log.shouldWarn())
            _log.warn("Not processing blocklist " + new Date(ble.updated) + ", already have " + new Date(oldTime));
        return;
    }
    Blocklist bl = _context.blocklist();
    Banlist ban = _context.banlist();
    DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT);
    fmt.setTimeZone(SystemVersion.getSystemTimeZone(_context));
    String reason = "Blocklist feed " + new Date(ble.updated);
    int banned = 0;
    for (Iterator<String> iter = ble.entries.iterator(); iter.hasNext(); ) {
        String s = iter.next();
        if (s.length() == 44) {
            byte[] b = Base64.decode(s);
            if (b == null || b.length != Hash.HASH_LENGTH) {
                iter.remove();
                continue;
            }
            Hash h = Hash.create(b);
            if (!ban.isBanlistedForever(h))
                ban.banlistRouterForever(h, reason);
        } else {
            byte[] ip = Addresses.getIP(s);
            if (ip == null) {
                iter.remove();
                continue;
            }
            if (!bl.isBlocklisted(ip))
                bl.add(ip);
        }
        if (++banned >= BlocklistEntries.MAX_ENTRIES) {
            // prevent somebody from destroying the whole network
            break;
        }
    }
    for (String s : ble.removes) {
        if (s.length() == 44) {
            byte[] b = Base64.decode(s);
            if (b == null || b.length != Hash.HASH_LENGTH)
                continue;
            Hash h = Hash.create(b);
            if (ban.isBanlistedForever(h))
                ban.unbanlistRouter(h);
        } else {
            byte[] ip = Addresses.getIP(s);
            if (ip == null)
                continue;
            if (bl.isBlocklisted(ip))
                bl.remove(ip);
        }
    }
    // Save the blocks. We do not save the unblocks.
    File f = new SecureFile(_context.getConfigDir(), BLOCKLIST_DIR);
    f.mkdirs();
    f = new File(f, BLOCKLIST_FILE);
    boolean fail = false;
    BufferedWriter out = null;
    try {
        out = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(f), "UTF-8"));
        out.write("# ");
        out.write(ble.supdated);
        out.newLine();
        banned = 0;
        for (String s : ble.entries) {
            // IPv6
            s = s.replace(':', ';');
            out.write(reason);
            out.write(':');
            out.write(s);
            out.newLine();
            if (++banned >= BlocklistEntries.MAX_ENTRIES)
                break;
        }
    } catch (IOException ioe) {
        _log.error("Error writing blocklist", ioe);
        fail = true;
    } finally {
        if (out != null)
            try {
                out.close();
            } catch (IOException ioe) {
            }
    }
    if (!fail) {
        f.setLastModified(ble.updated);
        String upd = Long.toString(ble.updated);
        _context.router().saveConfig(PROP_BLOCKLIST_TIME, upd);
        _mgr.notifyVersionAvailable(this, _currentURI, BLOCKLIST, "", HTTP, null, upd, "");
    }
    if (_log.shouldWarn())
        _log.warn("Processed " + ble.entries.size() + " blocks and " + ble.removes.size() + " unblocks from news feed");
}
Also used : SecureFile(net.i2p.util.SecureFile) IOException(java.io.IOException) Hash(net.i2p.data.Hash) Date(java.util.Date) RFC822Date(net.i2p.util.RFC822Date) Banlist(net.i2p.router.Banlist) BufferedWriter(java.io.BufferedWriter) Blocklist(net.i2p.router.Blocklist) DateFormat(java.text.DateFormat) OutputStreamWriter(java.io.OutputStreamWriter) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) SU3File(net.i2p.crypto.SU3File) SecureFile(net.i2p.util.SecureFile) File(java.io.File)

Aggregations

Hash (net.i2p.data.Hash)235 RouterInfo (net.i2p.data.router.RouterInfo)45 ArrayList (java.util.ArrayList)29 TunnelId (net.i2p.data.TunnelId)20 Destination (net.i2p.data.Destination)18 HashSet (java.util.HashSet)17 ConvertToHash (net.i2p.util.ConvertToHash)17 IOException (java.io.IOException)16 TunnelInfo (net.i2p.router.TunnelInfo)15 DataFormatException (net.i2p.data.DataFormatException)14 Properties (java.util.Properties)13 Date (java.util.Date)12 DatabaseEntry (net.i2p.data.DatabaseEntry)11 SessionKey (net.i2p.data.SessionKey)11 RouterAddress (net.i2p.data.router.RouterAddress)11 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)9 I2NPMessage (net.i2p.data.i2np.I2NPMessage)9 Job (net.i2p.router.Job)9 OutNetMessage (net.i2p.router.OutNetMessage)9 TunnelPoolSettings (net.i2p.router.TunnelPoolSettings)8