diff --git a/index.js b/index.js index 54b30ec..2520671 100644 --- a/index.js +++ b/index.js @@ -45,6 +45,8 @@ function DHT (opts) { this._secrets = [crypto.randomBytes(32), crypto.randomBytes(32)] this._secretsInterval = setInterval(rotateSecrets, 5 * 60 * 1000) this._tickInterval = setInterval(tick, 5 * 1000) + this._top = null + this._bottom = null if (opts.nodes) { for (var i = 0; i < opts.nodes.length; i++) { @@ -105,7 +107,17 @@ DHT.prototype.closest = function (query, opts, cb) { } DHT.prototype._pingSome = function () { - // console.log('ping some ...') + var all = this.nodes.toArray() + if (!all.length) return + + var cnt = this.inflightQueries > 2 ? 1 : 3 + var oldest = this._bottom + + while (cnt--) { + if (!oldest || this._tick - oldest.tick < 3) continue + this._check(oldest) + oldest = oldest.next + } } DHT.prototype._closestNodes = function (target, opts, cb) { @@ -163,7 +175,6 @@ DHT.prototype._rotateSecrets = function () { } DHT.prototype._bootstrap = function () { - // TODO: run in the background // TODO: check stats, to determine wheather to rerun? var self = this @@ -352,6 +363,13 @@ DHT.prototype._onnodeping = function (oldContacts, newContact) { if (reping.length) this._reping(reping, newContact) } +DHT.prototype._check = function (node) { + var self = this + this._request({command: '_ping', id: this._queryId}, node, false, function (err) { + if (err) self._removeNode(node) + }) +} + DHT.prototype._reping = function (oldContacts, newContact) { var self = this var next = null @@ -366,7 +384,7 @@ DHT.prototype._reping = function (oldContacts, newContact) { function afterPing (err) { if (!err) return ping() - self.nodes.remove(next.id) + self._removeNode(next) self.nodes.add(newContact) } } @@ -377,13 +395,29 @@ DHT.prototype._token = function (peer, i) { DHT.prototype._addNode = function (id, peer, token) { if (bufferEquals(id, this.id)) return - this.nodes.add({ - id: id, - port: peer.port, - host: peer.host, - roundtripToken: token, - tick: this._tick - }) + + var node = this.nodes.get(id) + var fresh = !node + + if (!node) node = {} + + node.id = id, + node.port = peer.port, + node.host = peer.host, + node.roundtripToken = token, + node.tick = this._tick + + if (!fresh) remove(this, node) + add(this, node) + + this.nodes.add(node) + if (fresh) this.emit('add-node', node) +} + +DHT.prototype._removeNode = function (node) { + remove(this, node) + this.nodes.remove(node.id) + this.emit('remove-node', node) } DHT.prototype.listen = function (port, cb) { @@ -418,3 +452,32 @@ function validateId (id) { function arbiter (incumbant, candidate) { return candidate } + +function remove (self, node) { + if (self._bottom !== node && self._top !== node) { + node.prev.next = node.next + node.next.prev = node.prev + node.next = node.prev = null + } else { + if (self._bottom === node) { + self._bottom = node.next + if (self._bottom) self._bottom.prev = null + } + if (self._top === node) { + self._top = node.prev + if (self._top) self._top.next = null + } + } +} + +function add (self, node) { + if (!self._top && !self._bottom) { + self._top = self._bottom = node + node.prev = node.next = null + } else { + self._top.next = node + node.prev = self._top + node.next = null + self._top = node + } +} diff --git a/package.json b/package.json index f7f3f6a..0458b4d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "hyperdht", + "name": "dht-rpc", "version": "0.0.0", - "description": "WIP dht based on kademlia, with a focus on extensibility + modularity", + "description": "Make RPC calls over a Kademlia based DHT.", "main": "index.js", "dependencies": { "buffer-equals": "^1.0.4", @@ -20,7 +20,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/mafintosh/hyperdht.git" + "url": "https://github.com/mafintosh/dht-rpc.git" }, "scripts": { "test": "standard" @@ -28,7 +28,7 @@ "author": "Mathias Buus (@mafintosh)", "license": "MIT", "bugs": { - "url": "https://github.com/mafintosh/hyperdht/issues" + "url": "https://github.com/mafintosh/dht-rpc/issues" }, - "homepage": "https://github.com/mafintosh/hyperdht" + "homepage": "https://github.com/mafintosh/dht-rpc" }