bittorrent-dht-byo
Advanced tools
Comparing version 0.0.1 to 0.0.2
@@ -16,3 +16,3 @@ #!/usr/bin/env node | ||
console.log("starting up; nodeId is %s and we have %d nodes", dht.nodeId.toString("hex"), dht.countNodes()); | ||
console.log("starting up; id is %s and we have %d nodes", dht.id.toString("hex"), dht.countNodes()); | ||
@@ -47,6 +47,6 @@ socket.on("message", function(message, from) { | ||
if (query.method.toString() === "ping") { | ||
console.log("responding to ping: %s from %s", query.id.toString("hex"), query.node.nodeId.toString("hex")); | ||
console.log("responding to ping: %s from %s", query.id.toString("hex"), query.node.id.toString("hex")); | ||
var response = { | ||
id: dht.nodeId, | ||
id: dht.id, | ||
}; | ||
@@ -62,6 +62,6 @@ | ||
if (query.method.toString() === "find_node") { | ||
console.log("responding to find_node: %s from %s for %s", query.id.toString("hex"), query.node.nodeId.toString("hex"), query.parameters.target.toString("hex")); | ||
console.log("responding to find_node: %s from %s for %s", query.id.toString("hex"), query.node.id.toString("hex"), query.parameters.target.toString("hex")); | ||
var response = { | ||
id: dht.nodeId, | ||
id: dht.id, | ||
nodes: Buffer(0), | ||
@@ -78,6 +78,6 @@ }; | ||
if (query.method.toString() === "get_peers") { | ||
console.log("responding to get_peers: %s from %s for %s", query.id.toString("hex"), query.node.nodeId.toString("hex"), query.parameters.info_hash.toString("hex")); | ||
console.log("responding to get_peers: %s from %s for %s", query.id.toString("hex"), query.node.id.toString("hex"), query.parameters.info_hash.toString("hex")); | ||
var response = { | ||
id: dht.nodeId, | ||
id: dht.id, | ||
token: crypto.randomBytes(20), | ||
@@ -102,3 +102,3 @@ nodes: Buffer(0), | ||
console.log("responding with error to %s: %s from %s", query.method.toString(), query.id.toString("hex"), query.node.nodeId.toString("hex")) | ||
console.log("responding with error to %s: %s from %s", query.method.toString(), query.id.toString("hex"), query.node.id.toString("hex")) | ||
@@ -116,3 +116,3 @@ var error = DHT.Error(204, "method not implemented"); | ||
setInterval(function() { | ||
fs.writeFileSync("./nodes.json", JSON.stringify({nodes: dht.nodes}, null, 2)); | ||
fs.writeFileSync("./nodes.json", JSON.stringify({nodes: dht.nodes.toArray()}, null, 2)); | ||
}, 5000); | ||
@@ -151,3 +151,3 @@ | ||
// dump the nodes out straight away | ||
fs.writeFileSync("./nodes.json", JSON.stringify({nodes: dht.nodes}, null, 2)); | ||
fs.writeFileSync("./nodes.json", JSON.stringify({nodes: dht.nodes.toArray()}, null, 2)); | ||
@@ -154,0 +154,0 @@ initiateSearch(); |
164
lib/dht.js
var async = require("async"), | ||
bencode = require("bencode-stream"), | ||
crypto = require("crypto"), | ||
events = require("events"); | ||
events = require("events"), | ||
KBucket = require("k-bucket"); | ||
@@ -14,3 +15,3 @@ var DHTError = require("./error"), | ||
this.nodeId = options.nodeId || Buffer.concat([Buffer("-DHT.JS-"), crypto.randomBytes(12)]); | ||
this.id = options.id || Buffer.concat([Buffer("-DHT.JS-"), crypto.randomBytes(12)]); | ||
@@ -21,4 +22,27 @@ this.counter = Math.floor(Math.random() * 4294967295); | ||
this.nodes = []; | ||
this.nodes = new KBucket({ | ||
localNodeId: this.id, | ||
}); | ||
var self = this; | ||
this.nodes.on("ping", function(oldContacts, newContact) { | ||
async.filter(oldContacts, function(oldContact, done) { | ||
self.pingQuery(oldContact, function(err, res) { | ||
if (err) { | ||
self.nodes.remove(oldContact); | ||
return done(true); | ||
} else { | ||
self.nodes.add(oldContact); | ||
return done(false); | ||
} | ||
}); | ||
}, function(removed) { | ||
if (removed.length > 0) { | ||
self.nodes.add(newContact); | ||
} | ||
}); | ||
}); | ||
if (Array.isArray(options.nodes)) { | ||
@@ -36,5 +60,3 @@ for (var i=0;i<options.nodes.length;++i) { | ||
DHT.prototype.ensureNode = function ensureNode(info) { | ||
var node = this.nodes.filter(function(node) { | ||
return node.nodeId.toString("hex") === info.nodeId.toString("hex"); | ||
}).shift(); | ||
var node = this.nodes.get(info.id); | ||
@@ -55,10 +77,3 @@ if (!node) { | ||
var exists = false; | ||
for (var i=0;i<this.nodes.length;++i) { | ||
if (this.nodes[i].nodeId[0] === node.nodeId[0] && this.nodes[i].nodeId.toString("hex") === node.nodeId.toString("hex")) { | ||
exists = true; | ||
} | ||
} | ||
if (exists) { | ||
if (this.nodes.get(node.id)) { | ||
return; | ||
@@ -69,3 +84,3 @@ } | ||
this.nodes.push(node); | ||
this.nodes.add(node); | ||
@@ -93,11 +108,7 @@ var self = this; | ||
DHT.prototype.removeNode = function removeNode(node) { | ||
for (var i=0;i<this.nodes.length;++i) { | ||
if (this.nodes[i].nodeId[0] === node.nodeId[0] && this.nodes[i].nodeId.toString("hex") === node.nodeId.toString("hex")) { | ||
this.nodes.splice(i--, 1); | ||
} | ||
} | ||
this.nodes.remove(node); | ||
}; | ||
DHT.prototype.countNodes = function countNodes() { | ||
return this.nodes.length; | ||
return this.nodes.count(); | ||
}; | ||
@@ -115,7 +126,7 @@ | ||
var nodeId = options.nodeId || crypto.randomBytes(20); | ||
var id = options.id || crypto.randomBytes(20); | ||
node = new DHTNode(node); | ||
this.findNodeQuery(node, nodeId, options, function(err, res) { | ||
this.findNodeQuery(node, id, options, function(err, res) { | ||
if (err) { | ||
@@ -125,3 +136,3 @@ return cb(err); | ||
node.nodeId = res.nodeId; | ||
node.id = res.id; | ||
@@ -164,6 +175,6 @@ self.addNode(node); | ||
cb.call(null, Error("timeout")); | ||
delete self.waiting[id.toString("hex")]; | ||
delete self.waiting[id.toString("hex")]; | ||
}, options.timeout || (30 * 1000)), | ||
return cb(Error("timeout")); | ||
}, options.timeout || (10 * 1000)), | ||
}; | ||
@@ -183,34 +194,28 @@ }); | ||
var retries = (typeof options.retries === "number") ? options.retries : 1; | ||
async.map(this.nodes.closest({id: infoHash}, 10), function(node, done) { | ||
self.getPeersQuery(node, infoHash, options, function(err, peers) { | ||
if (err) { | ||
return done(null, []); | ||
} | ||
async.map(this.nodes, function(node, done) { | ||
self.getPeersQuery(node, infoHash, options, function(err, res) { | ||
return done(null, res); | ||
return done(null, peers); | ||
}); | ||
}, function(err, responses) { | ||
responses = responses.filter(function(e) { | ||
return !!e; | ||
}); | ||
var peers = []; | ||
var nodes = responses.reduce(function(i, v) { | ||
i = i.concat(v.nodes); | ||
return i; | ||
}, []); | ||
responses.reduce(function(i, v) { return i.concat(v); }, []).forEach(function(peer) { | ||
for (var i=0;i<peers.length;++i) { | ||
if (peers[i].host === peer.host && peers[i].port === peer.port) { | ||
return; | ||
} | ||
} | ||
var peers = responses.reduce(function(i, v) { | ||
i = i.concat(v.peers); | ||
return i; | ||
}, []); | ||
peers.push(peer); | ||
}); | ||
self.addNodes(nodes); | ||
if (retries > 0 && peers.length === 0) { | ||
return self.getPeers(infoHash, {retries: retries - 1}, cb); | ||
} else { | ||
return cb(null, peers); | ||
} | ||
return cb(null, peers); | ||
}); | ||
}; | ||
DHT.prototype.findNodeQuery = function findNodeQuery(node, nodeId, options, cb) { | ||
DHT.prototype.findNodeQuery = function findNodeQuery(node, id, options, cb) { | ||
if (typeof options === "function") { | ||
@@ -223,3 +228,3 @@ cb = options; | ||
this.query(node, "find_node", {id: this.nodeId, target: nodeId}, options, function(err, res) { | ||
this.query(node, "find_node", {id: this.id, target: id}, options, function(err, res) { | ||
if (err) { | ||
@@ -236,3 +241,3 @@ return cb(err); | ||
nodes.push({ | ||
nodeId: res.nodes.slice(i * 26, i * 26 + 20), | ||
id: res.nodes.slice(i * 26, i * 26 + 20), | ||
host: [].slice.call(res.nodes, i * 26 + 20, i * 26 + 24).join("."), | ||
@@ -244,3 +249,3 @@ port: res.nodes.readUInt16BE(i * 26 + 24), | ||
return cb(null, { | ||
nodeId: nodeId, | ||
id: id, | ||
nodes: nodes, | ||
@@ -259,3 +264,5 @@ }); | ||
this.query(node, "get_peers", {id: this.nodeId, info_hash: infoHash}, options, function(err, res) { | ||
var self = this; | ||
this.query(node, "get_peers", {id: this.id, info_hash: infoHash}, options, function(err, res) { | ||
if (err) { | ||
@@ -277,3 +284,3 @@ return cb(err); | ||
nodes.push({ | ||
nodeId: res.nodes.slice(i * 26, i * 26 + 20), | ||
id: res.nodes.slice(i * 26, i * 26 + 20), | ||
host: [].slice.call(res.nodes, i * 26 + 20, i * 26 + 24).join("."), | ||
@@ -294,10 +301,41 @@ port: res.nodes.readUInt16BE(i * 26 + 24), | ||
return cb(null, { | ||
token: token, | ||
nodes: nodes, | ||
peers: peers, | ||
}); | ||
if (nodes.length > 0) { | ||
return async.map(nodes.filter(function(child) { | ||
return KBucket.distance(infoHash, node.id) > KBucket.distance(infoHash, child.id); | ||
}), function(info, done) { | ||
var node = new DHTNode(info); | ||
return self.getPeersQuery(node, infoHash, options, function(err, res) { | ||
if (err) { | ||
return done(null, []); | ||
} | ||
self.addNode(node); | ||
return done(null, res); | ||
}); | ||
}, function(err, results) { | ||
if (err) { | ||
return cb(err); | ||
} | ||
return cb(null, results.reduce(function(i, v) { return i.concat(v); }, [])); | ||
}); | ||
} | ||
return cb(null, peers); | ||
}); | ||
}; | ||
DHT.prototype.pingQuery = function pingQuery(node, options, cb) { | ||
if (typeof options === "function") { | ||
cb = options; | ||
options = null; | ||
} | ||
options = options || {}; | ||
return this.query(node, "ping", {id: this.id}, options, cb); | ||
}; | ||
DHT.prototype.respondTo = function respondTo(query, response, options, cb) { | ||
@@ -392,3 +430,3 @@ if (typeof options === "function") { | ||
var node = this.ensureNode({ | ||
nodeId: parameters.id, | ||
id: parameters.id, | ||
host: from.address, | ||
@@ -424,3 +462,3 @@ port: from.port, | ||
var node = this.ensureNode({ | ||
nodeId: parameters.id, | ||
id: parameters.id, | ||
host: from.address, | ||
@@ -452,3 +490,3 @@ port: from.port, | ||
var node = this.ensureNode({ | ||
nodeId: parameters.id, | ||
id: parameters.id, | ||
host: from.address, | ||
@@ -455,0 +493,0 @@ port: from.port, |
@@ -6,3 +6,3 @@ var events = require("events"); | ||
this.nodeId = options.nodeId || null; | ||
this.id = options.id || null; | ||
this.host = options.host || null; | ||
@@ -18,6 +18,6 @@ this.port = typeof options.port === "number" ? options.port : null; | ||
if (typeof this.nodeId === "string") { | ||
this.nodeId = Buffer(this.nodeId, "hex"); | ||
} else if (Array.isArray(this.nodeId)) { | ||
this.nodeId = Buffer(this.nodeId); | ||
if (typeof this.id === "string") { | ||
this.id = Buffer(this.id, "hex"); | ||
} else if (Array.isArray(this.id)) { | ||
this.id = Buffer(this.id); | ||
} | ||
@@ -35,3 +35,3 @@ | ||
return { | ||
nodeId: this.nodeId ? this.nodeId.toString("hex") : null, | ||
id: this.id ? this.id.toString("hex") : null, | ||
host: this.host, | ||
@@ -57,3 +57,3 @@ port: this.port, | ||
return Buffer.concat([ | ||
this.nodeId, | ||
this.id, | ||
this.toPeerInfo(), | ||
@@ -105,2 +105,3 @@ ]); | ||
var self = this; | ||
this.questionableTimeout = setTimeout(function() { | ||
@@ -107,0 +108,0 @@ self.setStatus("questionable"); |
{ | ||
"name": "bittorrent-dht-byo", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "A middle-level library for interacting with the BitTorrent DHT network. Bring your own transport layer and peer logic.", | ||
@@ -21,4 +21,5 @@ "main": "lib/dht.js", | ||
"bencode-stream": "0.0.9", | ||
"async": "~0.2.9" | ||
"async": "~0.2.9", | ||
"k-bucket": "git://github.com/deoxxa/k-bucket#patches" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29283
640
3
1