i2psnark: Add support for fast extensions (BEP 6)

untested
This commit is contained in:
zzz
2015-05-19 18:13:32 +00:00
parent 2dc3d68418
commit de4d47de95
6 changed files with 285 additions and 56 deletions

View File

@@ -155,10 +155,17 @@ class PeerState implements DataLoader
setInteresting(true);
}
void bitfieldMessage(byte[] bitmap)
{
synchronized(this)
{
void bitfieldMessage(byte[] bitmap) {
bitfieldMessage(bitmap, false);
}
/**
* @param bitmap null to use the isAll param
* @param isAll only if bitmap == null: true for have_all, false for have_none
* @since 0.9.21
*/
private void bitfieldMessage(byte[] bitmap, boolean isAll) {
synchronized(this) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " rcv bitfield");
if (bitfield != null)
@@ -172,10 +179,24 @@ class PeerState implements DataLoader
// XXX - Check for weird bitfield and disconnect?
// FIXME will have to regenerate the bitfield after we know exactly
// how many pieces there are, as we don't know how many spare bits there are.
if (metainfo == null)
bitfield = new BitField(bitmap, bitmap.length * 8);
else
bitfield = new BitField(bitmap, metainfo.getPieces());
if (metainfo == null) {
if (bitmap != null) {
bitfield = new BitField(bitmap, bitmap.length * 8);
} else {
// we can't handle this situation
if (_log.shouldLog(Log.WARN))
_log.warn("have_x w/o metainfo: " + isAll);
return;
}
} else {
if (bitmap != null) {
bitfield = new BitField(bitmap, metainfo.getPieces());
} else {
bitfield = new BitField(metainfo.getPieces());
if (isAll)
bitfield.setAll();
}
}
}
if (metainfo == null)
return;
@@ -198,12 +219,17 @@ class PeerState implements DataLoader
+ piece + ", " + begin + ", " + length + ") ");
if (metainfo == null)
return;
if (choking)
{
if (_log.shouldLog(Log.INFO))
_log.info("Request received, but choking " + peer);
if (choking) {
if (peer.supportsFast()) {
if (_log.shouldInfo())
_log.info("Request received, sending reject to choked " + peer);
out.sendReject(piece, begin, length);
} else {
if (_log.shouldInfo())
_log.info("Request received, but choking " + peer);
}
return;
}
}
// Sanity check
if (piece < 0
@@ -227,8 +253,14 @@ class PeerState implements DataLoader
// Todo: limit number of requests also? (robert 64 x 4KB)
if (out.queuedBytes() + length > MAX_PIPELINE_BYTES)
{
if (_log.shouldLog(Log.WARN))
_log.warn("Discarding request over pipeline limit from " + peer);
if (peer.supportsFast()) {
if (_log.shouldWarn())
_log.warn("Rejecting request over pipeline limit from " + peer);
out.sendReject(piece, begin, length);
} else {
if (_log.shouldWarn())
_log.warn("Discarding request over pipeline limit from " + peer);
}
return;
}
@@ -536,6 +568,58 @@ class PeerState implements DataLoader
listener.gotPort(peer, port, port + 1);
}
/////////// fast message handlers /////////
/**
* BEP 6
* Treated as "have" for now
* @since 0.9.21
*/
void suggestMessage(int piece) {
if (_log.shouldInfo())
_log.info("Handling suggest as have(" + piece + ") from " + peer);
haveMessage(piece);
}
/**
* BEP 6
* @param isAll true for have_all, false for have_none
* @since 0.9.21
*/
void haveMessage(boolean isAll) {
bitfieldMessage(null, isAll);
}
/**
* BEP 6
* @since 0.9.21
*/
void rejectMessage(int piece, int begin, int length) {
if (_log.shouldInfo())
_log.info("Got reject(" + piece + ',' + begin + ',' + length + ") from " + peer);
out.cancelRequest(piece, begin, length);
synchronized(this) {
for (Iterator<Request> iter = outstandingRequests.iterator(); iter.hasNext(); ) {
Request req = iter.next();
if (req.getPiece() == piece && req.off == begin && req.len == length)
iter.remove();
}
if (lastRequest != null && lastRequest.getPiece() == piece &&
lastRequest.off == begin && lastRequest.len == length)
lastRequest = null;
}
}
/**
* BEP 6
* Ignored for now
* @since 0.9.21
*/
void allowedFastMessage(int piece) {
if (_log.shouldInfo())
_log.info("Ignoring allowed_fast(" + piece + ") from " + peer);
}
void unknownMessage(int type, byte[] bs)
{
if (_log.shouldLog(Log.WARN))
@@ -543,6 +627,8 @@ class PeerState implements DataLoader
+ " length: " + bs.length);
}
/////////// end message handlers /////////
/**
* We now have this piece.
* Tell the peer and cancel any requests for the piece.