We are doing our own client specific peer discovery, using the BitTorrent mainline DHT, by having our peers announce and get peers on a so called secondary info hash, which depends on the primary info hash.
Problem
This extra peer discovery has nothing to do with our extension, native addon, or necessarily even LibTorrent. Its a technique that anyone could want to use with any application. Currently we have however mixed the implementation of this inside of our javascript wrapper here in joystream-node. If it was factored out as its own module, then the wrapper would be simpler - helping us moving in the direction of this https://github.com/JoyStream/joystream-node/issues/42, and testing the peer discovery itself would likely be easier.
Proposal A [preferred]
This proposal stops attempting to maintain any sort of list of peers, which is not being used for anything in joystream-electron currently anyway, but rather just makes sure to have the minimal amount of peer discovery support in any application, and drop it from this library.
In the application, then for each added torrent:
announcing host on that torrent at regular intervals on the secondary info hash of that torrent.
make requests to DHT node to get peers at regular intervals on the secondary info hash of that torrent.
when a request comes back for a torrent, do torrent_handle::connect to all peers on this list.
Proposal B
This proposal, involves maintaining a list of peers found. This is currently what we are already doing inside this library, in the Torrentclass. This requires maintaining state which is sufficiently complex so as to justify creation of a new module, e.g. called dht-peer-list, which can then be used by joystream-electron for example, which has the inteface described below.
Note:
One point of possible contention w.r.t. using this approach in joystream-electron is that we are in effect introducing a peer list and derived events based on LibTorrent events, and we have moved away from this in the javascript wrapper for this library. However, there is a distinction between these two cases. The peer lists we are introducing here do not exist as state in LibTorrent. They are entirely constructed based on our policy about how long a peer must be seen on the DHT for a given key. Hence this is bonafide application level state which is constructed in node, even if derived from LibTorrent information. this was not the key for torrent and peer lists in the wrapper.
class: PeerListManager
/**
* Created a `PeerListManager` object which is in stopped state.
* Automatically manages a peer list based using the DHT, using a provided key.
*
* @constructor
* @param {String} key key used
* @param {Function} announceOn Callback, without arguments, used to signal when to announce on `key`.
* @param {Number} announceEvery Number of minutes between each time `announceOn` is called.
* @param {GetPeers} getPeers Callback, without arguments, used to signal when to request get peers on `key`.
* @param {Number} getPeersEvery Number of minutes between each time `getPeers` is called.
* @param {Number} peerEvictionTickLimit The number of consecutive get peer replies from which a peer may be absent before getting evicted from the peer list
*/
Note that
callbacks, rather than events, are used to trigger announcing and requesting peers, because the appropriate usage pattern is to have a single consumer of these events.
this manager corresponds to a single torrent, not a set of torrents.
method: start
/**
* Starts manager.
* Makes an initial announcement and get peers request, as well as evicts any expired peers in peer list.
* Keeps doing such requests and evictions at regular intervals.
*
* @method start
* @throws {Error} If the manager has already started
*/
PS: this is the spot to start all timers
method: stop
/**
* Stops manager.
* Stops any further requests or peer evictions.
*
* @method start
* @throws {Error} If the manager has already started
*/
PS: this is the spot to clear all timers
method: isStarted
/**
* Returns whether the manager is in the started state or not.
*
* @method isStarted
* @return {Bool} whether manager is started
*/
method: peers
/**
* Get current peers.
*
* @method peers
* @return {Array} list of `Peer` objects
*/
Peer is of the form
{
host {String} : name or IP of host
port {Number} : port on host where BitTorrent daemon runs
tick {Number} : the number of consecutive get peer replies which have had this peer missing
}
method: processGetPeersReply
/**
* Processes reply to a prior get peers request on `getPeers`.
* - adds new peers to peer list, as seen in `peers`, and triggers `peerFound` event
* - updates tick for existing peers, and evicts expired peers, as well as trigger `peerEvicted` event
*
* @method processGetPeersReply
* @param {Array} List of `Peer` objects
*/
event: peerFound
/**
* A new peer is added to the peer list of this torrent.
* @event peerFound
* @param {Peer} peer which was found
*/
event: peerEvicted
/**
* A peer was evicted from the peer list of this torrent.
* @event peerEvicted
* @param {Peer} peer which was found
*/
Background
We are doing our own client specific peer discovery, using the BitTorrent mainline DHT, by having our peers announce and get peers on a so called secondary info hash, which depends on the primary info hash.
Problem
This extra peer discovery has nothing to do with our extension, native addon, or necessarily even LibTorrent. Its a technique that anyone could want to use with any application. Currently we have however mixed the implementation of this inside of our javascript wrapper here in
joystream-node
. If it was factored out as its own module, then the wrapper would be simpler - helping us moving in the direction of this https://github.com/JoyStream/joystream-node/issues/42, and testing the peer discovery itself would likely be easier.Proposal A [preferred]
This proposal stops attempting to maintain any sort of list of peers, which is not being used for anything in
joystream-electron
currently anyway, but rather just makes sure to have the minimal amount of peer discovery support in any application, and drop it from this library.In the application, then for each added torrent:
torrent_handle::connect
to all peers on this list.Proposal B
This proposal, involves maintaining a list of peers found. This is currently what we are already doing inside this library, in the
Torrent
class. This requires maintaining state which is sufficiently complex so as to justify creation of a new module, e.g. calleddht-peer-list
, which can then be used byjoystream-electron
for example, which has the inteface described below.Note: One point of possible contention w.r.t. using this approach in
joystream-electron
is that we are in effect introducing a peer list and derived events based on LibTorrent events, and we have moved away from this in the javascript wrapper for this library. However, there is a distinction between these two cases. The peer lists we are introducing here do not exist as state in LibTorrent. They are entirely constructed based on our policy about how long a peer must be seen on the DHT for a given key. Hence this is bonafide application level state which is constructed in node, even if derived from LibTorrent information. this was not the key for torrent and peer lists in the wrapper.class:
PeerListManager
Note that
method:
start
PS: this is the spot to start all timers
method:
stop
PS: this is the spot to clear all timers
method:
isStarted
method:
peers
Peer
is of the formmethod:
processGetPeersReply
event:
peerFound
event:
peerEvicted