* i2psnark:
- Fix NPE and other partials bugs - More extension message stubbing - Log tweaks
This commit is contained in:
@ -0,0 +1,36 @@
|
||||
package org.klomp.snark;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.klomp.snark.bencode.BEncoder;
|
||||
import org.klomp.snark.bencode.BEValue;
|
||||
|
||||
/**
|
||||
* REF: BEP 10 Extension Protocol
|
||||
* @since 0.8.2
|
||||
*/
|
||||
class ExtensionHandshake {
|
||||
|
||||
private static final byte[] _payload = buildPayload();
|
||||
|
||||
/**
|
||||
* @return bencoded data
|
||||
*/
|
||||
static byte[] getPayload() {
|
||||
return _payload;
|
||||
}
|
||||
|
||||
/** just a test for now */
|
||||
private static byte[] buildPayload() {
|
||||
Map<String, Object> handshake = new HashMap();
|
||||
Map<String, Integer> m = new HashMap();
|
||||
m.put("foo", Integer.valueOf(99));
|
||||
m.put("bar", Integer.valueOf(101));
|
||||
handshake.put("m", m);
|
||||
handshake.put("p", Integer.valueOf(6881));
|
||||
handshake.put("v", "I2PSnark");
|
||||
handshake.put("reqq", Integer.valueOf(5));
|
||||
return BEncoder.bencode(handshake);
|
||||
}
|
||||
}
|
@ -66,6 +66,7 @@ public class Peer implements Comparable
|
||||
private long options;
|
||||
|
||||
/**
|
||||
* Outgoing connection.
|
||||
* Creates a disconnected peer given a PeerID, your own id and the
|
||||
* relevant MetaInfo.
|
||||
*/
|
||||
@ -80,6 +81,7 @@ public class Peer implements Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming connection.
|
||||
* Creates a unconnected peer from the input and output stream got
|
||||
* from the socket. Note that the complete handshake (which can take
|
||||
* some time or block indefinitely) is done in the calling Thread to
|
||||
@ -201,6 +203,7 @@ public class Peer implements Comparable
|
||||
// Do we need to handshake?
|
||||
if (din == null)
|
||||
{
|
||||
// Outgoing connection
|
||||
sock = util.connect(peerID);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Connected to " + peerID + ": " + sock);
|
||||
@ -234,6 +237,7 @@ public class Peer implements Comparable
|
||||
+ PeerID.idencode(expected_id) + "'");
|
||||
}
|
||||
} else {
|
||||
// Incoming connection
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Already have din [" + sock + "] with " + toString());
|
||||
}
|
||||
@ -242,6 +246,12 @@ public class Peer implements Comparable
|
||||
PeerConnectionOut out = new PeerConnectionOut(this, dout);
|
||||
PeerState s = new PeerState(this, listener, metainfo, in, out);
|
||||
|
||||
if ((options & OPTION_EXTENSION) != 0) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Peer supports extensions, sending test message");
|
||||
out.sendExtension(0, ExtensionHandshake.getPayload());
|
||||
}
|
||||
|
||||
// Send our bitmap
|
||||
if (bitfield != null)
|
||||
s.out.sendBitfield(bitfield);
|
||||
@ -331,12 +341,10 @@ public class Peer implements Comparable
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Read the remote side's hash and peerID fully from " + toString());
|
||||
|
||||
// if ((options & OPTION_EXTENSION) != 0) {
|
||||
if (options != 0) {
|
||||
// send them something
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
//_log.debug("Peer supports extension message, what should we say? " + toString());
|
||||
_log.debug("Peer supports options 0x" + Long.toString(options, 16) + ", what should we say? " + toString());
|
||||
_log.debug("Peer supports options 0x" + Long.toString(options, 16) + ": " + toString());
|
||||
}
|
||||
|
||||
return bs;
|
||||
|
@ -114,8 +114,9 @@ class PeerCheckerTask extends TimerTask
|
||||
|
||||
// Choke a percentage of them rather than all so it isn't so drastic...
|
||||
// unless this torrent is over the limit all by itself.
|
||||
// choke 5/8 of the time when seeding and 3/8 when leeching
|
||||
boolean overBWLimitChoke = upload > 0 &&
|
||||
((overBWLimit && random.nextBoolean()) ||
|
||||
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 2 : 4))) ||
|
||||
(coordinator.overUpBWLimit(uploaded)));
|
||||
|
||||
// If we are at our max uploaders and we have lots of other
|
||||
|
@ -615,13 +615,13 @@ public class PeerCoordinator implements PeerListener
|
||||
// share blocks rather than starting from 0 with each peer.
|
||||
// This is where the flaws of the snark data model are really exposed.
|
||||
// Could also randomize within the duplicate set rather than strict rarest-first
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("parallel request (end game?) for " + peer + ": piece = " + piece);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("parallel request (end game?) for " + peer + ": piece = " + piece);
|
||||
}
|
||||
}
|
||||
if (record) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Now requesting: piece " + piece + " priority " + piece.getPriority());
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(peer + " is now requesting: piece " + piece + " priority " + piece.getPriority());
|
||||
piece.setRequested(true);
|
||||
}
|
||||
return piece.getId();
|
||||
@ -945,11 +945,11 @@ public class PeerCoordinator implements PeerListener
|
||||
PartialPiece pp = iter.next();
|
||||
int savedPiece = pp.getPiece();
|
||||
if (havePieces.get(savedPiece)) {
|
||||
iter.remove();
|
||||
// this is just a double-check, it should be in there
|
||||
for(Piece piece : wantedPieces) {
|
||||
if (piece.getId() == savedPiece) {
|
||||
piece.setRequested(true);
|
||||
iter.remove();
|
||||
if (_log.shouldLog(Log.INFO)) {
|
||||
_log.info("Restoring orphaned partial piece " + pp +
|
||||
" Partial list size now: " + partialPieces.size());
|
||||
@ -957,8 +957,12 @@ public class PeerCoordinator implements PeerListener
|
||||
return pp;
|
||||
}
|
||||
}
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Partial piece " + pp + " NOT in wantedPieces??");
|
||||
}
|
||||
}
|
||||
if (_log.shouldLog(Log.WARN) && !partialPieces.isEmpty())
|
||||
_log.warn("Peer " + peer + " has none of our partials " + partialPieces);
|
||||
}
|
||||
// ...and this section turns this into the general move-requests-around code!
|
||||
// Temporary? So PeerState never calls wantPiece() directly for now...
|
||||
@ -1004,7 +1008,7 @@ public class PeerCoordinator implements PeerListener
|
||||
}
|
||||
}
|
||||
}
|
||||
return wantPiece(peer, havePieces, false) > 0;
|
||||
return wantPiece(peer, havePieces, false) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -609,6 +609,9 @@ class PeerState implements DataLoader
|
||||
*/
|
||||
synchronized void addRequest()
|
||||
{
|
||||
// no bitfield yet? nothing to request then.
|
||||
if (bitfield == null)
|
||||
return;
|
||||
boolean more_pieces = true;
|
||||
while (more_pieces)
|
||||
{
|
||||
|
Reference in New Issue
Block a user