i2psnark: Don't disconnect seeds immediately if comments enabled (ticket #2288)

Implement variable timeout
Hardcode handshake bytes
Log tweaks
This commit is contained in:
zzz
2018-07-31 14:13:33 +00:00
parent a51d260a78
commit 5c3e408772
4 changed files with 47 additions and 15 deletions

View File

@ -79,6 +79,7 @@ public class Peer implements Comparable<Peer>
private long uploaded_old[] = {-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1};
private static final byte[] HANDSHAKE = DataHelper.getASCII("BitTorrent protocol");
// bytes per bt spec: 0011223344556677
private static final long OPTION_EXTENSION = 0x0000000000100000l;
private static final long OPTION_FAST = 0x0000000000000004l;
@ -343,8 +344,8 @@ public class Peer implements Comparable<Peer>
dout = new DataOutputStream(out);
// Handshake write - header
dout.write(19);
dout.write("BitTorrent protocol".getBytes("UTF-8"));
dout.write(HANDSHAKE.length);
dout.write(HANDSHAKE);
// Handshake write - options
long myOptions = OPTION_EXTENSION;
// we can't handle HAVE_ALL or HAVE_NONE if we don't know the number of pieces
@ -365,17 +366,15 @@ public class Peer implements Comparable<Peer>
// Handshake read - header
byte b = din.readByte();
if (b != 19)
if (b != HANDSHAKE.length)
throw new IOException("Handshake failure, expected 19, got "
+ (b & 0xff) + " on " + sock);
byte[] bs = new byte[19];
byte[] bs = new byte[HANDSHAKE.length];
din.readFully(bs);
String bittorrentProtocol = new String(bs, "UTF-8");
if (!"BitTorrent protocol".equals(bittorrentProtocol))
if (!Arrays.equals(HANDSHAKE, bs))
throw new IOException("Handshake failure, expected "
+ "'BitTorrent protocol', got '"
+ bittorrentProtocol + "'");
+ "'BitTorrent protocol'");
// Handshake read - options
options = din.readLong();
@ -685,6 +684,13 @@ public class Peer implements Comparable<Peer>
}
}
/** @since 0.9.36 */
public long getMaxInactiveTime() {
return isCompleted() && !isInteresting() ?
PeerCoordinator.MAX_SEED_INACTIVE :
PeerCoordinator.MAX_INACTIVE;
}
/**
* Send keepalive
*/

View File

@ -96,7 +96,7 @@ class PeerCheckerTask implements Runnable
continue;
}
if (peer.getInactiveTime() > PeerCoordinator.MAX_INACTIVE) {
if (peer.getInactiveTime() > peer.getMaxInactiveTime()) {
if (_log.shouldLog(Log.WARN))
_log.warn("Disconnecting peer idle " +
DataHelper.formatDuration(peer.getInactiveTime()) + ": " + peer);

View File

@ -75,6 +75,7 @@ class PeerCoordinator implements PeerListener
final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int MAX_UPLOADERS = 8;
public static final long MAX_INACTIVE = 8*60*1000;
public static final long MAX_SEED_INACTIVE = 2*60*1000;
/**
* Approximation of the number of current uploaders (unchoked peers),
@ -496,7 +497,7 @@ class PeerCoordinator implements PeerListener
synchronized(peers)
{
Peer old = peerIDInList(peer.getPeerID(), peers);
if ( (old != null) && (old.getInactiveTime() > MAX_INACTIVE) ) {
if (old != null && old.getInactiveTime() > old.getMaxInactiveTime()) {
// idle for 8 minutes, kill the old con (32KB/8min = 68B/sec minimum for one block)
if (_log.shouldLog(Log.WARN))
_log.warn("Remomving old peer: " + peer + ": " + old + ", inactive for " + old.getInactiveTime());
@ -592,8 +593,10 @@ class PeerCoordinator implements PeerListener
// thus there is an additional check in connected()
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
// Check if we already have this peer before we build the connection
if (need_more) {
Peer old = peerIDInList(peer.getPeerID(), peers);
need_more = need_more && ((old == null) || (old.getInactiveTime() > MAX_INACTIVE));
need_more = old == null || old.getInactiveTime() > old.getMaxInactiveTime();
}
}
if (need_more)
@ -629,9 +632,9 @@ class PeerCoordinator implements PeerListener
}
if (_log.shouldLog(Log.DEBUG)) {
if (peer.isConnected())
_log.info("Add peer already connected: " + peer);
_log.debug("Add peer already connected: " + peer);
else
_log.info("Connections: " + peersize + "/" + getMaxConnections()
_log.debug("Connections: " + peersize + "/" + getMaxConnections()
+ " not accepting extra peer: " + peer);
}
return false;

View File

@ -25,12 +25,16 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.Log;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
class PeerState implements DataLoader
{
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
@ -242,14 +246,33 @@ class PeerState implements DataLoader
} // synch
boolean interest = listener.gotBitField(peer, bitfield);
setInteresting(interest);
if (bitfield.complete() && !interest) {
// They are seeding and we are seeding,
// why did they contact us? (robert)
// Dump them quick before we send our whole bitmap
// If we both support comments, allow it
if (listener.getUtil().utCommentsEnabled()) {
Map<String, BEValue> handshake = peer.getHandshakeMap();
if (handshake != null) {
BEValue bev = handshake.get("m");
if (bev != null) {
try {
if (bev.getMap().get(ExtensionHandler.TYPE_COMMENT) != null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Allowing seed that connects to seeds for comments: " + peer);
setInteresting(interest);
return;
}
} catch (InvalidBEncodingException ibee) {}
}
}
}
if (_log.shouldLog(Log.WARN))
_log.warn("Disconnecting seed that connects to seeds: " + peer);
peer.disconnect(true);
} else {
setInteresting(interest);
}
}