Search in sources :

Example 1 with DHT

use of org.klomp.snark.dht.DHT in project i2p.i2p by i2p.

the class SnarkManager method addMagnet.

/**
 * Add a torrent with the info hash alone (magnet / maggot)
 * External use is for UpdateRunner.
 *
 * @param name hex or b32 name from the magnet link
 * @param ih 20 byte info hash
 * @param trackerURL may be null
 * @param updateStatus should we add this magnet to the config file,
 *                     to save it across restarts, in case we don't get
 *                     the metadata before shutdown?
 * @param dataDir must exist, or null to default to snark data directory
 * @param listener to intercept callbacks, should pass through to this
 * @return the new Snark or null on failure
 * @throws RuntimeException via Snark.fatal()
 * @since 0.9.4
 */
public Snark addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus, boolean autoStart, File dataDir, CompleteListener listener) {
    String dirPath = dataDir != null ? dataDir.getAbsolutePath() : getDataDir().getPath();
    Snark torrent = new Snark(_util, name, ih, trackerURL, listener, _peerCoordinatorSet, _connectionAcceptor, false, dirPath);
    synchronized (_snarks) {
        Snark snark = getTorrentByInfoHash(ih);
        if (snark != null) {
            addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName()));
            return null;
        }
        // Tell the dir monitor not to delete us
        _magnets.add(name);
        if (updateStatus)
            saveMagnetStatus(ih, dirPath, trackerURL, name);
        _snarks.put(name, torrent);
    }
    if (autoStart) {
        startTorrent(ih);
        if (false)
            addMessage(_t("Fetching {0}", name));
        DHT dht = _util.getDHT();
        boolean shouldWarn = _util.connected() && _util.getOpenTrackers().isEmpty() && ((!_util.shouldUseDHT()) || dht == null || dht.size() <= 0);
        if (shouldWarn) {
            addMessage(_t("Open trackers are disabled and we have no DHT peers. " + "Fetch of {0} may not succeed until you start another torrent, enable open trackers, or enable DHT.", name));
        }
    } else {
        addMessage(_t("Adding {0}", name));
    }
    return torrent;
}
Also used : DHT(org.klomp.snark.dht.DHT)

Example 2 with DHT

use of org.klomp.snark.dht.DHT in project i2p.i2p by i2p.

the class TrackerClient method unannounce.

/**
 *  Creates a thread for each tracker in parallel if tunnel is still open
 *  @since 0.9.1
 */
private void unannounce() {
    // Local DHT tracker unannounce
    DHT dht = _util.getDHT();
    if (dht != null)
        dht.unannounce(snark.getInfoHash());
    int i = 0;
    for (TCTracker tr : trackers) {
        if (_util.connected() && tr.started && (!tr.stop) && tr.trackerProblems == null) {
            try {
                (new I2PAppThread(new Unannouncer(tr), _threadName + " U" + (++i), true)).start();
            } catch (OutOfMemoryError oom) {
                // probably ran out of threads, ignore
                tr.reset();
            }
        } else {
            tr.reset();
        }
    }
}
Also used : DHT(org.klomp.snark.dht.DHT) I2PAppThread(net.i2p.util.I2PAppThread)

Example 3 with DHT

use of org.klomp.snark.dht.DHT in project i2p.i2p by i2p.

the class TrackerClient method loop.

/**
 *  Announce to all the trackers, get peers from PEX and DHT, then queue up a SimpleTimer2 event.
 *  This will take several seconds to several minutes.
 *  @since 0.9.1
 */
private void loop() {
    try {
        // normally this will only go once, then call queueLoop() and return
        while (!stop) {
            if (!verifyConnected()) {
                stop = true;
                return;
            }
            // Local DHT tracker announce
            DHT dht = _util.getDHT();
            if (dht != null && (meta == null || !meta.isPrivate()))
                dht.announce(snark.getInfoHash(), coordinator.completed());
            int oldSeenPeers = snark.getTrackerSeenPeers();
            int maxSeenPeers = 0;
            if (!trackers.isEmpty()) {
                maxSeenPeers = getPeersFromTrackers(trackers);
                // fast update for UI at startup
                if (maxSeenPeers > oldSeenPeers)
                    snark.setTrackerSeenPeers(maxSeenPeers);
            }
            int p = getPeersFromPEX();
            if (p > maxSeenPeers)
                maxSeenPeers = p;
            p = getPeersFromDHT();
            if (p > maxSeenPeers) {
                maxSeenPeers = p;
                // fast update for UI at startup
                if (maxSeenPeers > oldSeenPeers)
                    snark.setTrackerSeenPeers(maxSeenPeers);
            }
            // backup if DHT needs bootstrapping
            if (trackers.isEmpty() && !backupTrackers.isEmpty() && dht != null && dht.size() < 16) {
                p = getPeersFromTrackers(backupTrackers);
                if (p > maxSeenPeers)
                    maxSeenPeers = p;
            }
            // we could try and total the unique peers but that's too hard for now
            snark.setTrackerSeenPeers(maxSeenPeers);
            if (stop)
                return;
            try {
                // Sleep some minutes...
                // Sleep the minimum interval for all the trackers, but 60s minimum
                int delay;
                Random r = _util.getContext().random();
                int random = r.nextInt(120 * 1000);
                if (completed && runStarted)
                    delay = 3 * SLEEP * 60 * 1000 + random;
                else if (snark.getTrackerProblems() != null && ++consecutiveFails < MAX_CONSEC_FAILS)
                    delay = INITIAL_SLEEP;
                else if ((!runStarted) && _runCount < MAX_CONSEC_FAILS)
                    delay = INITIAL_SLEEP;
                else
                    // sleep a while, when we wake up we will contact only the trackers whose intervals have passed
                    delay = SLEEP * 60 * 1000 + random;
                if (delay > 20 * 1000) {
                    // put ourselves on SimpleTimer2
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Requeueing in " + DataHelper.formatDuration(delay) + ": " + Thread.currentThread().getName());
                    queueLoop(delay);
                    return;
                } else if (delay > 0) {
                    Thread.sleep(delay);
                }
            } catch (InterruptedException interrupt) {
            }
        }
    // *** end of while loop
    }// try
     catch (Throwable t) {
        _log.error("TrackerClient: " + t, t);
        if (t instanceof OutOfMemoryError)
            throw (OutOfMemoryError) t;
    }
}
Also used : DHT(org.klomp.snark.dht.DHT) Random(java.util.Random)

Example 4 with DHT

use of org.klomp.snark.dht.DHT in project i2p.i2p by i2p.

the class SnarkManager method stopAllTorrents.

/**
 * Stop all running torrents, and close the tunnel after a delay
 * to allow for announces.
 * If called at router shutdown via Jetty shutdown hook -&gt; webapp destroy() -&gt; stop(),
 * the tunnel won't actually be closed as the SimpleTimer2 is already shutdown
 * or will be soon, so we delay a few seconds inline.
 * @param finalShutdown if true, sleep at the end if any torrents were running
 * @since 0.9.1
 */
public void stopAllTorrents(boolean finalShutdown) {
    _stopping = true;
    if (finalShutdown && _log.shouldLog(Log.WARN))
        _log.warn("SnarkManager final shutdown");
    int count = 0;
    for (Snark snark : _snarks.values()) {
        if (!snark.isStopped()) {
            if (count == 0)
                addMessage(_t("Stopping all torrents and closing the I2P tunnel."));
            count++;
            if (finalShutdown)
                snark.stopTorrent(true);
            else
                stopTorrent(snark, false);
            // How to do this without creating a ton of threads?
            if (count % 8 == 0) {
                try {
                    Thread.sleep(20);
                } catch (InterruptedException ie) {
                }
            }
        } else {
            CommentSet cs = snark.getComments();
            if (cs != null) {
                synchronized (cs) {
                    if (cs.isModified()) {
                        locked_saveComments(snark, cs);
                    }
                }
            }
        }
    }
    if (_util.connected()) {
        if (count > 0) {
            DHT dht = _util.getDHT();
            if (dht != null)
                dht.stop();
            addMessage(_t("Closing I2P tunnel after notifying trackers."));
            if (finalShutdown) {
                long toWait = 5 * 1000;
                if (SystemVersion.isARM())
                    toWait *= 2;
                try {
                    Thread.sleep(toWait);
                } catch (InterruptedException ie) {
                }
                _util.disconnect();
                _stopping = false;
            } else {
                // Only schedule this if not a final shutdown
                _context.simpleTimer2().addEvent(new Disconnector(), 60 * 1000);
            }
        } else {
            _util.disconnect();
            _stopping = false;
            addMessage(_t("I2P tunnel closed."));
        }
    }
}
Also used : DHT(org.klomp.snark.dht.DHT) CommentSet(org.klomp.snark.comments.CommentSet)

Example 5 with DHT

use of org.klomp.snark.dht.DHT in project i2p.i2p by i2p.

the class TrackerClient method getPeersFromDHT.

/**
 *  @return max peers seen
 */
private int getPeersFromDHT() {
    // Get peers from DHT
    // FIXME this needs to be in its own thread
    int rv = 0;
    DHT dht = _util.getDHT();
    if (dht != null && (meta == null || !meta.isPrivate()) && (!stop) && (meta == null || _util.getContext().clock().now() > lastDHTAnnounce + MIN_DHT_ANNOUNCE_INTERVAL)) {
        int numwant;
        if (!coordinator.needOutboundPeers())
            numwant = 1;
        else
            numwant = _util.getMaxConnections();
        Collection<Hash> hashes = dht.getPeersAndAnnounce(snark.getInfoHash(), numwant, 5 * 60 * 1000, DHT_ANNOUNCE_PEERS, 3 * 60 * 1000, coordinator.completed(), numwant <= 1);
        if (!hashes.isEmpty()) {
            runStarted = true;
            lastDHTAnnounce = _util.getContext().clock().now();
            rv = hashes.size();
        } else {
            lastDHTAnnounce = 0;
        }
        if (_log.shouldLog(Log.INFO))
            _log.info("Got " + hashes + " from DHT");
        // now try these peers
        if ((!stop) && !hashes.isEmpty()) {
            List<Peer> peers = new ArrayList<Peer>(hashes.size());
            for (Hash h : hashes) {
                try {
                    PeerID pID = new PeerID(h.getData(), _util);
                    peers.add(new Peer(pID, snark.getID(), snark.getInfoHash(), snark.getMetaInfo()));
                } catch (InvalidBEncodingException ibe) {
                }
            }
            Random r = _util.getContext().random();
            Collections.shuffle(peers, r);
            Iterator<Peer> it = peers.iterator();
            while ((!stop) && it.hasNext() && coordinator.needOutboundPeers()) {
                Peer cur = it.next();
                if (coordinator.addPeer(cur) && it.hasNext()) {
                    int delay = r.nextInt(DELAY_RAND) + DELAY_MIN;
                    try {
                        Thread.sleep(delay);
                    } catch (InterruptedException ie) {
                    }
                }
            }
        }
    } else {
        if (_log.shouldLog(Log.INFO))
            _log.info("Not getting DHT peers");
    }
    return rv;
}
Also used : DHT(org.klomp.snark.dht.DHT) InvalidBEncodingException(org.klomp.snark.bencode.InvalidBEncodingException) Random(java.util.Random) ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) ConvertToHash(net.i2p.util.ConvertToHash)

Aggregations

DHT (org.klomp.snark.dht.DHT)9 ArrayList (java.util.ArrayList)3 Random (java.util.Random)3 InvalidBEncodingException (org.klomp.snark.bencode.InvalidBEncodingException)2 File (java.io.File)1 IOException (java.io.IOException)1 Date (java.util.Date)1 Hash (net.i2p.data.Hash)1 ConvertToHash (net.i2p.util.ConvertToHash)1 I2PAppThread (net.i2p.util.I2PAppThread)1 SecureFile (net.i2p.util.SecureFile)1 Snark (org.klomp.snark.Snark)1 BEValue (org.klomp.snark.bencode.BEValue)1 CommentSet (org.klomp.snark.comments.CommentSet)1