forked from I2P_Developers/i2p.i2p
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:
@ -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));
|
||||||
|
@ -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();
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user