diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2013-11-10 14:09:10 +0400 |
---|---|---|
committer | Feross Aboukhadijeh <feross@feross.org> | 2013-11-10 14:09:10 +0400 |
commit | f05032a7291317ae29ec679385c947bcfbe7438d (patch) | |
tree | fc2196798828f170b906407758e0a977b28ea2f8 | |
parent | 4977042caf8b04ff27be4f6d604b09ecdf3dd2d5 (diff) |
move bittorrent-dht into its own module
-rw-r--r-- | README.md | 16 | ||||
-rw-r--r-- | index.js | 2 | ||||
-rw-r--r-- | lib/bittorrent-dht/.jshintrc | 9 | ||||
-rw-r--r-- | lib/bittorrent-dht/.npmignore | 1 | ||||
-rw-r--r-- | lib/bittorrent-dht/README.md | 4 | ||||
-rw-r--r-- | lib/bittorrent-dht/choose-best.js | 34 | ||||
-rw-r--r-- | lib/bittorrent-dht/example.js | 27 | ||||
-rw-r--r-- | lib/bittorrent-dht/index.js | 211 | ||||
-rw-r--r-- | lib/bittorrent-dht/package.json | 19 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | test/echo/echo.c | 94 |
11 files changed, 9 insertions, 409 deletions
@@ -1,8 +1,5 @@ -![WebTorrent](https://raw.github.com/feross/webtorrent/master/img/wordmark.png) - -## WebTorrent - BitTorrent in the Browser (via WebRTC) - -A streaming torrent client in your browser, powered by webRTC and black magic. +# ![WebTorrent](https://raw.github.com/feross/webtorrent/master/img/wordmark.png) +### WebTorrent - Streaming BitTorrent client for the browser (via WebRTC) [![Build Status](https://travis-ci.org/feross/webtorrent.png?branch=master)](https://travis-ci.org/feross/webtorrent) [![Dependency Status](https://david-dm.org/feross/webtorrent.png)](https://david-dm.org/feross/webtorrent) @@ -57,13 +54,15 @@ Since WebTorrent is web-first, it's dead simple for users to use without underst "When applications are done well, they are just the really application-specific, brackish residue that can't be so easily abstracted away. All the nice, reusable components sublimate away onto github and npm where everybody can collaborate to advance the commons." — [substack](http://substack.net/how_I_write_modules) +![Magic](https://raw.github.com/feross/webtorrent/master/img/logo.png) + These are the modules we are writing to make WebTorrent work: - [webtorrent](https://github.com/feross/webtorrent) (this repo) - [magnet-uri](https://github.com/feross/magnet-uri) -- bittorent-dht (todo) -- bittorent-protocol (todo) -- bittorent-swarm (todo) +- [bittorrent-dht](https://github.com/feross/bittorrent-dht) (WIP) +- [bittorrent-protocol](https://github.com/feross/bittorrent-protocol) (WIP) +- bittorrent-swarm (todo) - webtorrent-protocol (todo) - webtorrent-dht (todo) - webtorrent-bootstrap (todo) @@ -76,7 +75,6 @@ These are the modules we are writing to make WebTorrent work: - webtorrent-chrome (todo) - [chrome-app-socket](https://github.com/feross/chrome-app-socket) ([chrome-dgram](https://github.com/feross/chrome-dgram) & [chrome-net](https://github.com/feross/chrome-net)) -![Magic](https://raw.github.com/feross/webtorrent/master/img/logo.png) ## TODO for basic working version @@ -9,7 +9,7 @@ // if (process.env.DEBUG !== 'false') console.log.apply(console, arguments) // } -var DHT = require('./lib/bittorrent-dht') +var DHT = require('bittorrent-dht') var hat = require('hat') var magnet = require('magnet-uri') var Swarm = require('./lib/peer-wire-swarm') diff --git a/lib/bittorrent-dht/.jshintrc b/lib/bittorrent-dht/.jshintrc deleted file mode 100644 index c1bb5e9..0000000 --- a/lib/bittorrent-dht/.jshintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "asi": true, - "laxbreak": true, - "expr": true, - "strict": false, - "node": true, - "browser": true, - "devel": true -}
\ No newline at end of file diff --git a/lib/bittorrent-dht/.npmignore b/lib/bittorrent-dht/.npmignore deleted file mode 100644 index 3c3629e..0000000 --- a/lib/bittorrent-dht/.npmignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/lib/bittorrent-dht/README.md b/lib/bittorrent-dht/README.md deleted file mode 100644 index 7708f9e..0000000 --- a/lib/bittorrent-dht/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# bittorrent-dht - -a lightweight implementation of the BitTorrent DHT - diff --git a/lib/bittorrent-dht/choose-best.js b/lib/bittorrent-dht/choose-best.js deleted file mode 100644 index 6a56e6a..0000000 --- a/lib/bittorrent-dht/choose-best.js +++ /dev/null @@ -1,34 +0,0 @@ - -var DHT = require('./'); -var async = require('async'); - -// 8217,4622,7171,4338,10334,2897,4903 -> 42482 -// 5275,2300,7371,2982,2250,3455,2788 -> 26421 - -var globalStart = Date.now(); -async.each( - [ - "99cf7a5ae561b7a55072eb07645277b6df0ef902", - "2b96d97e1de415f0f308f1cf70e9a18567f4a7f9", - //"ee08430b97ef922bbf123aebf07b43fed29e992d" - ], - function(hash, callback) { - var dht = new DHT(new Buffer(hash, 'hex')); - dht.findPeers(300); - - var peers = [], start = Date.now(), i = 0; - dht.on('peer', function(peer) { - //console.log(hash, ++i); // DEBUG - peers.push(peer); - - if (peers.length != 300) return; - console.log("\n\n\nready: "+(Date.now() - start)+"\n\n"); // 2 - 3 seconds - //setTimeout(callback, 4000); - callback(); - }); - }, - function(err) - { - console.log("Everything finished "+(Date.now() - globalStart)); - } -); diff --git a/lib/bittorrent-dht/example.js b/lib/bittorrent-dht/example.js deleted file mode 100644 index d6fd336..0000000 --- a/lib/bittorrent-dht/example.js +++ /dev/null @@ -1,27 +0,0 @@ - -var DHT = require('./'); -var async = require('async'); - -async.eachSeries( -//async.each( - [ - 'e756b6ed7f1f647db2ea7e153e2fdc6226218a1f', - // 'e756b6ed7f1f647db2ea7e153e2fdc6226218a1f', - '948cd498ab5acdc0a61dee8b012eb93ae231b2ff', - ], - function(hash, callback) { - var dht = new DHT(new Buffer(hash, 'hex')); - dht.findPeers(300); - - var peers = [], start = Date.now(), i = 0; - dht.on('peer', function(peer) { - //console.log(hash, ++i); // DEBUG - peers.push(peer); - - if (peers.length != 300) return; - console.log("\n\n\nready: "+(Date.now() - start)+"\n\n"); // 2 - 3 seconds - //setTimeout(callback, 4000); - callback(); - }); - } -); diff --git a/lib/bittorrent-dht/index.js b/lib/bittorrent-dht/index.js deleted file mode 100644 index c707fbf..0000000 --- a/lib/bittorrent-dht/index.js +++ /dev/null @@ -1,211 +0,0 @@ -// TODO: -// - Use the same DHT object for looking up multiple torrents -// - Persist the routing table for later bootstrapping -// - Should work in Node, not just browser -// - Use actual DHT data structure with "buckets" (follow spec) - -module.exports = DHT - -var bencode = require('bncode') -var bops = require('bops') -var compact2string = require('compact2string') -var EventEmitter = require('events').EventEmitter -var dgram = require('chrome-dgram') -var is = require('core-util-is') // added in Node 0.12 -var util = require('util') - -var MAX_NODES = 5000 -var BOOTSTRAP_TIMEOUT = 5000 -var BOOTSTRAP_NODES = [ - 'dht.transmissionbt.com:6881', - 'router.bittorrent.com:6881', - 'router.utorrent.com:6881' -] - -function randomId () { - var array = new Uint8Array(20) - window.crypto.getRandomValues(array) - return array -} - -function parseNodeInfo (compact) { - try { - var nodes = [] - for (var i = 0; i < compact.length; i += 26) { - nodes.push(compact2string(bops.subarray(compact, i + 20, i + 26))) - } - return nodes - } catch (err) { - console.warn('Invalid node info ' + compact) - return [] - } -} - -function parsePeerInfo (list) { - try { - return list.map(compact2string) - } catch (err) { - console.warn('Invalid peer info ' + list) - return [] - } -} - -util.inherits(DHT, EventEmitter) - -/** - * Create a new DHT - * @param {string|Buffer} infoHash - */ -function DHT (infoHash) { - var self = this - EventEmitter.call(self) - - // Support infoHash as string or Buffer - if (is.isString(infoHash)) { - infoHash = bops.from(infoHash, 'hex') - } else if (!is.isBuffer(infoHash)) { - throw new Error('DHT() requires string or buffer infoHash') - } - - self.infoHash = infoHash - self.nodes = {} - self.peers = {} - self.queue = [].concat(BOOTSTRAP_NODES) - - // Number of nodes we still need to find to satisfy the last call to findPeers - self.missingPeers = 0 - - self.nodeId = randomId() - console.log('our node id: ' + bops.to(self.nodeId, 'hex')) - - self.requestId = 1 - self.pendingRequests = {} - - self.message = { - t: self.requestId.toString(), - y: 'q', - q: 'get_peers', - a: { - id: self.nodeId, - info_hash: self.infoHash - } - } - console.log('created message: ' + JSON.stringify(self.message)) - self.message = bencode.encode(self.message) - - self.pendingRequests[self.requestId] = 1 - - self.socket = dgram.createSocket('udp4') - self.socket.on('message', self._onData.bind(self)) -} - -/** - * Called when client finds a new DHT node - * @param {string} addr - */ -DHT.prototype._handleNode = function (addr) { - var self = this - if (self.nodes[addr]) { - // console.log('already know about this node!') - return - } - - process.nextTick(function () { - self.emit('node', addr, bops.to(self.infoHash, 'hex')) - }) - - if (self.missingPeers > 0) self.query(addr) - // if (self.queue.length < 50) self.queue.push(addr) // TODO: remove this? -} - -/** - * Called when client finds a new peer - * @param {string} addr - */ -DHT.prototype._handlePeer = function (addr) { - var self = this - if (self.peers[addr]) return - self.peers[addr] = true - self.missingPeers = Math.max(0, self.missingPeers - 1) - - process.nextTick(function () { - self.emit('peer', addr, bops.to(self.infoHash, 'hex')) - }) -} - -DHT.prototype._onData = function (data, host, port) { - var self = this - var addr = host + ':' + port - - var message - try { - // console.log('got response from ' + addr) - message = bencode.decode(data) - // console.log(JSON.stringify(message)) - if (!message) throw new Error('message is undefined') - } catch (err) { - console.error('Failed to decode UDP data from node ' + addr) - console.error(err) - return - } - - if (!message.t || (bops.to(message.t) !== self.requestId.toString())) { - console.log('wrong message requestId: ', bops.to(message.t), self.requestId.toString(), host, port) - return - } - - // Mark that we've seen this node (the one we received data from) - self.nodes[addr] = true - - var r = message && message.r - - if (r && bops.is(r.nodes)) { - // console.log('got nodes') - parseNodeInfo(r.nodes).forEach(self._handleNode.bind(self)) - } - if (r && is.isArray(r.values)) { - // console.log('got peers') - parsePeerInfo(r.values).forEach(self._handlePeer.bind(self)) - } -} - -DHT.prototype.query = function (addr) { - var self = this - if (Object.keys(self.nodes).length > MAX_NODES) return - - var host = addr.split(':')[0] - var port = Number(addr.split(':')[1]) - self.socket.send(self.message, 0, self.message.length, port, host) -} - -DHT.prototype.findPeers = function (num) { - var self = this - if (!num) num = 1 - - // TODO: keep track of missing nodes for each `findPeers` call separately! - self.missingPeers += num - - while (self.queue.length) { - self.query(self.queue.pop()) - } - - // If we are connected to no nodes after timeout period, then retry with - // the bootstrap nodes. - setTimeout(function () { - if (Object.keys(self.nodes).length === 0) { - console.log('No nodes replied, retry with bootstrap nodes') - self.queue.push.apply(self.queue, BOOTSTRAP_NODES) - self.findPeers(num) - } - }, BOOTSTRAP_TIMEOUT) -} - -DHT.prototype.__defineGetter__('peersFound', function() { - var self = this - return Object.keys(self.peers).length -}) - -DHT.prototype.__defineGetter__('nodesFound', function () { - var self = this - return Object.keys(self.nodes).length -}) diff --git a/lib/bittorrent-dht/package.json b/lib/bittorrent-dht/package.json deleted file mode 100644 index e906554..0000000 --- a/lib/bittorrent-dht/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "bittorrent-dht", - "version": "0.1.1", - "description": "a lightweight, optimized implementation of the BitTorrent DHT", - "dependencies": { - "bncode": "~0.2.3", - "compact2string": "~1.0.0", - "bagpipe": "0.3.0", - "async": "0.2.9" - }, - "readme": "# bittorrent-dht\n\na lightweight implementation of the BitTorrent DHT\n\n", - "readmeFilename": "README.md", - "_id": "bittorrent-dht@0.1.1", - "dist": { - "shasum": "bbe79897a7354e251e0289dfadcc71f17fabc495" - }, - "_resolved": "git://github.com/bmcmahen/bittorrent-dht.git#9d5a6278ac51cdc6a601428747079f7b589740ef", - "_from": "bittorrent-dht@git://github.com/bmcmahen/bittorrent-dht.git" -} diff --git a/package.json b/package.json index 80e5f9c..b3c9488 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "dependencies": { "async": "0.x", "bitfield": "0.x", + "bittorrent-dht": "0.x", "bncode": "0.x", "bops": "0.x", "browserify": "2.x", diff --git a/test/echo/echo.c b/test/echo/echo.c deleted file mode 100644 index 693a07d..0000000 --- a/test/echo/echo.c +++ /dev/null @@ -1,94 +0,0 @@ -/* UDP echo server program -- echo-server-udp.c */ - -#include <stdio.h> /* standard C i/o facilities */ -#include <stdlib.h> /* needed for atoi() */ -#include <unistd.h> /* defines STDIN_FILENO, system calls,etc */ -#include <sys/types.h> /* system data type definitions */ -#include <sys/socket.h> /* socket specific definitions */ -#include <netinet/in.h> /* INET constants and stuff */ -#include <arpa/inet.h> /* IP address conversion stuff */ -#include <netdb.h> /* gethostbyname */ - - - -/* this routine echos any messages (UDP datagrams) received */ - -#define MAXBUF 1024*1024 - -void echo( int sd ) { - int len,n; - char bufin[MAXBUF]; - struct sockaddr_in remote; - - /* need to know how big address struct is, len must be set before the - call to recvfrom!!! */ - - len = sizeof(remote); - - while (1) { - /* read a datagram from the socket (put result in bufin) */ - n=recvfrom(sd,bufin,MAXBUF,0,(struct sockaddr *)&remote,&len); - - /* print out the address of the sender */ - printf("Got a datagram from %s port %d\n", - inet_ntoa(remote.sin_addr), ntohs(remote.sin_port)); - - if (n<0) { - perror("Error receiving data"); - } else { - printf("GOT %d BYTES\n",n); - /* Got something, just send it back */ - sendto(sd,bufin,n,0,(struct sockaddr *)&remote,len); - } - } -} - -/* server main routine */ - -int main() { - int ld; - struct sockaddr_in skaddr; - int length; - - /* create a socket - IP protocol family (PF_INET) - UDP protocol (SOCK_DGRAM) - */ - - if ((ld = socket( PF_INET, SOCK_DGRAM, 0 )) < 0) { - printf("Problem creating socket\n"); - exit(1); - } - - /* establish our address - address family is AF_INET - our IP address is INADDR_ANY (any of our IP addresses) - the port number is assigned by the kernel - */ - - skaddr.sin_family = AF_INET; - skaddr.sin_addr.s_addr = htonl(INADDR_ANY); - skaddr.sin_port = htons(0); - - if (bind(ld, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) { - printf("Problem binding\n"); - exit(0); - } - - /* find out what port we were assigned and print it out */ - - length = sizeof( skaddr ); - if (getsockname(ld, (struct sockaddr *) &skaddr, &length)<0) { - printf("Error getsockname\n"); - exit(1); - } - - /* port number's are network byte order, we have to convert to - host byte order before printing ! - */ - printf("The server UDP port number is %d\n",ntohs(skaddr.sin_port)); - - /* Go echo every datagram we get */ - echo(ld); - return(0); -} |