forked from I2P_Developers/i2p.i2p
i2psnark: Don't disconnect seeds immediately if comments enabled (ticket #2288)
Implement variable timeout Hardcode handshake bytes Log tweaks
This commit is contained in:
@ -79,6 +79,7 @@ public class Peer implements Comparable<Peer>
|
|||||||
private long uploaded_old[] = {-1,-1,-1};
|
private long uploaded_old[] = {-1,-1,-1};
|
||||||
private long downloaded_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
|
// bytes per bt spec: 0011223344556677
|
||||||
private static final long OPTION_EXTENSION = 0x0000000000100000l;
|
private static final long OPTION_EXTENSION = 0x0000000000100000l;
|
||||||
private static final long OPTION_FAST = 0x0000000000000004l;
|
private static final long OPTION_FAST = 0x0000000000000004l;
|
||||||
@ -343,8 +344,8 @@ public class Peer implements Comparable<Peer>
|
|||||||
dout = new DataOutputStream(out);
|
dout = new DataOutputStream(out);
|
||||||
|
|
||||||
// Handshake write - header
|
// Handshake write - header
|
||||||
dout.write(19);
|
dout.write(HANDSHAKE.length);
|
||||||
dout.write("BitTorrent protocol".getBytes("UTF-8"));
|
dout.write(HANDSHAKE);
|
||||||
// Handshake write - options
|
// Handshake write - options
|
||||||
long myOptions = OPTION_EXTENSION;
|
long myOptions = OPTION_EXTENSION;
|
||||||
// we can't handle HAVE_ALL or HAVE_NONE if we don't know the number of pieces
|
// 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
|
// Handshake read - header
|
||||||
byte b = din.readByte();
|
byte b = din.readByte();
|
||||||
if (b != 19)
|
if (b != HANDSHAKE.length)
|
||||||
throw new IOException("Handshake failure, expected 19, got "
|
throw new IOException("Handshake failure, expected 19, got "
|
||||||
+ (b & 0xff) + " on " + sock);
|
+ (b & 0xff) + " on " + sock);
|
||||||
|
|
||||||
byte[] bs = new byte[19];
|
byte[] bs = new byte[HANDSHAKE.length];
|
||||||
din.readFully(bs);
|
din.readFully(bs);
|
||||||
String bittorrentProtocol = new String(bs, "UTF-8");
|
if (!Arrays.equals(HANDSHAKE, bs))
|
||||||
if (!"BitTorrent protocol".equals(bittorrentProtocol))
|
|
||||||
throw new IOException("Handshake failure, expected "
|
throw new IOException("Handshake failure, expected "
|
||||||
+ "'BitTorrent protocol', got '"
|
+ "'BitTorrent protocol'");
|
||||||
+ bittorrentProtocol + "'");
|
|
||||||
|
|
||||||
// Handshake read - options
|
// Handshake read - options
|
||||||
options = din.readLong();
|
options = din.readLong();
|
||||||
@ -684,6 +683,13 @@ public class Peer implements Comparable<Peer>
|
|||||||
return -1; //"no state";
|
return -1; //"no state";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.36 */
|
||||||
|
public long getMaxInactiveTime() {
|
||||||
|
return isCompleted() && !isInteresting() ?
|
||||||
|
PeerCoordinator.MAX_SEED_INACTIVE :
|
||||||
|
PeerCoordinator.MAX_INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send keepalive
|
* Send keepalive
|
||||||
|
@ -96,7 +96,7 @@ class PeerCheckerTask implements Runnable
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peer.getInactiveTime() > PeerCoordinator.MAX_INACTIVE) {
|
if (peer.getInactiveTime() > peer.getMaxInactiveTime()) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Disconnecting peer idle " +
|
_log.warn("Disconnecting peer idle " +
|
||||||
DataHelper.formatDuration(peer.getInactiveTime()) + ": " + peer);
|
DataHelper.formatDuration(peer.getInactiveTime()) + ": " + peer);
|
||||||
|
@ -75,6 +75,7 @@ class PeerCoordinator implements PeerListener
|
|||||||
final static long CHECK_PERIOD = 40*1000; // 40 seconds
|
final static long CHECK_PERIOD = 40*1000; // 40 seconds
|
||||||
final static int MAX_UPLOADERS = 8;
|
final static int MAX_UPLOADERS = 8;
|
||||||
public static final long MAX_INACTIVE = 8*60*1000;
|
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),
|
* Approximation of the number of current uploaders (unchoked peers),
|
||||||
@ -496,7 +497,7 @@ class PeerCoordinator implements PeerListener
|
|||||||
synchronized(peers)
|
synchronized(peers)
|
||||||
{
|
{
|
||||||
Peer old = peerIDInList(peer.getPeerID(), 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)
|
// idle for 8 minutes, kill the old con (32KB/8min = 68B/sec minimum for one block)
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Remomving old peer: " + peer + ": " + old + ", inactive for " + old.getInactiveTime());
|
_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()
|
// thus there is an additional check in connected()
|
||||||
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
|
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
|
||||||
// Check if we already have this peer before we build the connection
|
// Check if we already have this peer before we build the connection
|
||||||
Peer old = peerIDInList(peer.getPeerID(), peers);
|
if (need_more) {
|
||||||
need_more = need_more && ((old == null) || (old.getInactiveTime() > MAX_INACTIVE));
|
Peer old = peerIDInList(peer.getPeerID(), peers);
|
||||||
|
need_more = old == null || old.getInactiveTime() > old.getMaxInactiveTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_more)
|
if (need_more)
|
||||||
@ -629,9 +632,9 @@ class PeerCoordinator implements PeerListener
|
|||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.DEBUG)) {
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
if (peer.isConnected())
|
if (peer.isConnected())
|
||||||
_log.info("Add peer already connected: " + peer);
|
_log.debug("Add peer already connected: " + peer);
|
||||||
else
|
else
|
||||||
_log.info("Connections: " + peersize + "/" + getMaxConnections()
|
_log.debug("Connections: " + peersize + "/" + getMaxConnections()
|
||||||
+ " not accepting extra peer: " + peer);
|
+ " not accepting extra peer: " + peer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -25,12 +25,16 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.ByteArray;
|
import net.i2p.data.ByteArray;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
import org.klomp.snark.bencode.BEValue;
|
||||||
|
import org.klomp.snark.bencode.InvalidBEncodingException;
|
||||||
|
|
||||||
class PeerState implements DataLoader
|
class PeerState implements DataLoader
|
||||||
{
|
{
|
||||||
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
|
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
|
||||||
@ -242,14 +246,33 @@ class PeerState implements DataLoader
|
|||||||
} // synch
|
} // synch
|
||||||
|
|
||||||
boolean interest = listener.gotBitField(peer, bitfield);
|
boolean interest = listener.gotBitField(peer, bitfield);
|
||||||
setInteresting(interest);
|
|
||||||
if (bitfield.complete() && !interest) {
|
if (bitfield.complete() && !interest) {
|
||||||
// They are seeding and we are seeding,
|
// They are seeding and we are seeding,
|
||||||
// why did they contact us? (robert)
|
// why did they contact us? (robert)
|
||||||
// Dump them quick before we send our whole bitmap
|
// 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))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Disconnecting seed that connects to seeds: " + peer);
|
_log.warn("Disconnecting seed that connects to seeds: " + peer);
|
||||||
peer.disconnect(true);
|
peer.disconnect(true);
|
||||||
|
} else {
|
||||||
|
setInteresting(interest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user