class PeerCoordinator extends Object implements PeerListener, BandwidthListener
This class manages the core BitTorrent coordination logic:
Thread safety: This class uses extensive synchronization for thread-safe peer management. External access to some fields is documented where permitted.
| Modifier and Type | Field and Description |
|---|---|
(package private) static long | CHECK_PERIODHow often to recompute upload slots and UI download speeds. |
static long | MAX_INACTIVEInactivity timeout before disconnecting idle peers. |
static long | MAX_SEED_INACTIVEInactivity timeout before disconnecting idle seeds. |
(package private) static int | MAX_UPLOADERSMaximum peers we upload to at once. |
(package private) MetaInfo | metainfoWill be null when in magnet mode. |
(package private) Deque<Peer> | peersSynchronize on this when changing peers or downloaders. |
(package private) static long | PIECE_STALL_TIMEOUTInactivity timeout before re-queuing a requested piece that is receiving no data. |
(package private) static int | RATE_DEPTHNumber of samples in the upload/download rate windows. |
(package private) Storage | storageWill be null when in magnet mode. |
| Constructor and Description |
|---|
PeerCoordinator(I2PSnarkUtil util,
byte[] id,
byte[] infohash,
MetaInfo metainfo,
Storage storage,
CoordinatorListener listener,
Snark torrent,
BandwidthListener bwl)Create a peer coordinator for the torrent. |
| Modifier and Type | Method and Description |
|---|---|
void | addInterestedAndChoking(int toAdd) |
boolean | addPeer(Peer peer)Add peer (inbound or outbound) |
int | allowedUploaders()Return number of allowed uploaders for this torrent. |
void | ban(Hash h)Ban the given hash. |
void | banWebPeer(String host,
boolean isPermanent)Ban a web peer for this torrent, for while or permanently. |
(package private) void | checkStalledPieces(long now)Re-queues any requested pieces that have received no data for PIECE_STALL_TIMEOUT, so they
can be requested from other peers. |
boolean | completed()Returns whether the torrent is complete. |
void | connected(Peer peer)Called when a peer connection is established. |
void | decrementUploaders(boolean isInterested)Decrement the uploaders and (if set) the interestedUploaders counts |
void | disconnected(Peer peer)Called when a peer disconnects. |
void | downloaded(int size)Called when a peer has downloaded some bytes of a piece. |
long | getCurrentUploadRate()Returns the rate in Bps over last complete CHECK_PERIOD seconds |
long | getDownBWLimit()Current limit in Bps |
long | getDownloaded()Returns the total number of downloaded bytes of all peers. |
long | getDownloadRate()Returns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds |
byte[] | getID()Returns our peer ID. |
byte[] | getInfoHash()The info hash for this torrent. |
int | getInterestedAndChoking()The current value. |
int | getInterestedUploaders()Uploaders, interested only. |
long | getLeft()Bytes not yet in storage. |
MetaInfo | getMetaInfo()Returns the metainfo for this torrent. |
String | getName()Returns the torrent name. |
long | getNeededLength()Bytes still wanted. |
PartialPiece | getPartialPiece(Peer peer,
BitField havePieces)Return partial piece to the PeerState if it's still wanted and peer has it. |
PartialPiece | getPartialPiece(Peer peer,
BitField havePieces,
Set<Integer> allowed)Return partial piece to the PeerState if it's still wanted and peer has it. |
PartialPiece | getPartialPiece(Peer peer,
int piece)Allocates a PartialPiece for a specific suggested piece, or returns null if the piece is not
wanted, is already being fetched, or the peer is already fetching it. |
int | getPeerCount()Returns the estimated peer count (may be stale). |
int | getPeers()Returns the current number of connected peers. |
(package private) Set<PeerID> | getPEXPeers()Called by TrackerClient |
(package private) static long | getRate(long[] array)The download or upload rate, per the param. |
Storage | getStorage()Returns the storage for this torrent. |
int | getSwarmPeerCount()Distinct swarm peers seen recently (within SWARM_PEER_TTL) or
currently connected, for the torrent view peer count. |
long | getUpBWLimit()Current limit in Bps |
long | getUploaded()Returns the total number of uploaded bytes of all peers. |
int | getUploaders()Uploaders whether interested or not Use this for per-torrent limits. |
long | getUploadRate()Returns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds |
I2PSnarkUtil | getUtil()Convenience |
boolean | gotBitField(Peer peer,
BitField bitfield)Returns true if the given bitfield contains at least one piece we are interested in. |
void | gotChoke(Peer peer,
boolean choke)Called when a choke message is received. |
void | gotCommentReq(Peer peer,
int num)Called when comments are requested via ut_comment |
void | gotComments(Peer peer,
List<Comment> comments)Called when comments are received via ut_comment |
void | gotExtension(Peer peer,
int id,
byte[] bs)PeerListener callback |
boolean | gotHave(Peer peer,
int piece)Whether we still want the given piece. |
void | gotInterest(Peer peer,
boolean interest)Called when an interested message is received. |
void | gotPeers(Peer peer,
List<PeerID> peers)Handle peers from PEX; a PeerListener callback. |
boolean | gotPiece(Peer peer,
PartialPiece pp)Returns false if the piece is no good (according to the hash). |
void | gotPort(Peer peer,
int port,
int rport)PeerListener callback Tell the DHT to ping it, this will get back the node info |
ByteArray | gotRequest(Peer peer,
int piece,
int off,
int len)Returns a byte array containing the requested piece or null of the piece is unknown. |
void | halt()Halt this coordinator, disconnecting all peers. |
boolean | halted()Returns whether this coordinator has been halted. |
boolean | isBanned(Hash h)Is the given hash banned? |
(package private) static boolean | isStalled(Piece p,
long now,
long timeout)Checks if the piece has been requested but has received no data for longer than the timeout. |
boolean | isWebPeerBanned(String host)Is a web peer banned? |
boolean | needOutboundPeers()Outbound. |
boolean | needPeers()Inbound. |
boolean | needPiece(Peer peer,
BitField havePieces)Called when we are downloading from the peer and may need to ask for a new piece. |
boolean | overDownBWLimit()Are we currently over the limit? |
boolean | overUpBWLimit()Is snark as a whole over its upload limit? |
boolean | overUpBWLimit(long total)Is a particular peer who has downloaded this many bytes from us in the last CHECK_PERIOD over
its limit? |
List<Peer> | peerList()Returns a snapshot of the connected peers list for web page detailed stats. |
(package private) void | recordSwarmPeer(Peer peer)Record a peer surfaced by any source (announce, PEX, DHT, inbound) as a
distinct swarm member, keyed by destination hash. |
void | restart()Restart after halt. |
void | savePartialPieces(Peer peer,
List<Request> partials)Save partial pieces on peer disconnection and hopefully restart it later. |
(package private) void | sendCommentReq(Peer peer)Send a commment request message to the peer, if he supports it. |
(package private) void | sendDHT(Peer peer)Send a DHT message to the peer, if we both support DHT. |
(package private) void | sendPeers(Peer peer)Send a PEX message to the peer, if he supports PEX. |
(package private) static void | setRate(long val,
long[] array)Push a value onto a RATE_DEPTH deep stack. |
void | setRateHistory(long up,
long down)Push the total uploaded/downloaded onto a RATE_DEPTH deep stack. |
void | setStorage(Storage stg)Store the storage after transition out of magnet mode. |
void | setUploaded(long up)The initial total of uploaded bytes of all peers, from a saved status. |
void | setUploaders(int upl,
int inter)Record the uploader and interested-uploader counts. |
void | setWantedPieces()Rebuild the wanted pieces list from storage. |
boolean | shouldRequest(Peer peer,
int size)Should we request this many bytes? |
boolean | shouldSend(int size)Should we send this many bytes? Do NOT call uploaded() if this returns true. |
(package private) void | unchokePeer()(Optimistically) unchoke. |
void | updatePiecePriorities()Maps file priorities to piece priorities. |
void | uploaded(int size)Called when a peer has uploaded some bytes of a piece. |
static final long CHECK_PERIOD
public static final long MAX_INACTIVE
public static final long MAX_SEED_INACTIVE
static final int MAX_UPLOADERS
MetaInfo metainfo
final Deque<Peer> peers
static final long PIECE_STALL_TIMEOUT
static final int RATE_DEPTH
Storage storage
public PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage, CoordinatorListener listener, Snark torrent, BandwidthListener bwl)
metainfo - null if in magnet modestorage - null if in magnet modepublic void addInterestedAndChoking(int toAdd)
public boolean addPeer(Peer peer)
public int allowedUploaders()
public void ban(Hash h)
ban in interface PeerListenerh - the hashpublic void banWebPeer(String host, boolean isPermanent)
host - the hostnamevoid checkStalledPieces(long now)
now - the current time in millisecondspublic boolean completed()
public void connected(Peer peer)
connected in interface PeerListenerpeer - the newly connected peerpublic void decrementUploaders(boolean isInterested)
public void disconnected(Peer peer)
disconnected in interface PeerListenerpeer - the disconnected peerpublic void downloaded(int size)
downloaded in interface BandwidthListenersize - the number of bytes receivedpublic long getCurrentUploadRate()
public long getDownBWLimit()
getDownBWLimit in interface BandwidthListenerpublic long getDownloaded()
public long getDownloadRate()
getDownloadRate in interface BandwidthListenerpublic byte[] getID()
public byte[] getInfoHash()
public int getInterestedAndChoking()
public int getInterestedUploaders()
public long getLeft()
public MetaInfo getMetaInfo()
public String getName()
public long getNeededLength()
public PartialPiece getPartialPiece(Peer peer, BitField havePieces)
getPartialPiece in interface PeerListenerhavePieces - pieces the peer has, the rv will be one of thesepublic PartialPiece getPartialPiece(Peer peer, BitField havePieces, Set<Integer> allowed)
When the allowed set is not null, only pieces in it are eligible, for requesting BEP 6 allowed fast pieces from a peer that chokes us.
getPartialPiece in interface PeerListenerhavePieces - pieces the peer has, the rv will be one of theseallowed - the pieces servable while choked, or null for no restrictionpublic PartialPiece getPartialPiece(Peer peer, int piece)
getPartialPiece in interface PeerListenerpeer - the peer that suggested the piecepiece - the suggested piece numberpublic int getPeerCount()
public int getPeers()
Set<PeerID> getPEXPeers()
static long getRate(long[] array)
public Storage getStorage()
public int getSwarmPeerCount()
SWARM_PEER_TTL) or
currently connected, for the torrent view peer count. Prunes stale
entries lazily.public long getUpBWLimit()
getUpBWLimit in interface BandwidthListenerpublic long getUploaded()
public int getUploaders()
public long getUploadRate()
getUploadRate in interface BandwidthListenerpublic I2PSnarkUtil getUtil()
getUtil in interface PeerListenerpublic boolean gotBitField(Peer peer, BitField bitfield)
gotBitField in interface PeerListenerpeer - the Peer that got the message.bitfield - a BitField containing the pieces that the other side has.public void gotChoke(Peer peer, boolean choke)
gotChoke in interface PeerListenerpeer - the peerchoke - true for choke, false for unchokepublic void gotCommentReq(Peer peer, int num)
gotCommentReq in interface PeerListenerpublic void gotComments(Peer peer, List<Comment> comments)
gotComments in interface PeerListenercomments - non-nullpublic void gotExtension(Peer peer, int id, byte[] bs)
gotExtension in interface PeerListenerpeer - the Peer that got the message.id - the message IDbs - the message payloadpublic boolean gotHave(Peer peer, int piece)
gotHave in interface PeerListenerpeer - the Peer that got the message.piece - the piece number that the per just got.public void gotInterest(Peer peer, boolean interest)
gotInterest in interface PeerListenerpeer - the peerinterest - true for interested, false for uninterestedpublic void gotPeers(Peer peer, List<PeerID> peers)
gotPeers in interface PeerListenerpeer - the Peer that got the message.peers - the peer IDs (dest hashes)public boolean gotPiece(Peer peer, PartialPiece pp)
gotPiece in interface PeerListenerpeer - the Peer that got the piece.pp - the piece received.RuntimeException - on a genuine storage error saving the piecepublic void gotPort(Peer peer, int port, int rport)
gotPort in interface PeerListenerrport - must be port + 1peer - the Peer that got the message.port - the query portpublic ByteArray gotRequest(Peer peer, int piece, int off, int len)
gotRequest in interface PeerListenerpeer - the Peer that wants the piece.piece - the piece number requested.off - byte offset into the piece.len - length of the chunk requested.RuntimeException - on IOE getting the datapublic void halt()
public boolean halted()
public boolean isBanned(Hash h)
isBanned in interface PeerListenerh - the hashstatic boolean isStalled(Piece p, long now, long timeout)
p - the piece to checknow - the current time in millisecondstimeout - the stall timeout in millisecondspublic boolean isWebPeerBanned(String host)
host - the hostnamepublic boolean needOutboundPeers()
public boolean needPeers()
public boolean needPiece(Peer peer, BitField havePieces)
needPiece in interface PeerListenerpeer - the Peer that will be asked to provide the piece.havePieces - a BitField containing the pieces that the other side has.public boolean overDownBWLimit()
overDownBWLimit in interface BandwidthListenerpublic boolean overUpBWLimit()
overUpBWLimit in interface BandwidthListenerpublic boolean overUpBWLimit(long total)
total - bytes uploaded to the peer in the last CHECK_PERIODpublic List<Peer> peerList()
void recordSwarmPeer(Peer peer)
peer - the peer, non-nullpublic void restart()
public void savePartialPieces(Peer peer, List<Request> partials)
Also mark the piece unrequested if this peer was the only one.
savePartialPieces in interface PeerListenerpeer - partials, must include the zero-offset (empty) ones too. No dup pieces. len field
in Requests is ignored.void sendCommentReq(Peer peer)
void sendDHT(Peer peer)
void sendPeers(Peer peer)
static void setRate(long val,
long[] array)val - the value to pusharray - the rate array to updatepublic void setRateHistory(long up,
long down)up - uploaded bytes this perioddown - downloaded bytes this periodpublic void setStorage(Storage stg)
public void setUploaded(long up)
public void setUploaders(int upl,
int inter)upl - whether interested or notinter - interested onlypublic void setWantedPieces()
public boolean shouldRequest(Peer peer, int size)
shouldRequest in interface BandwidthListenerpeer - the peersize - the number of bytes to requestpublic boolean shouldSend(int size)
shouldSend in interface BandwidthListenersize - the number of bytes to sendvoid unchokePeer()
public void updatePiecePriorities()
public void uploaded(int size)
uploaded in interface BandwidthListenersize - the number of bytes sent