forked from I2P_Developers/i2p.i2p
* i2psnark:
- Fix bug preventing completion announcement, broken in 0.9.1 - Fix setting short retry time after initial announce failure - Fix DHT announce and getPeers - Fix DHT warning message - log tweaks
This commit is contained in:
@ -828,7 +828,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
} else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
|
||||
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
|
||||
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
|
||||
} else if (_util.getDHT() != null) {
|
||||
} else if (_util.shouldUseDHT()) {
|
||||
addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName()));
|
||||
} else {
|
||||
addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
|
||||
|
@ -27,6 +27,7 @@ import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
@ -100,6 +101,7 @@ public class TrackerClient implements Runnable {
|
||||
// these 2 used in loop()
|
||||
private volatile boolean runStarted;
|
||||
private volatile int consecutiveFails;
|
||||
private boolean completed;
|
||||
private volatile boolean _fastUnannounce;
|
||||
|
||||
private final List<Tracker> trackers;
|
||||
@ -218,11 +220,16 @@ public class TrackerClient implements Runnable {
|
||||
try {
|
||||
if (!_initialized) {
|
||||
setup();
|
||||
// FIXME dht
|
||||
if (trackers.isEmpty()) {
|
||||
stop = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (trackers.isEmpty() && _util.getDHT() == null) {
|
||||
stop = true;
|
||||
this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?",
|
||||
this.snark.getBaseName()));
|
||||
_log.error("No valid trackers for " + this.snark.getBaseName());
|
||||
this.snark.stopTorrent();
|
||||
return;
|
||||
}
|
||||
if (!_initialized) {
|
||||
_initialized = true;
|
||||
// FIXME only when starting everybody at once, not for a single torrent
|
||||
long delay = I2PAppContext.getGlobalContext().random().nextInt(30*1000);
|
||||
@ -296,15 +303,7 @@ public class TrackerClient implements Runnable {
|
||||
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
|
||||
}
|
||||
}
|
||||
|
||||
if (trackers.isEmpty() && _util.getDHT() == null) {
|
||||
stop = true;
|
||||
this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?",
|
||||
this.snark.getBaseName()));
|
||||
_log.error("No valid trackers for " + this.snark.getBaseName());
|
||||
this.snark.stopTorrent();
|
||||
return;
|
||||
}
|
||||
this.completed = coordinator.getLeft() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +330,6 @@ public class TrackerClient implements Runnable {
|
||||
long uploaded = coordinator.getUploaded();
|
||||
long downloaded = coordinator.getDownloaded();
|
||||
long left = coordinator.getLeft(); // -1 in magnet mode
|
||||
boolean completed = (left == 0);
|
||||
|
||||
// First time we got a complete download?
|
||||
String event;
|
||||
@ -345,8 +343,7 @@ public class TrackerClient implements Runnable {
|
||||
|
||||
// *** loop once for each tracker
|
||||
int maxSeenPeers = 0;
|
||||
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
|
||||
Tracker tr = (Tracker)iter.next();
|
||||
for (Tracker tr : trackers) {
|
||||
if ((!stop) && (!tr.stop) &&
|
||||
(completed || coordinator.needOutboundPeers() || !tr.started) &&
|
||||
(event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
||||
@ -468,7 +465,9 @@ public class TrackerClient implements Runnable {
|
||||
numwant = 1;
|
||||
else
|
||||
numwant = _util.getMaxConnections();
|
||||
List<Hash> hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000);
|
||||
Collection<Hash> hashes = dht.getPeers(snark.getInfoHash(), numwant, 2*60*1000);
|
||||
if (!hashes.isEmpty())
|
||||
runStarted = true;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Got " + hashes + " from DHT");
|
||||
// announce ourselves while the token is still good
|
||||
@ -509,10 +508,6 @@ public class TrackerClient implements Runnable {
|
||||
if (stop)
|
||||
return;
|
||||
|
||||
if (!runStarted)
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(" Retrying in one minute...");
|
||||
|
||||
try {
|
||||
// Sleep some minutes...
|
||||
// Sleep the minimum interval for all the trackers, but 60s minimum
|
||||
@ -522,6 +517,8 @@ public class TrackerClient implements Runnable {
|
||||
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;
|
||||
|
@ -4,7 +4,7 @@ package org.klomp.snark.dht;
|
||||
* GPLv2
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
@ -42,9 +42,9 @@ public interface DHT {
|
||||
* @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
|
||||
* @return list or empty list (never null)
|
||||
* @return possibly empty (never null)
|
||||
*/
|
||||
public List<Hash> getPeers(byte[] ih, int max, long maxWait);
|
||||
public Collection<Hash> getPeers(byte[] ih, int max, long maxWait);
|
||||
|
||||
/**
|
||||
* Announce to ourselves.
|
||||
|
@ -299,25 +299,28 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
* @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
|
||||
* @return list or empty list (never null)
|
||||
* @return possibly empty (never null)
|
||||
*/
|
||||
public List<Hash> getPeers(byte[] ih, int max, long maxWait) {
|
||||
public Collection<Hash> getPeers(byte[] ih, int max, long maxWait) {
|
||||
// check local tracker first
|
||||
InfoHash iHash = new InfoHash(ih);
|
||||
List<Hash> rv = _tracker.getPeers(iHash, max);
|
||||
Collection<Hash> rv = _tracker.getPeers(iHash, max);
|
||||
rv.remove(_myNodeInfo.getHash());
|
||||
if (!rv.isEmpty())
|
||||
return rv; // TODO get DHT too?
|
||||
if (rv.size() >= max)
|
||||
return rv;
|
||||
rv = new HashSet(rv);
|
||||
long endTime = _context.clock().now() + maxWait;
|
||||
|
||||
// Initial set to try, will get added to as we go
|
||||
List<NodeInfo> nodes = _knownNodes.findClosest(iHash, max);
|
||||
int maxNodes = 12;
|
||||
List<NodeInfo> nodes = _knownNodes.findClosest(iHash, maxNodes);
|
||||
SortedSet<NodeInfo> toTry = new TreeSet(new NodeInfoComparator(iHash));
|
||||
toTry.addAll(nodes);
|
||||
Set<NodeInfo> tried = new HashSet();
|
||||
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting getPeers with " + nodes.size() + " to try");
|
||||
for (int i = 0; i < max; i++) {
|
||||
_log.info("Starting getPeers for " + iHash + " with " + nodes.size() + " to try");
|
||||
for (int i = 0; i < maxNodes; i++) {
|
||||
if (!_isRunning)
|
||||
break;
|
||||
NodeInfo nInfo;
|
||||
@ -334,7 +337,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
continue;
|
||||
synchronized(waiter) {
|
||||
try {
|
||||
waiter.wait(maxWait);
|
||||
waiter.wait(Math.max(20*1000, (Math.min(40*1000, endTime - _context.clock().now()))));
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
@ -350,9 +353,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
_log.info("Got peers");
|
||||
List<Hash> reply = (List<Hash>) waiter.getReplyObject();
|
||||
if (!reply.isEmpty()) {
|
||||
for (int j = 0; j < reply.size() && rv.size() < max; j++) {
|
||||
rv.add(reply.get(j));
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Finished get Peers, returning " + reply.size());
|
||||
return reply;
|
||||
_log.info("Finished get Peers, got " + rv.size() + " from DHT, returning " + reply.size());
|
||||
return rv;
|
||||
}
|
||||
} else if (replyType == REPLY_NODES) {
|
||||
List<NodeInfo> reply = (List<NodeInfo>) waiter.getReplyObject();
|
||||
@ -366,10 +372,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Got unexpected reply " + replyType + ": " + waiter.getReplyObject());
|
||||
}
|
||||
if (_context.clock().now() > endTime)
|
||||
break;
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Finished get Peers, fail");
|
||||
return Collections.EMPTY_LIST;
|
||||
_log.info("Finished get Peers, " + rv.size() + " from local and none from DHT");
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -465,7 +473,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
if (maxWait <= 0)
|
||||
return false;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("No token for announce to " + nInfo + " sending get_peers first");
|
||||
_log.info("No token for announce to " + nInfo + ", sending get_peers first");
|
||||
ReplyWaiter waiter = sendGetPeers(nInfo, iHash);
|
||||
if (waiter == null)
|
||||
return false;
|
||||
@ -478,20 +486,20 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
||||
int replyType = waiter.getReplyCode();
|
||||
if (!(replyType == REPLY_PEERS || replyType == REPLY_NODES)) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Get_peers failed to " + nInfo);
|
||||
_log.info("Get_peers in announce() failed to " + nInfo);
|
||||
return false;
|
||||
}
|
||||
// we should have a token now
|
||||
token = _incomingTokens.get(nInfo.getNID());
|
||||
if (token == null) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Huh? no token after get_peers succeeded to " + nInfo);
|
||||
_log.info("Huh? no token after get_peers in announce() succeeded to " + nInfo);
|
||||
return false;
|
||||
}
|
||||
maxWait -= _context.clock().now() - start;
|
||||
if (maxWait < 1000) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Ran out of time after get_peers succeeded to " + nInfo);
|
||||
_log.info("Ran out of time after get_peers in announce() succeeded to " + nInfo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
2012-08-15 zzz
|
||||
* i2psnark:
|
||||
- Fix bug preventing completion announcement, broken in 0.9.1
|
||||
- Fix setting short retry time after initial announce failure
|
||||
- Fix DHT announce and getPeers
|
||||
- Fix DHT warning message
|
||||
|
||||
2012-08-13 zzz
|
||||
* SSU EstablishmentManager:
|
||||
- Remove use of outbound timers in EstablishmentManager; drive all events in Establisher thread
|
||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 9;
|
||||
public final static long BUILD = 10;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user