org.klomp.snark
Class PeerCoordinator

java.lang.Object
  extended by org.klomp.snark.PeerCoordinator
All Implemented Interfaces:
PeerListener

 class PeerCoordinator
extends Object
implements PeerListener

Coordinates what peer does what.


Field Summary
(package private) static long CHECK_PERIOD
           
(package private)  int interestedAndChoking
          External use by PeerCheckerTask only.
static long MAX_INACTIVE
           
(package private) static int MAX_UPLOADERS
           
(package private)  MetaInfo metainfo
          External use by PeerMonitorTask only.
(package private)  Deque<Peer> peers
          synchronize on this when changing peers or downloaders.
(package private) static int RATE_DEPTH
           
(package private)  Storage storage
          External use by PeerMonitorTask only.
(package private)  int uploaders
          Approximation of the number of current uploaders.
 
Constructor Summary
PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage, CoordinatorListener listener, Snark torrent)
           
 
Method Summary
 boolean addPeer(Peer peer)
          Add peer (inbound or outbound)
 int allowedUploaders()
          Return number of allowed uploaders for this torrent.
 boolean completed()
           
 void connected(Peer peer)
          Called when the connection to the peer has started and the handshake was successfull.
 void disconnected(Peer peer)
          Called when the connection to the peer was terminated or the connection handshake failed.
 void downloaded(Peer peer, int size)
          Called when a peer has downloaded some bytes of a piece.
 long getCurrentUploadRate()
           
 long getDownloaded()
          Returns the total number of downloaded bytes of all peers.
 long getDownloadRate()
          Returns the 4-minute-average rate in Bps
 byte[] getID()
           
 byte[] getInfoHash()
           
 long getLeft()
          Bytes not yet in storage.
 MetaInfo getMetaInfo()
           
 String getName()
           
 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.
 int getPeerCount()
          might be wrong
 int getPeers()
          should be right
(package private)  Set<PeerID> getPEXPeers()
          Called by TrackerClient
(package private) static long getRate(long[] array)
           
 Storage getStorage()
           
 long getUploaded()
          Returns the total number of uploaded bytes of all peers.
 int getUploaders()
           
 long getUploadRate()
           
 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)
          this does nothing but logging
 void gotExtension(Peer peer, int id, byte[] bs)
          PeerListener callback
 boolean gotHave(Peer peer, int piece)
          Called when a have piece message is received.
 void gotInterest(Peer peer, boolean interest)
          Called when an interested message is received.
 void gotPeers(Peer peer, List<PeerID> peers)
          Get peers from PEX - 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()
           
 boolean halted()
           
 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 overUpBWLimit()
           
 boolean overUpBWLimit(long total)
           
 List<Peer> peerList()
          for web page detailed stats
 void restart()
           
 void savePartialPieces(Peer peer, List<Request> partials)
          Save partial pieces on peer disconnection and hopefully restart it later.
(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)
           
 void setRateHistory(long up, long down)
          Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
 void setStorage(Storage stg)
          Sets the storage after transition out of magnet mode Snark calls this after we call gotMetaInfo()
 void setUploaded(long up)
          Sets the initial total of uploaded bytes of all peers (from a saved status)
 void setWantedPieces()
          Only called externally from Storage after the double-check fails.
(package private)  void unchokePeer()
           
 void updatePiecePriorities()
          Maps file priorities to piece priorities.
 void uploaded(Peer peer, int size)
          Called when a peer has uploaded some bytes of a piece.
 int wantPiece(Peer peer, BitField havePieces)
          Returns one of pieces in the given BitField that is still wanted or -1 if none of the given pieces are wanted.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

metainfo

MetaInfo metainfo
External use by PeerMonitorTask only. Will be null when in magnet mode.


storage

Storage storage
External use by PeerMonitorTask only. Will be null when in magnet mode.


CHECK_PERIOD

static final long CHECK_PERIOD
See Also:
Constant Field Values

MAX_UPLOADERS

static final int MAX_UPLOADERS
See Also:
Constant Field Values

MAX_INACTIVE

public static final long MAX_INACTIVE
See Also:
Constant Field Values

uploaders

int uploaders
Approximation of the number of current uploaders. Resynced by PeerChecker once in a while. External use by PeerCheckerTask only.


interestedAndChoking

int interestedAndChoking
External use by PeerCheckerTask only.


RATE_DEPTH

static final int RATE_DEPTH
See Also:
Constant Field Values

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. External use by PeerMonitorTask only.

Constructor Detail

PeerCoordinator

public PeerCoordinator(I2PSnarkUtil util,
                       byte[] id,
                       byte[] infohash,
                       MetaInfo metainfo,
                       Storage storage,
                       CoordinatorListener listener,
                       Snark torrent)
Parameters:
metainfo - null if in magnet mode
storage - null if in magnet mode
Method Detail

setWantedPieces

public void setWantedPieces()
Only called externally from Storage after the double-check fails. Sets wantedBytes too.


getStorage

public Storage getStorage()

peerList

public List<Peer> peerList()
for web page detailed stats


getID

public byte[] getID()

getName

public String getName()

completed

public boolean completed()

getPeerCount

public int getPeerCount()
might be wrong


getPeers

public int getPeers()
should be right


getLeft

public long getLeft()
Bytes not yet in storage. Does NOT account for skipped files. Not exact (does not adjust for last piece size). 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.
Since:
0.9.1

getUploaded

public long getUploaded()
Returns the total number of uploaded bytes of all peers.


setUploaded

public void setUploaded(long up)
Sets the initial total of uploaded bytes of all peers (from a saved status)

Since:
0.9.15

getDownloaded

public long getDownloaded()
Returns the total number of downloaded bytes of all peers.


setRateHistory

public void setRateHistory(long up,
                           long down)
Push the total uploaded/downloaded onto a RATE_DEPTH deep stack


setRate

static void setRate(long val,
                    long[] array)

getDownloadRate

public long getDownloadRate()
Returns the 4-minute-average rate in Bps


getUploadRate

public long getUploadRate()

getCurrentUploadRate

public long getCurrentUploadRate()

getRate

static long getRate(long[] array)

getMetaInfo

public MetaInfo getMetaInfo()

getInfoHash

public byte[] getInfoHash()
Since:
0.8.4

needPeers

public boolean needPeers()
Inbound. Not halted, peers < max.

Since:
0.9.1

needOutboundPeers

public boolean needOutboundPeers()
Outbound. Not halted, peers < max, and need pieces.

Since:
0.9.1

halted

public boolean halted()

halt

public void halt()

restart

public void restart()
Since:
0.9.1

connected

public void connected(Peer peer)
Description copied from interface: PeerListener
Called when the connection to the peer has started and the handshake was successfull.

Specified by:
connected in interface PeerListener
Parameters:
peer - the Peer that just got connected.

addPeer

public boolean addPeer(Peer peer)
Add peer (inbound or outbound)

Returns:
true if actual attempt to add peer occurs

unchokePeer

void unchokePeer()

gotHave

public boolean gotHave(Peer peer,
                       int piece)
Description copied from interface: PeerListener
Called when a have piece message is received. If the method returns true and the peer has not yet received a interested message or we indicated earlier to be not interested then an interested message will be send.

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

public int wantPiece(Peer peer,
                     BitField havePieces)
Returns one of pieces in the given BitField that is still wanted or -1 if none of the given pieces are wanted.

Specified by:
wantPiece 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:
one of the pieces from the bitfield that we want or -1 if we are no longer interested in the peer.

updatePiecePriorities

public void updatePiecePriorities()
Maps file priorities to piece priorities. Call after updating file priorities Storage.setPriority()

Since:
0.8.1

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

uploaded

public void uploaded(Peer peer,
                     int size)
Called when a peer has uploaded some bytes of a piece.

Specified by:
uploaded in interface PeerListener
Parameters:
peer - the Peer to which size bytes where uploaded.
size - the number of bytes that where uploaded.

downloaded

public void downloaded(Peer peer,
                       int size)
Called when a peer has downloaded some bytes of a piece.

Specified by:
downloaded in interface PeerListener
Parameters:
peer - the Peer from which size bytes where downloaded.
size - the number of bytes that where downloaded.

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 IOE saving the piece

gotChoke

public void gotChoke(Peer peer,
                     boolean choke)
this does nothing but logging

Specified by:
gotChoke in interface PeerListener
Parameters:
peer - the Peer that got the message.
choke - true when the peer got a choke message, false when the peer got an unchoke message.

gotInterest

public void gotInterest(Peer peer,
                        boolean interest)
Description copied from interface: PeerListener
Called when an interested message is received.

Specified by:
gotInterest in interface PeerListener
Parameters:
peer - the Peer that got the message.
interest - true when the peer got a interested message, false when the peer got an uninterested message.

disconnected

public void disconnected(Peer peer)
Description copied from interface: PeerListener
Called when the connection to the peer was terminated or the connection handshake failed.

Specified by:
disconnected in interface PeerListener
Parameters:
peer - the Peer that just got disconnected.

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, piece.setDownloaded() must be set. len field in Requests is ignored.
Since:
0.8.2

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:
havePieces - pieces the peer has, the rv will be one of these
Returns:
PartialPiece or null
Since:
0.8.2

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() 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
Since:
0.8.2

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
Since:
0.8.4

sendPeers

void sendPeers(Peer peer)
Send a PEX message to the peer, if he supports PEX. This just sends everybody we are connected to, we don't track new vs. old peers yet.

Since:
0.8.4

sendDHT

void sendDHT(Peer peer)
Send a DHT message to the peer, if we both support DHT.

Since:
DHT

setStorage

public void setStorage(Storage stg)
Sets the storage after transition out of magnet mode Snark calls this after we call gotMetaInfo()

Since:
0.8.4

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:
rport - must be port + 1
peer - the Peer that got the message.
port - the query port
Since:
0.8.4

gotPeers

public void gotPeers(Peer peer,
                     List<PeerID> peers)
Get peers from PEX - PeerListener callback

Specified by:
gotPeers in interface PeerListener
Parameters:
peer - the Peer that got the message.
peers - the peer IDs (dest hashes)
Since:
0.8.4

getPEXPeers

Set<PeerID> getPEXPeers()
Called by TrackerClient

Returns:
the Set itself, modifiable, not a copy, caller should clear()
Since:
0.8.4

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.


getUploaders

public int getUploaders()
Returns:
current
Since:
0.8.4

overUpBWLimit

public boolean overUpBWLimit()

overUpBWLimit

public boolean overUpBWLimit(long total)

getUtil

public I2PSnarkUtil getUtil()
Convenience

Specified by:
getUtil in interface PeerListener
Since:
0.9.2