i2psnark:

- Change "private" value in infohash from string to number,
    to match what everybody else does
  - Send seed/leech status in DHT announces (ticket #1280)
This commit is contained in:
zzz
2014-05-25 19:41:01 +00:00
parent c28f707f55
commit 5a3eab0c7c
4 changed files with 32 additions and 15 deletions

View File

@ -220,7 +220,9 @@ public class MetaInfo
Object o = val.getValue(); Object o = val.getValue();
// Is it supposed to be a number or a string? // Is it supposed to be a number or a string?
// i2psnark does it as a string. BEP 27 doesn't say. // i2psnark does it as a string. BEP 27 doesn't say.
// Transmission does numbers. // Transmission does numbers. So does libtorrent.
// We handle both as of 0.9.9.
// We switch to storing as number as of 0.9.14.
privateTorrent = "1".equals(o) || privateTorrent = "1".equals(o) ||
((o instanceof Number) && ((Number) o).intValue() == 1); ((o instanceof Number) && ((Number) o).intValue() == 1);
} else { } else {
@ -621,7 +623,9 @@ public class MetaInfo
info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8))); info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8)));
// BEP 27 // BEP 27
if (privateTorrent) if (privateTorrent)
info.put("private", new BEValue(DataHelper.getUTF8("1"))); // switched to number in 0.9.14
//info.put("private", new BEValue(DataHelper.getUTF8("1")));
info.put("private", new BEValue(Integer.valueOf(1)));
info.put("piece length", new BEValue(Integer.valueOf(piece_length))); info.put("piece length", new BEValue(Integer.valueOf(piece_length)));
info.put("pieces", new BEValue(piece_hashes)); info.put("pieces", new BEValue(piece_hashes));

View File

@ -650,7 +650,9 @@ public class TrackerClient implements Runnable {
numwant = 1; numwant = 1;
else else
numwant = _util.getMaxConnections(); numwant = _util.getMaxConnections();
Collection<Hash> hashes = dht.getPeersAndAnnounce(snark.getInfoHash(), numwant, 5*60*1000, 1, 3*60*1000); Collection<Hash> hashes = dht.getPeersAndAnnounce(snark.getInfoHash(), numwant,
5*60*1000, 1, 3*60*1000,
coordinator.completed());
if (!hashes.isEmpty()) { if (!hashes.isEmpty()) {
runStarted = true; runStarted = true;
lastDHTAnnounce = _util.getContext().clock().now(); lastDHTAnnounce = _util.getContext().clock().now();

View File

@ -45,9 +45,12 @@ public interface DHT {
* @param maxWait the maximum time to wait (ms) must be > 0 * @param maxWait the maximum time to wait (ms) must be > 0
* @param annMax the number of peers to announce to * @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 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
* @return possibly empty (never null) * @return possibly empty (never null)
*/ */
public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait); public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait,
int annMax, long annMaxWait,
boolean isSeed);
/** /**
* Announce to ourselves. * Announce to ourselves.
@ -58,7 +61,7 @@ public interface DHT {
public void announce(byte[] ih); public void announce(byte[] ih);
/** /**
* Announce somebody else we know about. * Announce somebody else we know about to ourselves.
* Non-blocking. * Non-blocking.
* *
* @param ih the Info Hash (torrent) * @param ih the Info Hash (torrent)
@ -84,9 +87,10 @@ public interface DHT {
* *
* @param ih the Info Hash (torrent) * @param ih the Info Hash (torrent)
* @param maxWait the maximum total time to wait (ms) or 0 to do all in parallel and return immediately. * @param maxWait the maximum total time to wait (ms) or 0 to do all in parallel and return immediately.
* @param isSeed true if seed, false if leech
* @return the number of successful announces, not counting ourselves. * @return the number of successful announces, not counting ourselves.
*/ */
public int announce(byte[] ih, int max, long maxWait); public int announce(byte[] ih, int max, long maxWait, boolean isSeed);
/** /**
* Stop everything. * Stop everything.

View File

@ -315,9 +315,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
* @param maxWait the maximum time to wait (ms) must be > 0 * @param maxWait the maximum time to wait (ms) must be > 0
* @param annMax the number of peers to announce to * @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 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
* @return possibly empty (never null) * @return possibly empty (never null)
*/ */
public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait) { public Collection<Hash> getPeersAndAnnounce(byte[] ih, int max, long maxWait,
int annMax, long annMaxWait,
boolean isSeed) {
// check local tracker first // check local tracker first
InfoHash iHash = new InfoHash(ih); InfoHash iHash = new InfoHash(ih);
Collection<Hash> rv = _tracker.getPeers(iHash, max); Collection<Hash> rv = _tracker.getPeers(iHash, max);
@ -424,7 +427,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Announcing to closest from get peers: " + annTo); _log.info("Announcing to closest from get peers: " + annTo);
long toWait = annMaxWait > 0 ? Math.min(annMaxWait, 60*1000) : 0; long toWait = annMaxWait > 0 ? Math.min(annMaxWait, 60*1000) : 0;
if (announce(ih, annTo, toWait)) if (announce(ih, annTo, toWait, isSeed))
annCnt++; annCnt++;
if (annMaxWait > 0) { if (annMaxWait > 0) {
annMaxWait -= _context.clock().now() - start; annMaxWait -= _context.clock().now() - start;
@ -437,7 +440,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
// so this is essentially just a retry // so this is essentially just a retry
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Announcing to closest in kbuckets after get peers failed"); _log.info("Announcing to closest in kbuckets after get peers failed");
announce(ih, annMax, annMaxWait); announce(ih, annMax, annMaxWait, isSeed);
} }
if (_log.shouldLog(Log.INFO)) { if (_log.shouldLog(Log.INFO)) {
_log.info("Finished get Peers, returning " + rv.size()); _log.info("Finished get Peers, returning " + rv.size());
@ -460,7 +463,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
} }
/** /**
* Announce somebody else we know about. * Announce somebody else we know about to ourselves.
* Non-blocking. * Non-blocking.
* *
* @param ih the Info Hash (torrent) * @param ih the Info Hash (torrent)
@ -500,9 +503,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
* @param ih the Info Hash (torrent) * @param ih the Info Hash (torrent)
* @param max maximum number of peers to announce to * @param max maximum number of peers to announce to
* @param maxWait the maximum total time to wait (ms) or 0 to do all in parallel and return immediately. * @param maxWait the maximum total time to wait (ms) or 0 to do all in parallel and return immediately.
* @param isSeed true if seed, false if leech
* @return the number of successful announces, not counting ourselves. * @return the number of successful announces, not counting ourselves.
*/ */
public int announce(byte[] ih, int max, long maxWait) { public int announce(byte[] ih, int max, long maxWait, boolean isSeed) {
announce(ih); announce(ih);
int rv = 0; int rv = 0;
long start = _context.clock().now(); long start = _context.clock().now();
@ -513,7 +517,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
for (NodeInfo nInfo : nodes) { for (NodeInfo nInfo : nodes) {
if (!_isRunning) if (!_isRunning)
break; break;
if (announce(ih, nInfo, Math.min(maxWait, 60*1000))) if (announce(ih, nInfo, Math.min(maxWait, 60*1000), isSeed))
rv++; rv++;
maxWait -= _context.clock().now() - start; maxWait -= _context.clock().now() - start;
if (maxWait < 1000) if (maxWait < 1000)
@ -531,9 +535,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
* @param ih the Info Hash (torrent) * @param ih the Info Hash (torrent)
* @param nInfo the peer to announce to * @param nInfo the peer to announce to
* @param maxWait the maximum time to wait (ms) or 0 to return immediately. * @param maxWait the maximum time to wait (ms) or 0 to return immediately.
* @param isSeed true if seed, false if leech
* @return success * @return success
*/ */
private boolean announce(byte[] ih, NodeInfo nInfo, long maxWait) { private boolean announce(byte[] ih, NodeInfo nInfo, long maxWait, boolean isSeed) {
InfoHash iHash = new InfoHash(ih); InfoHash iHash = new InfoHash(ih);
// it isn't clear from BEP 5 if a token is bound to a single infohash? // it isn't clear from BEP 5 if a token is bound to a single infohash?
// for now, just bind to the NID // for now, just bind to the NID
@ -580,7 +585,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
} }
// send and wait on rcv msg lock unless maxWait <= 0 // send and wait on rcv msg lock unless maxWait <= 0
ReplyWaiter waiter = sendAnnouncePeer(nInfo, iHash, token); ReplyWaiter waiter = sendAnnouncePeer(nInfo, iHash, token, isSeed);
if (waiter == null) if (waiter == null)
return false; return false;
if (maxWait <= 0) if (maxWait <= 0)
@ -743,9 +748,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
* Non-blocking, will fail if we don't have the dest for the nodeinfo * Non-blocking, will fail if we don't have the dest for the nodeinfo
* *
* @param nInfo who to send it to * @param nInfo who to send it to
* @param isSeed true if seed, false if leech
* @return null on error * @return null on error
*/ */
private ReplyWaiter sendAnnouncePeer(NodeInfo nInfo, InfoHash ih, Token token) { private ReplyWaiter sendAnnouncePeer(NodeInfo nInfo, InfoHash ih, Token token, boolean isSeed) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Sending announce of " + ih + " to: " + nInfo); _log.info("Sending announce of " + ih + " to: " + nInfo);
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
@ -755,6 +761,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
// port ignored // port ignored
args.put("port", Integer.valueOf(TrackerClient.PORT)); args.put("port", Integer.valueOf(TrackerClient.PORT));
args.put("token", token.getData()); args.put("token", token.getData());
args.put("seed", Integer.valueOf(isSeed ? 1 : 0));
map.put("a", args); map.put("a", args);
// an announce need not be signed, we have a token // an announce need not be signed, we have a token
ReplyWaiter rv = sendQuery(nInfo, map, false); ReplyWaiter rv = sendQuery(nInfo, map, false);