/
torrent-manager.js
146 lines (120 loc) · 3.67 KB
/
torrent-manager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
module.exports = TorrentManager
var $ = require('jquery')
var async = require('async')
var DHT = require('bittorrent-dht')
var EventEmitter = require('events').EventEmitter
var hat = require('hat')
var inherits = require('inherits')
var portfinder = require('chrome-portfinder')
var Torrent = require('./torrent')
var MAX_PEERS = 200
portfinder.basePort = Math.floor(Math.random() * 60000) + 1025 // >1024
inherits(TorrentManager, EventEmitter)
function TorrentManager () {
var self = this
if (!(self instanceof TorrentManager)) return new TorrentManager()
EventEmitter.call(self)
// TODO: should these ids be consistent between restarts?
self.peerId = new Buffer('-WW0001-' + hat(48), 'utf8')
self.nodeId = new Buffer(hat(160), 'hex')
self.torrents = []
self.dht = new DHT({ nodeId: self.nodeId })
self._reemitEvents(self.dht, 'dht', ['node', 'peer'])
self.dht.on('peer', function (addr, infoHash) {
var torrent = self.getTorrent(infoHash)
torrent.addPeer(addr)
})
self.ready = false
self._installWindowEvents()
async.auto({
dhtPort: function (cb) {
portfinder.getPort(cb)
},
torrentPort: function (cb) {
portfinder.getPort(cb)
}
}, function (err, r) {
self.dhtPort = r.dhtPort
self.torrentPort = r.torrentPort
self.dht.listen(self.dhtPort, function () {
self.ready = true
self.emit('ready')
})
})
}
Object.defineProperty(TorrentManager.prototype, 'ratio', {
get: function () {
var self = this
var uploaded = self.torrents.reduce(function (total, torrent) {
return total + torrent.uploaded
}, 0)
var downloaded = self.torrents.reduce(function (total, torrent) {
return total + torrent.downloaded
}, 0)
if (downloaded === 0) return 0
return uploaded / downloaded
}
})
TorrentManager.prototype.getTorrent = function (infoHash) {
var self = this
var index
for (var i = 0, len = self.torrents.length; i < len; i += 1) {
var torrent = self.torrents[i]
if (torrent.infoHash === infoHash)
return torrent
}
return null
}
TorrentManager.prototype.add = function (uri) {
var self = this
if (!self.ready)
return self.once('ready', self.add.bind(self, uri))
var torrent = new Torrent(uri, {
peerId: self.peerId,
torrentPort: self.torrentPort,
dhtPort: self.dhtPort
})
self.torrents.push(torrent)
self._reemitEvents(torrent, 'torrent', ['listening'])
self.emit('addTorrent', torrent)
torrent.on('listening', function (port) {
console.log('Swarm listening on port ' + port)
// TODO: Add the torrent to the public DHT so peers know to find up
})
torrent.on('error', function (err) {
self.emit('error', err)
})
self.dht.setInfoHash(torrent.infoHash)
self.dht.findPeers(MAX_PEERS) // TODO: should the DHT be concerned with max peers?
}
TorrentManager.prototype._reemitEvents = function (obj, eventPrefix, events) {
var self = this
events.forEach(function (event) {
obj.on(event, function () {
var args = Array.prototype.slice.call(arguments)
args.unshift(eventPrefix + ':' + event, obj)
self.emit.apply(self, args)
})
})
}
TorrentManager.prototype._installWindowEvents = function () {
var self = this
var appWindow
// TODO: on add/remove torrent call resizeTo to set window size
chrome.app.runtime.onLaunched.addListener(function () {
chrome.app.window.create('app.html', {
bounds: {
width: 500,
height: 600
},
frame: 'none',
id: 'app',
minWidth: 350,
minHeight: 165
}, function (_appWindow) {
appWindow = _appWindow
appWindow.contentWindow.name = 'app'
appWindow.contentWindow.torrentManager = self
})
})
}