org.klomp.snark

## Class Peer

- java.lang.Object
- - org.klomp.snark.Peer

- All Implemented Interfaces:
    Comparable<Peer>, BandwidthListener
  Direct Known Subclasses:
    WebPeer

      public class Peer
      extends Object
      implements Comparable<Peer>, BandwidthListener

  Represents a peer in the BitTorrent network, managing all public information and communication with that peer.

  This class handles:

  - Peer identification and handshaking
  - BitTorrent protocol communication
  - Upload/download statistics tracking
  - Connection state management
  - Bandwidth monitoring and limiting

  Peers can be either incoming (they connected to us) or outgoing (we connected to them) connections.

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected Log` | `_log`
    `(package private) static long` | `CHECK_PERIOD`
    `(package private) MagnetState` | `magnetState` shared across all peers on this torrent
    `protected MetaInfo` | `metainfo` will start out null in magnet mode
    `(package private) static int` | `RATE_DEPTH`
    `(package private) PeerState` | `state` ` Keeps state for in/out connections.

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Peer(I2PSocket sock, InputStream in, OutputStream out, byte[] my_id, byte[] infohash, MetaInfo metainfo)` Incoming connection.
    `Peer(PeerID peerID, byte[] my_id, byte[] infohash, MetaInfo metainfo)` Outgoing connection.

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `(package private) void` | `cancel(int piece)` Tell the other side that we are no longer interested in any of the outstanding requests (if any) for this piece.
    `int` | `completed()` Return how much the peer has
    `(package private) void` | `disconnect()`
    `void` | `disconnect(boolean deregister)` Disconnects this peer if it was connected.
    `void` | `downloaded(int size)` Increment the counter.
    `boolean` | `equals(Object o)` Two Peers are equal when they have the same PeerID.
    `Destination` | `getDestination()`
    `long` | `getDownBWLimit()` Current limit in Bps
    `long` | `getDownloaded()` Returns the number of bytes that have been downloaded.
    `long` | `getDownloadRate()` Returns the average download rate in bytes per second.
    `Map<String,BEValue>` | `getHandshakeMap()`
    `long` | `getInactiveTime()`
    `MagnetState` | `getMagnetState()` Shared state across all peers, callers must sync on returned object
    `long` | `getMaxInactiveTime()`
    `int` | `getMaxPipeline()`
    `PeerID` | `getPeerID()` Returns the id of the peer.
    `long` | `getPexLastSent()` when did we last send pex peers?
    `String` | `getSocket()`
    `(package private) int` | `getTotalCommentsSent()`
    `long` | `getUpBWLimit()` Current limit in Bps
    `long` | `getUploaded()` Returns the number of bytes that have been uploaded.
    `long` | `getUploadRate()` Returns the average rate in Bps
    `long` | `getWhenConnected()` when did handshake complete?
    `int` | `hashCode()` The hash code of a Peer is the hash code of the peerID.
    `void` | `have(int piece)` Tell the peer we have another piece.
    `boolean` | `isChoked()` Whether or not the peer choked us.
    `boolean` | `isChoking()` Whether or not we are choking the peer.
    `boolean` | `isCompleted()` Return if a peer is a seeder
    `boolean` | `isConnected()`
    `boolean` | `isIncoming()` Is this an incoming connection? For RPC
    `boolean` | `isInterested()` Whether or not the peer is interested in pieces we have.
    `boolean` | `isInteresting()` Whether or not the peer has pieces we want from it.
    `boolean` | `isWebPeer()`
    `void` | `keepAlive()` Send keepalive
    `boolean` | `overDownBWLimit()` Are we currently over the limit?
    `boolean` | `overUpBWLimit()` Is snark as a whole over its limit?
    `(package private) void` | `request()` Update the request queue.
    `void` | `retransmitRequests()` Retransmit outstanding requests if necessary
    `void` | `runConnection(I2PSnarkUtil util, PeerListener listener, BandwidthListener bwl, BitField bitfield, MagnetState mState, boolean uploadOnly)` Runs the connection to the other peer.
    `void` | `sendExtension(int type, byte[] payload)`
    `void` | `setChoking(boolean choke)` Sets whether or not we are choking the peer.
    `void` | `setHandshakeMap(Map<String,BEValue> map)`
    `void` | `setMetaInfo(MetaInfo meta)` Switch from magnet mode to normal mode
    `void` | `setPexLastSent(long now)` when did we last send pex peers?
    `(package private) void` | `setRateHistory()` Push the total uploaded/downloaded onto a RATE_DEPTH deep stack Resets the downloaded and uploaded counters to zero.
    `(package private) void` | `setTotalCommentsSent(int count)`
    `boolean` | `shouldRequest(int size)` Should we request this many bytes?
    `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() after this.
    `boolean` | `supportsFast()`
    `String` | `toString()` Returns the String representation of the peerID.
    `void` | `uploaded(int size)` Increment the counter.

    - ### Methods inherited from class java.lang.Object

      `clone, finalize, getClass, notify, notifyAll, wait, wait, wait`

    - ### Methods inherited from interface java.lang.Comparable

      `compareTo`

- - ### Field Detail

    - #### _log

          protected final Log _log

    - #### CHECK_PERIOD

          static final long CHECK_PERIOD

      See Also:
        Constant Field Values

    - #### magnetState

          MagnetState magnetState

      shared across all peers on this torrent

    - #### metainfo

          protected MetaInfo metainfo

      will start out null in magnet mode

    - #### RATE_DEPTH

          static final int RATE_DEPTH

      See Also:
        Constant Field Values

    - #### state

          volatile PeerState state

      ` Keeps state for in/out connections. Non-null when the handshake was successful, the connection setup and runs. Do not access directly. All actions should be through Peer methods.

  - ### Constructor Detail

    - #### Peer

          public Peer(I2PSocket sock,
                      InputStream in,
                      OutputStream out,
                      byte[] my_id,
                      byte[] infohash,
                      MetaInfo metainfo)
               throws IOException

      Incoming connection. Creates a unconnected peer from the input and output stream got from the socket. Note that the complete handshake (which can take some time or block indefinitely) is done in the calling Thread to get the remote peer id. To completely start the connection call the connect() method.
      Parameters:
        `metainfo` - null if in magnet mode
      Throws:
        `IOException` - when an error occurred during the handshake.

    - #### Peer

          public Peer(PeerID peerID,
                      byte[] my_id,
                      byte[] infohash,
                      MetaInfo metainfo)

      Outgoing connection. Creates a disconnected peer given a PeerID, your own id and the relevant MetaInfo.
      Parameters:
        `metainfo` - null if in magnet mode

  - ### Method Detail

    - #### cancel

          void cancel(int piece)

      Tell the other side that we are no longer interested in any of the outstanding requests (if any) for this piece.

    - #### completed

          public int completed()

      Return how much the peer has
      Returns:
        number of completed pieces (not bytes)

    - #### disconnect

          void disconnect()

    - #### disconnect

          public void disconnect(boolean deregister)

      Disconnects this peer if it was connected. PeerListener.disconnected() will be called when the connection is completely terminated. If deregister is true, partial pieces will be returned.

    - #### downloaded

          public void downloaded(int size)

      Increment the counter.
      Specified by:
        `downloaded` in interface `BandwidthListener`
      Parameters:
        `size` - the number of bytes received

    - #### equals

          public boolean equals(Object o)

      Two Peers are equal when they have the same PeerID. All other properties are ignored.
      Overrides:
        `equals` in class `Object`

    - #### getDestination

          public Destination getDestination()

    - #### getDownBWLimit

          public long getDownBWLimit()

      Current limit in Bps
      Specified by:
        `getDownBWLimit` in interface `BandwidthListener`
      Returns:
        the download limit in Bps

    - #### getDownloaded

          public long getDownloaded()

      Returns the number of bytes that have been downloaded. Can be reset to zero with `resetCounters()` which is called every CHECK_PERIOD by PeerCheckerTask.

    - #### getDownloadRate

          public long getDownloadRate()

      Description copied from interface: `BandwidthListener`
      Returns the average download rate in bytes per second.
      Specified by:
        `getDownloadRate` in interface `BandwidthListener`
      Returns:
        the average download rate in Bps

    - #### getHandshakeMap

          public Map<String,BEValue> getHandshakeMap()

      Returns:
        could be null @since 0.8.4

    - #### getInactiveTime

          public long getInactiveTime()

    - #### getMagnetState

          public MagnetState getMagnetState()

      Shared state across all peers, callers must sync on returned object
      Returns:
        non-null

    - #### getMaxInactiveTime

          public long getMaxInactiveTime()

    - #### getMaxPipeline

          public int getMaxPipeline()

      Returns:
        min of PeerState.MIN_PIPELINE, max of PeerState.MAX_PIPELINE

    - #### getPeerID

          public PeerID getPeerID()

      Returns the id of the peer.

    - #### getPexLastSent

          public long getPexLastSent()

      when did we last send pex peers?

    - #### getSocket

          public String getSocket()

      Returns:
        socket debug string (for debug printing)

    - #### getTotalCommentsSent

          int getTotalCommentsSent()

    - #### getUpBWLimit

          public long getUpBWLimit()

      Current limit in Bps
      Specified by:
        `getUpBWLimit` in interface `BandwidthListener`
      Returns:
        the upload limit in Bps

    - #### getUploaded

          public long getUploaded()

      Returns the number of bytes that have been uploaded. Can be reset to zero with `resetCounters()` which is called every CHECK_PERIOD by PeerCheckerTask.

    - #### getUploadRate

          public long getUploadRate()

      Returns the average rate in Bps
      Specified by:
        `getUploadRate` in interface `BandwidthListener`
      Returns:
        the average upload rate in Bps

    - #### getWhenConnected

          public long getWhenConnected()

      when did handshake complete?

    - #### hashCode

          public int hashCode()

      The hash code of a Peer is the hash code of the peerID.
      Overrides:
        `hashCode` in class `Object`

    - #### have

          public void have(int piece)

      Tell the peer we have another piece.

    - #### isChoked

          public boolean isChoked()

      Whether or not the peer choked us. Returns true when not connected.

    - #### isChoking

          public boolean isChoking()

      Whether or not we are choking the peer. Returns true when not connected.

    - #### isCompleted

          public boolean isCompleted()

      Return if a peer is a seeder

    - #### isConnected

          public boolean isConnected()

    - #### isIncoming

          public boolean isIncoming()

      Is this an incoming connection? For RPC

    - #### isInterested

          public boolean isInterested()

      Whether or not the peer is interested in pieces we have. Returns false if not connected.

    - #### isInteresting

          public boolean isInteresting()

      Whether or not the peer has pieces we want from it. Returns false if not connected.

    - #### isWebPeer

          public boolean isWebPeer()

      Returns:
        false

    - #### keepAlive

          public void keepAlive()

      Send keepalive

    - #### 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

    - #### overUpBWLimit

          public boolean overUpBWLimit()

      Is snark as a whole over its limit?
      Specified by:
        `overUpBWLimit` in interface `BandwidthListener`
      Returns:
        true if over the upload limit, false otherwise

    - #### request

          void request()

      Update the request queue. Call after adding wanted pieces.

    - #### retransmitRequests

          public void retransmitRequests()

      Retransmit outstanding requests if necessary

    - #### runConnection

          public void runConnection(I2PSnarkUtil util,
                                    PeerListener listener,
                                    BandwidthListener bwl,
                                    BitField bitfield,
                                    MagnetState mState,
                                    boolean uploadOnly)

      Runs the connection to the other peer. This method does not return until the connection is terminated.

      When the connection is correctly started the connected() method of the given PeerListener is called. If the connection ends or the connection could not be setup correctly the disconnected() method is called.

      If the given BitField is non-null it is send to the peer as first message.

      Parameters:
        `uploadOnly` - if we are complete with skipped files, i.e. a partial seed

    - #### sendExtension

          public void sendExtension(int type,
                                    byte[] payload)

    - #### setChoking

          public void setChoking(boolean choke)

      Sets whether or not we are choking the peer. Defaults to true. When choke is false and the peer requests some pieces we upload them, otherwise requests of this peer are ignored.

    - #### setHandshakeMap

          public void setHandshakeMap(Map<String,BEValue> map)

      Parameters:
        `map` - non-null

    - #### setMetaInfo

          public void setMetaInfo(MetaInfo meta)

      Switch from magnet mode to normal mode

    - #### setPexLastSent

          public void setPexLastSent(long now)

      when did we last send pex peers?

    - #### setRateHistory

          void setRateHistory()

      Push the total uploaded/downloaded onto a RATE_DEPTH deep stack Resets the downloaded and uploaded counters to zero.

    - #### setTotalCommentsSent

          void setTotalCommentsSent(int count)

    - #### shouldRequest

          public boolean shouldRequest(int size)

      Should we request this 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 to request from
        `size` - the number of bytes to request
      Returns:
        true if the request should be made, false otherwise

    - #### shouldSend

          public boolean shouldSend(int size)

      Should we send this many bytes? Do NOT call uploaded() after this.
      Specified by:
        `shouldSend` in interface `BandwidthListener`
      Parameters:
        `size` - the number of bytes to send
      Returns:
        true if the bytes should be sent, false otherwise

    - #### supportsFast

          public boolean supportsFast()

    - #### toString

          public String toString()

      Returns the String representation of the peerID.
      Overrides:
        `toString` in class `Object`

    - #### uploaded

          public void uploaded(int size)

      Increment the counter.
      Specified by:
        `uploaded` in interface `BandwidthListener`
      Parameters:
        `size` - the number of bytes sent