java.lang.Object
org.klomp.snark.PeerCoordinator
All Implemented Interfaces:
BandwidthListener, PeerListener

class PeerCoordinatorextends Object implements PeerListener, BandwidthListener
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.

See Also:
  • Field Details

    • _log

      private final Log _log
      Logger for the peer coordinator.
    • metainfo

      MetaInfo metainfo
      Will be null when in magnet mode.
    • storage

      Storage storage
      Will be null when in magnet mode.
    • snark

      private final Snark snark
      The download we coordinate peers for.
    • CHECK_PERIOD

      static final long CHECK_PERIOD
      How often to recompute upload slots and UI download speeds.
      See Also:
    • MAX_UPLOADERS

      static final int MAX_UPLOADERS
      Maximum peers we upload to at once.
      See Also:
    • MAX_INACTIVE

      public static final long MAX_INACTIVE
      Inactivity timeout before disconnecting idle peers.
      See Also:
    • MAX_SEED_INACTIVE

      public static final long MAX_SEED_INACTIVE
      Inactivity timeout before disconnecting idle seeds.
      See Also:
    • PIECE_STALL_TIMEOUT

      static final long PIECE_STALL_TIMEOUT
      Inactivity timeout before re-queuing a requested piece that is receiving no data.
      See Also:
    • uploaders

      private final AtomicInteger uploaders
      Approximation of the number of current uploaders (unchoked peers), whether interested or not. Resynced by PeerChecker once in a while.
    • interestedUploaders

      private final AtomicInteger interestedUploaders
      Approximation of the number of current uploaders (unchoked peers), that are interested. Resynced by PeerChecker once in a while.
    • interestedAndChoking

      private final AtomicInteger interestedAndChoking
      External use by PeerCheckerTask only.
    • uploaded

      private final AtomicLong uploaded
      Bytes uploaded to peers.
    • downloaded

      private final AtomicLong downloaded
      Bytes downloaded from peers.
    • RATE_DEPTH

      static final int RATE_DEPTH
      Number of samples in the upload/download rate windows.
      See Also:
    • uploaded_old

      private final long[] uploaded_old
      Upload totals at the rate stat boundaries.
    • downloaded_old

      private final long[] downloaded_old
      Download totals at the rate stat boundaries.
    • peers

      final Deque<Peer> peers
      Synchronize on this when changing peers or downloaders. This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking.
    • pexPeers

      private final Set<PeerID> pexPeers
      Peers we heard about via PEX.
    • MAX_SWARM_PEERS

      private static final int MAX_SWARM_PEERS
      Max distinct swarm peers remembered per torrent.
      See Also:
    • SWARM_PEER_TTL

      private static final long SWARM_PEER_TTL
      How long a remembered swarm peer stays valid without resurfacing.
      See Also:
    • swarmSeen

      private final Map<Hash,Long> swarmSeen
      Distinct swarm peers, keyed by destination hash, value is the last-seen wall time.
    • peerCount

      private volatile int peerCount
      Estimate of the peers, without requiring any synchronization.
    • timer

      private final PeerCoordinator.CheckEvent timer
      Timer to handle all periodical tasks.
    • rerequestTimer

      private final SimpleTimer2.TimedEvent rerequestTimer
      Timer re-requesting peers from the tracker.
    • rerequestLock

      private final Object rerequestLock
      Lock for the re-request state.
    • wasRequestAllowed

      private boolean wasRequestAllowed
      Whether the last tracker request was allowed.
    • isRerequestScheduled

      private boolean isRerequestScheduled
      True while a re-request is scheduled.
    • id

      private final byte[] id
      Our 20-byte peer id.
    • infohash

      private final byte[] infohash
      The torrent's info hash.
    • wantedPieces

      private final List<Piece> wantedPieces
      The wanted pieces. We could use a TreeSet but we'd have to clear and re-add everything when priorities change.
    • wantedBytes

      private long wantedBytes
      The total number of bytes in wantedPieces, or -1 if not yet known. Sync on wantedPieces.
    • partialPieces

      private final List<PartialPiece> partialPieces
      Pieces received but not yet complete.
    • partialIds

      private final Set<Integer> partialIds
      Piece ids currently in partialPieces, for O(1) membership checks. Sync on wantedPieces.
    • wantedMap

      private final Map<Integer,Piece> wantedMap
      Index of wantedPieces by piece id, for O(1) lookups. Sync on wantedPieces.
    • wantedDirty

      private boolean wantedDirty
      Whether wantedPieces needs resorting (rarest-first). Sync on wantedPieces.
    • halted

      private volatile boolean halted
      True once the coordinator has halted.
    • magnetState

      private final MagnetState magnetState
      Magnet fetch state, null for a normal torrent.
    • listener

      private final CoordinatorListener listener
      Listener for progress events.
    • bwListener

      private final BandwidthListener bwListener
      Listener for bandwidth events, may be null.
    • _util

      private final I2PSnarkUtil _util
      The plugin's shared utilities.
    • _random

      private final RandomSource _random
      Random source for peer and piece selection.
    • _commentsLastRequested

      private final AtomicLong _commentsLastRequested
      When torrent comments were last requested.
    • _commentsNotRequested

      private final AtomicInteger _commentsNotRequested
      Peers that did not ask for comments.
    • COMMENT_REQ_INTERVAL

      private static final long COMMENT_REQ_INTERVAL
      Interval between comment requests.
      See Also:
    • COMMENT_REQ_DELAY

      private static final long COMMENT_REQ_DELAY
      Delay before the first comment request.
      See Also:
    • MAX_COMMENT_NOT_REQ

      private static final int MAX_COMMENT_NOT_REQ
      Non-requesting peers that trigger a request.
      See Also:
    • _webPeerBans

      private Map<String,Long> _webPeerBans
      Hostname to expire time. Sync on this.
    • WEBPEER_BAN_TIME

      private static final long WEBPEER_BAN_TIME
      How long a bad web peer is banned.
      See Also:
    • END_GAME_THRESHOLD

      private static final int END_GAME_THRESHOLD
      This 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_REQUESTS
      Max 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 clocks
      id - the 20 byte torrent hash the peers are matched against
      infohash - the torrent hash used for magnet and peer exchange lookups
      metainfo - null if in magnet mode
      storage - null if in magnet mode
      listener - notified as peers are added, dropped and completed
      torrent - the torrent this coordinator drives
      bwl - 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

      public Storage getStorage()
      Returns the storage for this torrent.
      Returns:
      the storage, or null if in magnet mode
    • peerList

      public List<Peer> peerList()
      Returns a snapshot of the connected peers list for web page detailed stats.
      Returns:
      list of connected peers
    • recordSwarmPeer

      void recordSwarmPeer(Peer peer)
      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 (within SWARM_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

      public String 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:
      uploaded in interface BandwidthListener
      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:
      downloaded in interface BandwidthListener
      Parameters:
      size - the number of bytes received
    • shouldSend

      public boolean shouldSend(int size)
      Should we send this many bytes? Do NOT call uploaded if this returns true.
      Specified by:
      shouldSend in interface BandwidthListener
      Parameters:
      size - the number of bytes to send
      Returns:
      whether the bandwidth allowance permits sending that many bytes
    • shouldRequest

      public boolean shouldRequest(Peer peer, int size)
      Should we request this many bytes?
      Specified by:
      shouldRequest in interface BandwidthListener
      Parameters:
      peer - the peer the bytes would be requested from
      size - 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 period
      down - 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 push
      array - the rate array to update
    • getDownloadRate

      public long getDownloadRate()
      Returns the average rate in Bps over last RATE_DEPTH * CHECK_PERIOD seconds.
      Specified by:
      getDownloadRate in interface BandwidthListener
      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:
      getUploadRate in interface BandwidthListener
      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:
      getUpBWLimit in interface BandwidthListener
      Returns:
      the up b w limit
    • overUpBWLimit

      public boolean overUpBWLimit()
      Is snark as a whole over its upload limit?
      Specified by:
      overUpBWLimit in interface BandwidthListener
      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:
      getDownBWLimit in interface BandwidthListener
      Returns:
      the down b w limit
    • overDownBWLimit

      public boolean overDownBWLimit()
      Are we currently over the limit?
      Specified by:
      overDownBWLimit in interface BandwidthListener
      Returns:
      true if over the download limit, false otherwise
    • getMetaInfo

      public MetaInfo 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

      public void connected(Peer peer)
      Called when a peer connection is established.
      Specified by:
      connected in interface PeerListener
      Parameters:
      peer - the newly connected peer
    • peerIDInList

      private static Peer peerIDInList(PeerID pid, Collection<Peer> peers)
      The peer with the given ID, or null.
      Parameters:
      pid - the peer id to look for
      peers - the collection of peers to scan
      Returns:
      peer if peer id is in the collection, else null
    • addPeer

      public boolean addPeer(Peer peer)
      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

      public boolean gotHave(Peer peer, int piece)
      Whether we still want the given piece.
      Specified by:
      gotHave in interface PeerListener
      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

      public boolean gotBitField(Peer peer, BitField bitfield)
      Returns true if the given bitfield contains at least one piece we are interested in.
      Specified by:
      gotBitField in interface PeerListener
      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

      private Piece wantPiece(Peer peer, BitField havePieces, boolean record)
      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 from
      havePieces - the pieces the peer claims to have
      record - 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

      private Piece wantPiece(Peer peer, BitField havePieces, boolean record, Set<Integer> allowed)
      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 from
      havePieces - the pieces the peer claims to have
      record - 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 priorities Storage.setPriority(int, int).
    • gotRequest

      public 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.
      Specified by:
      gotRequest in interface PeerListener
      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

      private static boolean isFatalStorageError(IOException ioe)
      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

      public boolean gotPiece(Peer peer, PartialPiece pp)
      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:
      gotPiece in interface PeerListener
      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

      public void gotChoke(Peer peer, boolean choke)
      Called when a choke message is received. This does nothing but logging.
      Specified by:
      gotChoke in interface PeerListener
      Parameters:
      peer - the peer that sent the choke or unchoke
      choke - true for choke, false for unchoke
    • gotInterest

      public void gotInterest(Peer peer, boolean interest)
      Called when an interested message is received.
      Specified by:
      gotInterest in interface PeerListener
      Parameters:
      peer - the peer that sent the interested or uninterested message
      interest - true for interested, false for uninterested
    • disconnected

      public void disconnected(Peer peer)
      Called when a peer disconnects.
      Specified by:
      disconnected in interface PeerListener
      Parameters:
      peer - the disconnected peer
    • removePeerFromPieces

      private void removePeerFromPieces(Peer peer)
      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

      public void savePartialPieces(Peer peer, List<Request> partials)
      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:
      savePartialPieces in interface PeerListener
      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

      public PartialPiece getPartialPiece(Peer peer, BitField havePieces)
      Return partial piece to the PeerState if it's still wanted and peer has it.
      Specified by:
      getPartialPiece in interface PeerListener
      Parameters:
      peer - the peer that just connected
      havePieces - pieces the peer has, the rv will be one of these
      Returns:
      PartialPiece or null
    • getPartialPiece

      public PartialPiece getPartialPiece(Peer peer, BitField havePieces, Set<Integer> allowed)
      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:
      getPartialPiece in interface PeerListener
      Parameters:
      peer - the peer that just connected
      havePieces - pieces the peer has, the rv will be one of these
      allowed - the pieces servable while choked, or null for no restriction
      Returns:
      PartialPiece or null
    • getPartialPiece

      public 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. Used for BEP 6 suggest handling.
      Specified by:
      getPartialPiece in interface PeerListener
      Parameters:
      peer - the peer that suggested the piece
      piece - the suggested piece number
      Returns:
      a new PartialPiece to request, or null
    • needPiece

      public boolean needPiece(Peer peer, BitField havePieces)
      Called when we are downloading from the peer and may need to ask for a new piece. Returns true if wantPiece(Peer, BitField, boolean) or getPartialPiece() would return a piece.
      Specified by:
      needPiece in interface PeerListener
      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

      private void markUnrequested(Peer peer, int piece)
      Clear the requested flag for a piece.
      Parameters:
      peer - the peer the piece was requested from
      piece - the piece number to clear the flag for
    • isStalled

      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.
      Parameters:
      p - the piece to check
      now - the current time in milliseconds
      timeout - 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

      private void expireStalledPiece(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.
      Parameters:
      p - the stalled piece
      requesters - snapshot of the peers requesting it, taken under the wantedPieces lock
    • gotExtension

      public void gotExtension(Peer peer, int id, byte[] bs)
      PeerListener callback.
      Specified by:
      gotExtension in interface PeerListener
      Parameters:
      peer - the Peer that got the message.
      id - the message ID
      bs - the message payload
    • sendPeers

      void sendPeers(Peer peer)
      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

      void sendDHT(Peer peer)
      Send a DHT message to the peer, if we both support DHT.
      Parameters:
      peer - the peer to send to
    • sendCommentReq

      void sendCommentReq(Peer peer)
      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

      public void setStorage(Storage stg)
      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

      public void gotPort(Peer peer, int port, int rport)
      PeerListener callback Tell the DHT to ping it, this will get back the node info.
      Specified by:
      gotPort in interface PeerListener
      Parameters:
      peer - the Peer that got the message.
      port - the query port
      rport - must be port + 1
    • gotPeers

      public void gotPeers(Peer peer, List<PeerID> peers)
      Handle peers from PEX; a PeerListener callback.
      Specified by:
      gotPeers in interface PeerListener
      Parameters:
      peer - the Peer that got the message.
      peers - the peer IDs (dest hashes)
    • gotCommentReq

      public void gotCommentReq(Peer peer, int num)
      Called when comments are requested via ut_comment.
      Specified by:
      gotCommentReq in interface PeerListener
      Parameters:
      peer - the Peer that got the message.
      num - the number of comments asked for
    • gotComments

      public void gotComments(Peer peer, List<Comment> comments)
      Called when comments are received via ut_comment.
      Specified by:
      gotComments in interface PeerListener
      Parameters:
      peer - the Peer that got the message.
      comments - non-null
    • getPEXPeers

      Set<PeerID> getPEXPeers()
      Called by TrackerClient.
      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 not
      inter - 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

      public I2PSnarkUtil getUtil()
      Returns the shared torrent utility this coordinator was built with.
      Specified by:
      getUtil in interface PeerListener
      Returns:
      the shared I2PSnarkUtil, common to every torrent in this router
    • banWebPeer

      public void banWebPeer(String host, boolean isPermanent)
      Ban a web peer for this torrent, for while or permanently.
      Parameters:
      host - the hostname to ban
      isPermanent - true to ban until restart, false to ban for WEBPEER_BAN_TIME
    • isWebPeerBanned

      public boolean isWebPeerBanned(String host)
      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

      public boolean isBanned(Hash h)
      Is the given hash banned?
      Specified by:
      isBanned in interface PeerListener
      Parameters:
      h - the torrent's info hash, checked against the ban list and bad-tracker count
      Returns:
      true if banned
    • ban

      public void ban(Hash h)
      Ban the given hash.
      Specified by:
      ban in interface PeerListener
      Parameters:
      h - the torrent's info hash to add to the ban list