forked from I2P_Developers/i2p.i2p
i2psnark: Add support for fast extensions (BEP 6)
untested
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user