JoystreamClassic / joystream-node

Node bindings for joystream libtorrent extension
MIT License
0 stars 3 forks source link

Factor out secondary DHT peer discovery #45

Open bedeho opened 7 years ago

bedeho commented 7 years ago

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:

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

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
*/
bedeho commented 7 years ago

Ok, this is done now, have a look @rllola