java.lang.Object
org.klomp.snark.PeerCoordinator
- All Implemented Interfaces:
BandwidthListener, PeerListener
Coordinates peer activities for a single torrent including upload/download management, peer selection, piece distribution, and bandwidth allocation.
This class manages the core BitTorrent coordination logic:
- Managing connected peers and their states
- Choking/unchoking logic for upload slots
- Piece selection and rarest-first distribution
- Request queue management and pipeline control
- Bandwidth distribution among peers
- Peer Exchange (PEX) for peer discovery
- DHT integration for trackerless operation
- Tracker announcements and response processing
Thread safety: This class uses extensive synchronization for thread-safe peer management. External access to some fields is documented where permitted.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classRun the PeerCheckerTask via the SimpleTimer2 executors.private classRerequest after unthrottled.private static classA stalled piece and the snapshot of its requesters, taken under the wantedPieces lock.Field Summary
Modifier and TypeFieldDescriptionprivate final AtomicLongWhen torrent comments were last requested.private final AtomicIntegerPeers that did not ask for comments.private final LogLogger for the peer coordinator.private final RandomSourceRandom source for peer and piece selection.private final I2PSnarkUtilThe plugin's shared utilities.Hostname to expire time.private final BandwidthListenerListener for bandwidth events, may be null.(package private) static final longHow often to recompute upload slots and UI download speeds.private static final longDelay before the first comment request.private static final longInterval between comment requests.private final AtomicLongBytes downloaded from peers.private final long[]Download totals at the rate stat boundaries.private static final intThis should be somewhat less than the max conns per torrent, but not too much less, so a torrent doesn't get stuck near the end.private booleanTrue once the coordinator has halted.private final byte[]Our 20-byte peer id.private final byte[]The torrent's info hash.private final AtomicIntegerExternal use byPeerCheckerTaskonly.private final AtomicIntegerApproximation of the number of current uploaders (unchoked peers), that are interested.private booleanTrue while a re-request is scheduled.private final CoordinatorListenerListener for progress events.private final MagnetStateMagnet fetch state, null for a normal torrent.private static final intNon-requesting peers that trigger a request.static final longInactivity timeout before disconnecting idle peers.private static final intMax number of peers to get a piece from when in end game.static final longInactivity timeout before disconnecting idle seeds.private static final intMax distinct swarm peers remembered per torrent.(package private) static final intMaximum peers we upload to at once.(package private) MetaInfoWill be null when in magnet mode.Piece ids currently in partialPieces, for O(1) membership checks.private final List<PartialPiece> Pieces received but not yet complete.private intEstimate of the peers, without requiring any synchronization.Synchronize on this when changing peers or downloaders.Peers we heard about via PEX.(package private) static final longInactivity timeout before re-queuing a requested piece that is receiving no data.(package private) static final intNumber of samples in the upload/download rate windows.private final ObjectLock for the re-request state.private final SimpleTimer2.TimedEventTimer re-requesting peers from the tracker.private final SnarkThe download we coordinate peers for.(package private) StorageWill be null when in magnet mode.private static final longHow long a remembered swarm peer stays valid without resurfacing.Distinct swarm peers, keyed by destination hash, value is the last-seen wall time.private final PeerCoordinator.CheckEventTimer to handle all periodical tasks.private final AtomicLongBytes uploaded to peers.private final long[]Upload totals at the rate stat boundaries.private final AtomicIntegerApproximation of the number of current uploaders (unchoked peers), whether interested or not.private longThe total number of bytes in wantedPieces, or -1 if not yet known.private booleanWhether wantedPieces needs resorting (rarest-first).Index of wantedPieces by piece id, for O(1) lookups.The wanted pieces.private booleanWhether the last tracker request was allowed.private static final longHow long a bad web peer is banned.Constructor Summary
ConstructorsConstructorDescriptionPeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage, CoordinatorListener listener, Snark torrent, BandwidthListener bwl) Create a peer coordinator for the torrent.Method Summary
Modifier and TypeMethodDescriptionvoidaddInterestedAndChoking(int toAdd) Shift the interested-and-choking count by a delta, as the checker drops peers without a full recount.booleanAdd peer (inbound or outbound).intReturn number of allowed uploaders for this torrent.voidBan the given hash.voidbanWebPeer(String host, boolean isPermanent) Ban a web peer for this torrent, for while or permanently.(package private) voidcheckStalledPieces(long now) Re-queues any requested pieces that have received no data for PIECE_STALL_TIMEOUT, so they can be requested from other peers.booleanReturns whether the torrent is complete.voidCalled when a peer connection is established.voiddecrementUploaders(boolean isInterested) Decrement the uploaders and (if set) the interestedUploaders counts.voiddisconnected(Peer peer) Called when a peer disconnects.voiddownloaded(int size) Called when a peer has downloaded some bytes of a piece.private voidexpireStalledPiece(Piece p, Set<PeerID> requesters) Cancels the outstanding requests for a stalled piece and returns its partial data to the partial piece list, so the piece can be re-requested from other peers.longReturns the rate in Bps over last complete CHECK_PERIOD seconds.longCurrent limit in Bps.longReturns the total number of downloaded bytes of all peers.longReturns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds.byte[]getID()Returns our peer ID.byte[]The info hash for this torrent.intThe current value.intUploaders, interested only.longgetLeft()Bytes not yet in storage.private intFormerly used to reduce max if huge pieces to keep from ooming when leeching but now we don't.Returns the metainfo for this torrent.getName()Returns the torrent name.longBytes still wanted.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.getPartialPiece(Peer peer, BitField havePieces) Return partial piece to the PeerState if it's still wanted and peer has it.getPartialPiece(Peer peer, BitField havePieces, Set<Integer> allowed) Return partial piece to the PeerState if it's still wanted and peer has it.intReturns the estimated peer count (may be stale).intgetPeers()Returns the current number of connected peers.Called byTrackerClient.(package private) static longgetRate(long[] array) The download or upload rate, per the param.Returns the storage for this torrent.intDistinct swarm peers seen recently (withinSWARM_PEER_TTL) or currently connected, for the torrent view peer count.longCurrent limit in Bps.longReturns the total number of uploaded bytes of all peers.intUploaders whether interested or not Use this for per-torrent limits.longReturns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds.getUtil()Returns the shared torrent utility this coordinator was built with.booleangotBitField(Peer peer, BitField bitfield) Returns true if the given bitfield contains at least one piece we are interested in.voidCalled when a choke message is received.voidgotCommentReq(Peer peer, int num) Called when comments are requested via ut_comment.voidgotComments(Peer peer, List<Comment> comments) Called when comments are received via ut_comment.voidgotExtension(Peer peer, int id, byte[] bs) PeerListener callback.booleanWhether we still want the given piece.voidgotInterest(Peer peer, boolean interest) Called when an interested message is received.voidHandle peers from PEX; a PeerListener callback.booleangotPiece(Peer peer, PartialPiece pp) Returns false if the piece is no good (according to the hash).voidPeerListener callback Tell the DHT to ping it, this will get back the node info.gotRequest(Peer peer, int piece, int off, int len) Returns a byte array containing the requested piece or null of the piece is unknown.voidhalt()Halt this coordinator, disconnecting all peers.booleanhalted()Returns whether this coordinator has been halted.booleanIs the given hash banned?private static booleanWhether the storage error is a genuine filesystem problem that should stop the torrent with an explicit reason.(package private) static booleanChecks if the piece has been requested but has received no data for longer than the timeout.booleanisWebPeerBanned(String host) Is a web peer banned?private voidmarkUnrequested(Peer peer, int piece) Clear the requested flag for a piece.booleanOutbound.booleanInbound.booleanCalled when we are downloading from the peer and may need to ask for a new piece.booleanAre we currently over the limit?booleanIs snark as a whole over its upload limit?booleanoverUpBWLimit(long total) Is a particular peer who has downloaded this many bytes from us in the last CHECK_PERIOD over its limit?private static PeerpeerIDInList(PeerID pid, Collection<Peer> peers) The peer with the given ID, or null.peerList()Returns a snapshot of the connected peers list for web page detailed stats.(package private) voidrecordSwarmPeer(Peer peer) Record a peer surfaced by any source (announce, PEX, DHT, inbound) as a distinct swarm member, keyed by destination hash.private voidremovePartialPiece(int piece) Remove saved state for this piece.private voidremovePeerFromPieces(Peer peer) Called when a peer is removed, to prevent it from being used in rarest-first calculations.voidrestart()Restart after halt.voidsavePartialPieces(Peer peer, List<Request> partials) Save partial pieces on peer disconnection and hopefully restart it later.(package private) voidsendCommentReq(Peer peer) Send a comment request message to the peer, if he supports it.(package private) voidSend a DHT message to the peer, if we both support DHT.(package private) voidSend a PEX message to the peer, if he supports PEX.(package private) static voidsetRate(long val, long[] array) Push a value onto a RATE_DEPTH deep stack.voidsetRateHistory(long up, long down) Push the total uploaded/downloaded onto a RATE_DEPTH deep stack.voidsetStorage(Storage stg) Store the storage after transition out of magnet mode.voidsetUploaded(long up) The initial total of uploaded bytes of all peers, from a saved status.voidsetUploaders(int upl, int inter) Record the uploader and interested-uploader counts.voidRebuild the wanted pieces list from storage.booleanshouldRequest(Peer peer, int size) Should we request this many bytes?booleanshouldSend(int size) Should we send this many bytes? Do NOT calluploadedif this returns true.(package private) void(Optimistically) unchoke.voidMaps file priorities to piece priorities.voiduploaded(int size) BandwidthListener interface method, called when a peer has uploaded some bytes of a piece.private PieceReturns one of pieces in the given BitField that is still wanted or null if none of the given pieces are wanted.private PieceReturns one of the claimed pieces in the given BitField that is still wanted or null if none of the given pieces are wanted.
Field Details
_log
Logger for the peer coordinator.metainfo
MetaInfo metainfoWill be null when in magnet mode.storage
Storage storageWill be null when in magnet mode.snark
The download we coordinate peers for.CHECK_PERIOD
static final long CHECK_PERIODHow often to recompute upload slots and UI download speeds.- See Also:
MAX_UPLOADERS
MAX_INACTIVE
public static final long MAX_INACTIVEInactivity timeout before disconnecting idle peers.- See Also:
MAX_SEED_INACTIVE
public static final long MAX_SEED_INACTIVEInactivity timeout before disconnecting idle seeds.- See Also:
PIECE_STALL_TIMEOUT
static final long PIECE_STALL_TIMEOUTInactivity timeout before re-queuing a requested piece that is receiving no data.- See Also:
uploaders
Approximation of the number of current uploaders (unchoked peers), whether interested or not. Resynced by PeerChecker once in a while.interestedUploaders
Approximation of the number of current uploaders (unchoked peers), that are interested. Resynced by PeerChecker once in a while.interestedAndChoking
External use byPeerCheckerTaskonly.uploaded
Bytes uploaded to peers.downloaded
Bytes downloaded from peers.RATE_DEPTH
static final int RATE_DEPTHNumber of samples in the upload/download rate windows.- See Also:
uploaded_old
private final long[] uploaded_oldUpload totals at the rate stat boundaries.downloaded_old
private final long[] downloaded_oldDownload totals at the rate stat boundaries.peers
pexPeers
MAX_SWARM_PEERS
private static final int MAX_SWARM_PEERSMax distinct swarm peers remembered per torrent.- See Also:
SWARM_PEER_TTL
private static final long SWARM_PEER_TTLHow long a remembered swarm peer stays valid without resurfacing.- See Also:
swarmSeen
peerCount
private volatile int peerCountEstimate of the peers, without requiring any synchronization.timer
Timer to handle all periodical tasks.rerequestTimer
Timer re-requesting peers from the tracker.rerequestLock
Lock for the re-request state.wasRequestAllowed
private boolean wasRequestAllowedWhether the last tracker request was allowed.isRerequestScheduled
private boolean isRerequestScheduledTrue while a re-request is scheduled.id
private final byte[] idOur 20-byte peer id.infohash
private final byte[] infohashThe torrent's info hash.wantedPieces
wantedBytes
private long wantedBytesThe total number of bytes in wantedPieces, or -1 if not yet known. Sync on wantedPieces.partialPieces
Pieces received but not yet complete.partialIds
wantedMap
wantedDirty
private boolean wantedDirtyWhether wantedPieces needs resorting (rarest-first). Sync on wantedPieces.halted
private volatile boolean haltedTrue once the coordinator has halted.magnetState
Magnet fetch state, null for a normal torrent.listener
Listener for progress events.bwListener
Listener for bandwidth events, may be null._util
The plugin's shared utilities._random
Random source for peer and piece selection._commentsLastRequested
When torrent comments were last requested._commentsNotRequested
Peers that did not ask for comments.COMMENT_REQ_INTERVAL
private static final long COMMENT_REQ_INTERVALInterval between comment requests.- See Also:
COMMENT_REQ_DELAY
private static final long COMMENT_REQ_DELAYDelay before the first comment request.- See Also:
MAX_COMMENT_NOT_REQ
private static final int MAX_COMMENT_NOT_REQNon-requesting peers that trigger a request.- See Also:
_webPeerBans
WEBPEER_BAN_TIME
private static final long WEBPEER_BAN_TIMEHow long a bad web peer is banned.- See Also:
END_GAME_THRESHOLD
private static final int END_GAME_THRESHOLDThis should be somewhat less than the max conns per torrent, but not too much less, so a torrent doesn't get stuck near the end. https://en.wikipedia.org/wiki/Glossary_of_BitTorrent_terms#Endgame_/_Endgame_mode- See Also:
MAX_PARALLEL_REQUESTS
private static final int MAX_PARALLEL_REQUESTSMax number of peers to get a piece from when in end game.- See Also:
Constructor Details
PeerCoordinator
public PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage, CoordinatorListener listener, Snark torrent, BandwidthListener bwl) Create a peer coordinator for the torrent.- Parameters:
util- the context wrapper supplying the I2P app context, random source and clocksid- the 20 byte torrent hash the peers are matched againstinfohash- the torrent hash used for magnet and peer exchange lookupsmetainfo- null if in magnet modestorage- null if in magnet modelistener- notified as peers are added, dropped and completedtorrent- the torrent this coordinator drivesbwl- receives the byte totals reported by every peer connection
Method Details
setWantedPieces
public void setWantedPieces()Rebuild the wanted pieces list from storage. Sets wantedBytes too. Only called externally from Storage after the double-check fails.getStorage
Returns the storage for this torrent.- Returns:
- the storage, or null if in magnet mode
peerList
recordSwarmPeer
Record a peer surfaced by any source (announce, PEX, DHT, inbound) as a distinct swarm member, keyed by destination hash. Web seeds are not swarm members. Bounded; refreshes the last-seen time.- Parameters:
peer- the peer, non-null
getSwarmPeerCount
public int getSwarmPeerCount()Distinct swarm peers seen recently (withinSWARM_PEER_TTL) or currently connected, for the torrent view peer count. Prunes stale entries lazily.- Returns:
- the count, 0 if none
getID
public byte[] getID()Returns our peer ID.- Returns:
- the peer ID bytes
getName
Returns the torrent name.- Returns:
- the torrent's display name, taken from the torrent file unless the completion listener renamed it
completed
public boolean completed()Returns whether the torrent is complete.- Returns:
- true if all pieces are downloaded
getPeerCount
public int getPeerCount()Returns the estimated peer count (may be stale).- Returns:
- estimated peer count
getPeers
public int getPeers()Returns the current number of connected peers.- Returns:
- the number of currently connected peers
getLeft
public long getLeft()Bytes not yet in storage. Does NOT account for skipped files. Returns how many bytes are still needed to get the complete torrent.- Returns:
- -1 if in magnet mode
getNeededLength
public long getNeededLength()Bytes still wanted. DOES account for skipped files.- Returns:
- exact value. or -1 if no storage yet.
getUploaded
public long getUploaded()Returns the total number of uploaded bytes of all peers.- Returns:
- total uploaded bytes
setUploaded
public void setUploaded(long up) The initial total of uploaded bytes of all peers, from a saved status.- Parameters:
up- the byte count to seed the uploaded total with
getDownloaded
public long getDownloaded()Returns the total number of downloaded bytes of all peers.- Returns:
- total downloaded bytes
uploaded
public void uploaded(int size) BandwidthListener interface method, called when a peer has uploaded some bytes of a piece.- Specified by:
uploadedin interfaceBandwidthListener- Parameters:
size- the number of bytes sent
downloaded
public void downloaded(int size) Called when a peer has downloaded some bytes of a piece.- Specified by:
downloadedin interfaceBandwidthListener- Parameters:
size- the number of bytes received
shouldSend
public boolean shouldSend(int size) Should we send this many bytes? Do NOT calluploadedif this returns true.- Specified by:
shouldSendin interfaceBandwidthListener- Parameters:
size- the number of bytes to send- Returns:
- whether the bandwidth allowance permits sending that many bytes
shouldRequest
Should we request this many bytes?- Specified by:
shouldRequestin interfaceBandwidthListener- Parameters:
peer- the peer the bytes would be requested fromsize- the number of bytes to request- Returns:
- whether the bandwidth allowance permits requesting that many bytes
setRateHistory
public void setRateHistory(long up, long down) Push the total uploaded/downloaded onto a RATE_DEPTH deep stack.- Parameters:
up- uploaded bytes this perioddown- downloaded bytes this period
setRate
static void setRate(long val, long[] array) Push a value onto a RATE_DEPTH deep stack.- Parameters:
val- the value to pusharray- the rate array to update
getDownloadRate
public long getDownloadRate()Returns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds.- Specified by:
getDownloadRatein interfaceBandwidthListener- Returns:
- the average download rate in Bps
getUploadRate
public long getUploadRate()Returns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds.- Specified by:
getUploadRatein interfaceBandwidthListener- Returns:
- the average upload rate in Bps
getCurrentUploadRate
public long getCurrentUploadRate()Returns the rate in Bps over last complete CHECK_PERIOD seconds.- Returns:
- the upload rate in bytes per second over the most recent complete CHECK_PERIOD, or 0 when halted or before the first sample is recorded
getRate
static long getRate(long[] array) The download or upload rate, per the param.- Parameters:
array- rolling byte-count samples, most recent entry first, ending at a negative value- Returns:
- the weighted average rate in bytes per second, weighting each sample more heavily the more recent it is, or 0 when the ring holds no complete sample
getUpBWLimit
public long getUpBWLimit()Current limit in Bps.- Specified by:
getUpBWLimitin interfaceBandwidthListener- Returns:
- the up b w limit
overUpBWLimit
public boolean overUpBWLimit()Is snark as a whole over its upload limit?- Specified by:
overUpBWLimitin interfaceBandwidthListener- Returns:
- true if over limit
overUpBWLimit
public boolean overUpBWLimit(long total) Is a particular peer who has downloaded this many bytes from us in the last CHECK_PERIOD over its limit?- Parameters:
total- bytes uploaded to the peer in the last CHECK_PERIOD- Returns:
- true if over limit
getDownBWLimit
public long getDownBWLimit()Current limit in Bps.- Specified by:
getDownBWLimitin interfaceBandwidthListener- Returns:
- the down b w limit
overDownBWLimit
public boolean overDownBWLimit()Are we currently over the limit?- Specified by:
overDownBWLimitin interfaceBandwidthListener- Returns:
- true if over the download limit, false otherwise
getMetaInfo
Returns the metainfo for this torrent.- Returns:
- the metainfo, or null if in magnet mode
getInfoHash
public byte[] getInfoHash()The info hash for this torrent.- Returns:
- the torrent hash used for magnet and peer exchange lookups
needPeers
public boolean needPeers()Inbound. Not halted, peers < max.- Returns:
- true while the coordinator is running and holds fewer than the configured maximum peer connections, so another inbound may be accepted
needOutboundPeers
public boolean needOutboundPeers()Outbound. Not halted, peers < max, and need pieces.- Returns:
- true while the coordinator is running, holds at least two connections below the maximum so new peers can displace stale ones, and either pieces are still wanted or a comment request is due
getMaxConnections
private int getMaxConnections()Formerly used to reduce max if huge pieces to keep from ooming when leeching but now we don't.- Returns:
- usually I2PSnarkUtil.MAX_CONNECTIONS
halted
public boolean halted()Returns whether this coordinator has been halted.- Returns:
- true if halted
halt
public void halt()Halt this coordinator, disconnecting all peers.restart
public void restart()Restart after halt.connected
Called when a peer connection is established.- Specified by:
connectedin interfacePeerListener- Parameters:
peer- the newly connected peer
peerIDInList
The peer with the given ID, or null.- Parameters:
pid- the peer id to look forpeers- the collection of peers to scan- Returns:
- peer if peer id is in the collection, else null
addPeer
Add peer (inbound or outbound).- Parameters:
peer- the connection to take over; disconnected rather than tracked if halted or full- Returns:
- true if actual attempt to add peer occurs
unchokePeer
void unchokePeer()(Optimistically) unchoke. Must be called with peers synchronized.gotHave
Whether we still want the given piece.- Specified by:
gotHavein interfacePeerListener- Parameters:
peer- the Peer that got the message.piece- the piece number that the per just got.- Returns:
- true if we still want the given piece
gotBitField
Returns true if the given bitfield contains at least one piece we are interested in.- Specified by:
gotBitFieldin interfacePeerListener- Parameters:
peer- the Peer that got the message.bitfield- a BitField containing the pieces that the other side has.- Returns:
- true when the BitField contains pieces we want, false if the piece is already known.
wantPiece
Returns one of pieces in the given BitField that is still wanted or null if none of the given pieces are wanted.- Parameters:
peer- the peer to request the piece fromhavePieces- the pieces the peer claims to haverecord- if true, actually record in our data structures that we gave the request to this peer. If false, do not update the data structures.- Returns:
- the piece to request, or null if none of the peer's pieces are wanted
wantPiece
Returns one of the claimed pieces in the given BitField that is still wanted or null if none of the given pieces are wanted.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.
- Parameters:
peer- the peer to request the piece fromhavePieces- the pieces the peer claims to haverecord- if true, actually record in our data structures that we gave the request to this peer. If false, do not update the data structures.allowed- the pieces servable while choked, or null for no restriction- Returns:
- the piece to request, or null if none of the peer's allowed pieces are wanted
updatePiecePriorities
public void updatePiecePriorities()Maps file priorities to piece priorities. Call after updating file prioritiesStorage.setPriority(int, int).gotRequest
Returns a byte array containing the requested piece or null of the piece is unknown.- Specified by:
gotRequestin interfacePeerListener- Parameters:
peer- the Peer that wants the piece.piece- the piece number requested.off- byte offset into the piece.len- length of the chunk requested.- Returns:
- bytes or null for errors such as not having the piece yet
- Throws:
RuntimeException- on IOE getting the data
isFatalStorageError
Whether the storage error is a genuine filesystem problem that should stop the torrent with an explicit reason. Genuine means no space, bad permissions, read-only filesystem, or hardware I/O error; transient or stale-handle conditions (EBADF, fd exhaustion, vanished file) can be retried.- Parameters:
ioe- the storage error- Returns:
- true if the torrent should stop
gotPiece
Returns false if the piece is no good (according to the hash). In that case the peer that supplied the piece should probably be blacklisted.- Specified by:
gotPiecein interfacePeerListener- Parameters:
peer- the Peer that got the piece.pp- the piece received.- Returns:
- true when the bytes represent the piece, false otherwise.
- Throws:
RuntimeException- on a genuine storage error saving the piece
gotChoke
Called when a choke message is received. This does nothing but logging.- Specified by:
gotChokein interfacePeerListener- Parameters:
peer- the peer that sent the choke or unchokechoke- true for choke, false for unchoke
gotInterest
Called when an interested message is received.- Specified by:
gotInterestin interfacePeerListener- Parameters:
peer- the peer that sent the interested or uninterested messageinterest- true for interested, false for uninterested
disconnected
Called when a peer disconnects.- Specified by:
disconnectedin interfacePeerListener- Parameters:
peer- the disconnected peer
removePeerFromPieces
Called when a peer is removed, to prevent it from being used in rarest-first calculations.- Parameters:
peer- the peer being removed from all piece records
savePartialPieces
Save partial pieces on peer disconnection and hopefully restart it later. Replace a partial piece in the List if the new one is bigger. Storage method is private so we can expand to save multiple partials if we wish.Also mark the piece unrequested if this peer was the only one.
- Specified by:
savePartialPiecesin interfacePeerListener- Parameters:
peer- partials, must include the zero-offset (empty) ones too. No dup pieces. len field in Requests is ignored.partials- the still-outstanding piece requests whose partial data can be salvaged
getPartialPiece
Return partial piece to the PeerState if it's still wanted and peer has it.- Specified by:
getPartialPiecein interfacePeerListener- Parameters:
peer- the peer that just connectedhavePieces- pieces the peer has, the rv will be one of these- Returns:
- PartialPiece or null
getPartialPiece
Return partial piece to the PeerState if it's still wanted and peer has it.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.
- Specified by:
getPartialPiecein interfacePeerListener- Parameters:
peer- the peer that just connectedhavePieces- pieces the peer has, the rv will be one of theseallowed- the pieces servable while choked, or null for no restriction- Returns:
- PartialPiece or null
getPartialPiece
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. Used for BEP 6 suggest handling.- Specified by:
getPartialPiecein interfacePeerListener- Parameters:
peer- the peer that suggested the piecepiece- the suggested piece number- Returns:
- a new PartialPiece to request, or null
needPiece
Called when we are downloading from the peer and may need to ask for a new piece. Returns true ifwantPiece(Peer, BitField, boolean)or getPartialPiece() would return a piece.- Specified by:
needPiecein interfacePeerListener- Parameters:
peer- the Peer that will be asked to provide the piece.havePieces- a BitField containing the pieces that the other side has.- Returns:
- if we want any of what the peer has
removePartialPiece
private void removePartialPiece(int piece) Remove saved state for this piece. Unless we are in the end game there shouldnt be anything in there. Do not call with wantedPieces lock held (deadlock).- Parameters:
piece- the piece number whose saved partial data is dropped
markUnrequested
Clear the requested flag for a piece.- Parameters:
peer- the peer the piece was requested frompiece- the piece number to clear the flag for
isStalled
Checks if the piece has been requested but has received no data for longer than the timeout.- Parameters:
p- the piece to checknow- the current time in millisecondstimeout- the stall timeout in milliseconds- Returns:
- true if the piece is requested and stale
checkStalledPieces
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. Called periodically by PeerCheckerTask.- Parameters:
now- the current time in milliseconds
expireStalledPiece
Cancels the outstanding requests for a stalled piece and returns its partial data to the partial piece list, so the piece can be re-requested from other peers.- Parameters:
p- the stalled piecerequesters- snapshot of the peers requesting it, taken under the wantedPieces lock
gotExtension
PeerListener callback.- Specified by:
gotExtensionin interfacePeerListener- Parameters:
peer- the Peer that got the message.id- the message IDbs- the message payload
sendPeers
Send a PEX message to the peer, if he supports PEX. This sends everybody we have connected to since the last time we sent PEX to him.- Parameters:
peer- the connection to advertise peers to; needs the PEX extension, non-private torrent
sendDHT
Send a DHT message to the peer, if we both support DHT.- Parameters:
peer- the peer to send to
sendCommentReq
Send a comment request message to the peer, if he supports it.- Parameters:
peer- the connection to ask for comments; needs the comment extension advertised
setStorage
Store the storage after transition out of magnet mode. Snark calls this after we call gotMetaInfo().- Parameters:
stg- storage built from the metainfo that just arrived; wanted pieces recomputed
gotPort
PeerListener callback Tell the DHT to ping it, this will get back the node info.- Specified by:
gotPortin interfacePeerListener- Parameters:
peer- the Peer that got the message.port- the query portrport- must be port + 1
gotPeers
Handle peers from PEX; a PeerListener callback.- Specified by:
gotPeersin interfacePeerListener- Parameters:
peer- the Peer that got the message.peers- the peer IDs (dest hashes)
gotCommentReq
Called when comments are requested via ut_comment.- Specified by:
gotCommentReqin interfacePeerListener- Parameters:
peer- the Peer that got the message.num- the number of comments asked for
gotComments
Called when comments are received via ut_comment.- Specified by:
gotCommentsin interfacePeerListener- Parameters:
peer- the Peer that got the message.comments- non-null
getPEXPeers
Called byTrackerClient.- Returns:
- the Set itself, modifiable, not a copy, caller should clear()
allowedUploaders
public int allowedUploaders()Return number of allowed uploaders for this torrent. Check with Snark to see if we are over the total upload limit.- Returns:
- the current uploader count plus one, capped at MAX_UPLOADERS, or one less than the current count while Snark reports the total upload limit exceeded
getUploaders
public int getUploaders()Uploaders whether interested or not Use this for per-torrent limits.- Returns:
- the uploader count, capped at the connected peer count
getInterestedUploaders
public int getInterestedUploaders()Uploaders, interested only. Use this to calculate the global total, so that unchoked but uninterested peers don't count against the global limit.- Returns:
- the interested-uploader count, capped at the connected peer count
setUploaders
public void setUploaders(int upl, int inter) Record the uploader and interested-uploader counts.- Parameters:
upl- whether interested or notinter- the interested-only subset of that count, also capped at the maximum
decrementUploaders
public void decrementUploaders(boolean isInterested) Decrement the uploaders and (if set) the interestedUploaders counts.- Parameters:
isInterested- true to also decrement the interested uploader count
getInterestedAndChoking
public int getInterestedAndChoking()The current value.- Returns:
- the number of peers that are interested but choked
addInterestedAndChoking
public void addInterestedAndChoking(int toAdd) Shift the interested-and-choking count by a delta, as the checker drops peers without a full recount.- Parameters:
toAdd- the number of peers just removed from the interested set
getUtil
Returns the shared torrent utility this coordinator was built with.- Specified by:
getUtilin interfacePeerListener- Returns:
- the shared I2PSnarkUtil, common to every torrent in this router
banWebPeer
Ban a web peer for this torrent, for while or permanently.- Parameters:
host- the hostname to banisPermanent- true to ban until restart, false to ban forWEBPEER_BAN_TIME
isWebPeerBanned
Is a web peer banned?- Parameters:
host- the host name to look up in the web peer ban map- Returns:
- whether web peer banned
isBanned
Is the given hash banned?- Specified by:
isBannedin interfacePeerListener- Parameters:
h- the torrent's info hash, checked against the ban list and bad-tracker count- Returns:
- true if banned
ban
Ban the given hash.- Specified by:
banin interfacePeerListener- Parameters:
h- the torrent's info hash to add to the ban list