mirror of
https://github.com/webtorrent/bittorrent-tracker.git
synced 2025-01-18 20:21:36 +00:00
tracker should not modify opts
object, it's passed to all trackers
This commit is contained in:
parent
53c973b4ae
commit
c3abef72ce
14
client.js
14
client.js
@ -23,7 +23,7 @@ inherits(Client, EventEmitter)
|
||||
* @param {Number} port torrent client listening port
|
||||
* @param {Object} torrent parsed torrent
|
||||
* @param {Object} opts options object
|
||||
* @param {Number} opts.numWant number of peers to request
|
||||
* @param {Number} opts.numwant number of peers to request
|
||||
* @param {Number} opts.interval announce interval (in ms)
|
||||
* @param {Number} opts.rtcConfig RTCPeerConnection configuration object
|
||||
* @param {Number} opts.wrtc custom webrtc implementation
|
||||
@ -56,7 +56,7 @@ function Client (peerId, port, torrent, opts) {
|
||||
self._wrtc = opts.wrtc
|
||||
|
||||
// optional
|
||||
self._numWant = opts.numWant || common.DEFAULT_ANNOUNCE_PEERS
|
||||
self._numwant = opts.numwant || common.DEFAULT_ANNOUNCE_PEERS
|
||||
self._intervalMs = opts.interval || common.DEFAULT_ANNOUNCE_INTERVAL
|
||||
|
||||
debug('new client %s', self._infoHashHex)
|
||||
@ -160,6 +160,7 @@ Client.prototype.start = function (opts) {
|
||||
* @param {Object} opts
|
||||
* @param {number=} opts.uploaded
|
||||
* @param {number=} opts.downloaded
|
||||
* @param {number=} opts.numwant
|
||||
* @param {number=} opts.left (if not set, calculated automatically)
|
||||
*/
|
||||
Client.prototype.stop = function (opts) {
|
||||
@ -175,6 +176,7 @@ Client.prototype.stop = function (opts) {
|
||||
* @param {Object} opts
|
||||
* @param {number=} opts.uploaded
|
||||
* @param {number=} opts.downloaded
|
||||
* @param {number=} opts.numwant
|
||||
* @param {number=} opts.left (if not set, calculated automatically)
|
||||
*/
|
||||
Client.prototype.complete = function (opts) {
|
||||
@ -194,6 +196,7 @@ Client.prototype.complete = function (opts) {
|
||||
* @param {Object} opts
|
||||
* @param {number=} opts.uploaded
|
||||
* @param {number=} opts.downloaded
|
||||
* @param {number=} opts.numwant
|
||||
* @param {number=} opts.left (if not set, calculated automatically)
|
||||
*/
|
||||
Client.prototype.update = function (opts) {
|
||||
@ -207,6 +210,7 @@ Client.prototype.update = function (opts) {
|
||||
Client.prototype._announce = function (opts) {
|
||||
var self = this
|
||||
self._trackers.forEach(function (tracker) {
|
||||
// tracker should not modify `opts` object, it's passed to all trackers
|
||||
tracker.announce(opts)
|
||||
})
|
||||
}
|
||||
@ -214,15 +218,13 @@ Client.prototype._announce = function (opts) {
|
||||
/**
|
||||
* Send a scrape request to the trackers.
|
||||
* @param {Object} opts
|
||||
* @param {number=} opts.uploaded
|
||||
* @param {number=} opts.downloaded
|
||||
* @param {number=} opts.left (if not set, calculated automatically)
|
||||
*/
|
||||
Client.prototype.scrape = function (opts) {
|
||||
var self = this
|
||||
debug('send `scrape`')
|
||||
if (!opts) opts = {}
|
||||
self._trackers.forEach(function (tracker) {
|
||||
// tracker should not modify `opts` object, it's passed to all trackers
|
||||
tracker.scrape(opts)
|
||||
})
|
||||
}
|
||||
@ -258,7 +260,7 @@ Client.prototype._defaultAnnounceOpts = function (opts) {
|
||||
var self = this
|
||||
if (!opts) opts = {}
|
||||
|
||||
if (opts.numWant == null) opts.numWant = self._numWant
|
||||
if (opts.numwant == null) opts.numwant = self._numwant
|
||||
|
||||
if (opts.uploaded == null) opts.uploaded = 0
|
||||
if (opts.downloaded == null) opts.downloaded = 0
|
||||
|
@ -45,16 +45,20 @@ function HTTPTracker (client, announceUrl, opts) {
|
||||
HTTPTracker.prototype.announce = function (opts) {
|
||||
var self = this
|
||||
if (self.destroyed) return
|
||||
if (self._trackerId) opts.trackerid = self._trackerId
|
||||
|
||||
if (opts.compact == null) opts.compact = 1
|
||||
if (opts.numwant == null) opts.numwant = self.client._numWant // spec says 'numwant'
|
||||
var params = {
|
||||
numwant: opts.numwant,
|
||||
uploaded: opts.uploaded,
|
||||
downloaded: opts.downloaded,
|
||||
event: opts.event,
|
||||
compact: (opts.compact == null) ? 1 : opts.compact,
|
||||
info_hash: self.client._infoHashBinary,
|
||||
peer_id: self.client._peerIdBinary,
|
||||
port: self.client._port
|
||||
}
|
||||
if (self._trackerId) params.trackerid = self._trackerId
|
||||
|
||||
opts.info_hash = self.client._infoHashBinary
|
||||
opts.peer_id = self.client._peerIdBinary
|
||||
opts.port = self.client._port
|
||||
|
||||
self._request(self._announceUrl, opts, self._onAnnounceResponse.bind(self))
|
||||
self._request(self._announceUrl, params, self._onAnnounceResponse.bind(self))
|
||||
}
|
||||
|
||||
HTTPTracker.prototype.scrape = function (opts) {
|
||||
@ -66,13 +70,15 @@ HTTPTracker.prototype.scrape = function (opts) {
|
||||
return
|
||||
}
|
||||
|
||||
opts.info_hash = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
|
||||
? opts.infoHash.map(function (infoHash) { return infoHash.toString('binary') })
|
||||
var infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
|
||||
? opts.infoHash.map(function (infoHash) {
|
||||
return infoHash.toString('binary')
|
||||
})
|
||||
: (opts.infoHash || self.client._infoHash).toString('binary')
|
||||
|
||||
if (opts.infoHash) delete opts.infoHash
|
||||
|
||||
self._request(self._scrapeUrl, opts, self._onScrapeResponse.bind(self))
|
||||
var params = {
|
||||
info_hash: infoHashes
|
||||
}
|
||||
self._request(self._scrapeUrl, params, self._onScrapeResponse.bind(self))
|
||||
}
|
||||
|
||||
// TODO: Improve this interface
|
||||
@ -95,12 +101,11 @@ HTTPTracker.prototype.destroy = function (cb) {
|
||||
cb(null)
|
||||
}
|
||||
|
||||
HTTPTracker.prototype._request = function (requestUrl, opts, cb) {
|
||||
HTTPTracker.prototype._request = function (requestUrl, params, cb) {
|
||||
var self = this
|
||||
|
||||
var u = requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') +
|
||||
common.querystringStringify(opts)
|
||||
|
||||
common.querystringStringify(params)
|
||||
get.concat(u, function (err, data, res) {
|
||||
if (self.destroyed) return
|
||||
if (err) return self.client.emit('warning', err)
|
||||
|
@ -13,7 +13,6 @@ function parseUdpRequest (msg, rinfo) {
|
||||
transactionId: msg.readUInt32BE(12)
|
||||
}
|
||||
|
||||
// TODO: randomize
|
||||
if (!bufferEqual(params.connectionId, common.CONNECTION_ID)) {
|
||||
throw new Error('received packet with invalid connection id')
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ function parseWebSocketRequest (socket, params) {
|
||||
Number(params.offers && params.offers.length) || 0, // no default - explicit only
|
||||
common.MAX_ANNOUNCE_PEERS
|
||||
)
|
||||
params.compact = -1 // return full peer objects (used for websocket responses)
|
||||
|
||||
return params
|
||||
}
|
||||
|
52
lib/swarm.js
52
lib/swarm.js
@ -15,20 +15,24 @@ Swarm.prototype.announce = function (params, cb) {
|
||||
var self = this
|
||||
var peer = self.peers[params.addr || params.peer_id]
|
||||
|
||||
// Dispatch announce event
|
||||
var fn = '_onAnnounce_' + params.event
|
||||
if (self[fn]) {
|
||||
self[fn](params, peer) // process event
|
||||
|
||||
var peerType = params.compact === undefined ? 'webrtc' : 'addr'
|
||||
cb(null, {
|
||||
complete: self.complete,
|
||||
incomplete: self.incomplete,
|
||||
peers: self._getPeers(params.numwant, peerType)
|
||||
})
|
||||
if (params.event === 'started') {
|
||||
self._onAnnounceStarted(params, peer)
|
||||
} else if (params.event === 'stopped') {
|
||||
self._onAnnounceStopped(params, peer)
|
||||
} else if (params.event === 'completed') {
|
||||
self._onAnnounceCompleted(params, peer)
|
||||
} else if (params.event === 'update') {
|
||||
self._onAnnounceUpdate(params, peer)
|
||||
} else {
|
||||
cb(new Error('invalid event'))
|
||||
return
|
||||
}
|
||||
console.log('FEROSS', params.compact)
|
||||
cb(null, {
|
||||
complete: self.complete,
|
||||
incomplete: self.incomplete,
|
||||
peers: self._getPeers(params.numwant, !!params.socket)
|
||||
})
|
||||
}
|
||||
|
||||
Swarm.prototype.scrape = function (params, cb) {
|
||||
@ -38,7 +42,7 @@ Swarm.prototype.scrape = function (params, cb) {
|
||||
})
|
||||
}
|
||||
|
||||
Swarm.prototype._onAnnounce_started = function (params, peer) {
|
||||
Swarm.prototype._onAnnounceStarted = function (params, peer) {
|
||||
if (peer) {
|
||||
debug('unexpected `started` event from peer that is already in swarm')
|
||||
return this._onAnnounce_update(params, peer) // treat as an update
|
||||
@ -48,14 +52,14 @@ Swarm.prototype._onAnnounce_started = function (params, peer) {
|
||||
else this.incomplete += 1
|
||||
peer = this.peers[params.addr || params.peer_id] = {
|
||||
complete: params.left === 0,
|
||||
ip: params.ip, // only http+udp
|
||||
peerId: params.peer_id, // as hex
|
||||
port: params.port, // only http+udp
|
||||
ip: params.ip, // only http, udp
|
||||
port: params.port, // only http, udp
|
||||
socket: params.socket // only websocket
|
||||
}
|
||||
}
|
||||
|
||||
Swarm.prototype._onAnnounce_stopped = function (params, peer) {
|
||||
Swarm.prototype._onAnnounceStopped = function (params, peer) {
|
||||
if (!peer) {
|
||||
debug('unexpected `stopped` event from peer that is not in swarm')
|
||||
return // do nothing
|
||||
@ -66,7 +70,7 @@ Swarm.prototype._onAnnounce_stopped = function (params, peer) {
|
||||
this.peers[params.addr || params.peer_id] = null
|
||||
}
|
||||
|
||||
Swarm.prototype._onAnnounce_completed = function (params, peer) {
|
||||
Swarm.prototype._onAnnounceCompleted = function (params, peer) {
|
||||
if (!peer) {
|
||||
debug('unexpected `completed` event from peer that is not in swarm')
|
||||
return this._onAnnounce_started(params, peer) // treat as a start
|
||||
@ -81,7 +85,7 @@ Swarm.prototype._onAnnounce_completed = function (params, peer) {
|
||||
peer.complete = true
|
||||
}
|
||||
|
||||
Swarm.prototype._onAnnounce_update = function (params, peer) {
|
||||
Swarm.prototype._onAnnounceUpdate = function (params, peer) {
|
||||
if (!peer) {
|
||||
debug('unexpected `update` event from peer that is not in swarm')
|
||||
return this._onAnnounce_started(params, peer) // treat as a start
|
||||
@ -94,16 +98,14 @@ Swarm.prototype._onAnnounce_update = function (params, peer) {
|
||||
}
|
||||
}
|
||||
|
||||
Swarm.prototype._getPeers = function (numWant, peerType) {
|
||||
Swarm.prototype._getPeers = function (numwant, isWebRTC) {
|
||||
var peers = []
|
||||
var ite = randomIterate(Object.keys(this.peers))
|
||||
while (true) {
|
||||
var peerId = ite()
|
||||
if (peers.length >= numWant || peerId == null) return peers
|
||||
var peerId
|
||||
while ((peerId = ite()) && peers.length < numwant) {
|
||||
var peer = this.peers[peerId]
|
||||
if (peer &&
|
||||
((peerType === 'webrtc' && peer.socket) || (peerType === 'addr' && peer.ip))) {
|
||||
peers.push(peer)
|
||||
}
|
||||
if (!peer) continue
|
||||
if ((isWebRTC && peer.socket) || (!isWebRTC && peer.ip)) peers.push(peer)
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
@ -208,7 +208,6 @@ UDPTracker.prototype._request = function (opts) {
|
||||
}
|
||||
|
||||
function announce (connectionId, opts) {
|
||||
opts = opts || {}
|
||||
transactionId = genTransactionId()
|
||||
|
||||
send(Buffer.concat([
|
||||
@ -217,14 +216,14 @@ UDPTracker.prototype._request = function (opts) {
|
||||
transactionId,
|
||||
self.client._infoHash,
|
||||
self.client._peerId,
|
||||
toUInt64(opts.downloaded || 0),
|
||||
toUInt64(opts.downloaded),
|
||||
opts.left != null ? toUInt64(opts.left) : new Buffer('FFFFFFFFFFFFFFFF', 'hex'),
|
||||
toUInt64(opts.uploaded || 0),
|
||||
common.toUInt32(common.EVENTS[opts.event] || 0),
|
||||
toUInt64(opts.uploaded),
|
||||
common.toUInt32(common.EVENTS[opts.event]),
|
||||
common.toUInt32(0), // ip address (optional)
|
||||
common.toUInt32(0), // key (optional)
|
||||
common.toUInt32(opts.numWant || common.DEFAULT_ANNOUNCE_PEERS),
|
||||
toUInt16(self.client._port || 0)
|
||||
common.toUInt32(opts.numwant),
|
||||
toUInt16(self.client._port)
|
||||
]))
|
||||
}
|
||||
|
||||
|
@ -51,20 +51,23 @@ WebSocketTracker.prototype.announce = function (opts) {
|
||||
return self._socket.once('connect', self.announce.bind(self, opts))
|
||||
}
|
||||
|
||||
opts.info_hash = self.client._infoHashBinary
|
||||
opts.peer_id = self.client._peerIdBinary
|
||||
|
||||
// Limit number of offers (temporarily)
|
||||
// TODO: Limit number of offers (temporarily)
|
||||
// TODO: remove this when we cleanup old RTCPeerConnections cleanly
|
||||
if (opts.numWant > 10) opts.numWant = 10
|
||||
var numwant = Math.min(opts.numwant, 10)
|
||||
|
||||
self._generateOffers(opts.numWant, function (offers) {
|
||||
opts.offers = offers
|
||||
|
||||
if (self._trackerId) {
|
||||
opts.trackerid = self._trackerId
|
||||
self._generateOffers(numwant, function (offers) {
|
||||
var params = {
|
||||
numwant: numwant,
|
||||
uploaded: opts.uploaded || 0,
|
||||
downloaded: opts.downloaded,
|
||||
event: opts.event,
|
||||
info_hash: self.client._infoHashBinary,
|
||||
peer_id: self.client._peerIdBinary,
|
||||
offers: offers
|
||||
}
|
||||
self._send(opts)
|
||||
if (self._trackerId) params.trackerid = self._trackerId
|
||||
|
||||
self._send(params)
|
||||
})
|
||||
}
|
||||
|
||||
@ -252,13 +255,13 @@ WebSocketTracker.prototype._send = function (params) {
|
||||
self._socket.send(message)
|
||||
}
|
||||
|
||||
WebSocketTracker.prototype._generateOffers = function (numWant, cb) {
|
||||
WebSocketTracker.prototype._generateOffers = function (numwant, cb) {
|
||||
var self = this
|
||||
var offers = []
|
||||
debug('generating %s offers', numWant)
|
||||
debug('generating %s offers', numwant)
|
||||
|
||||
// TODO: cleanup dead peers and peers that never get a return offer, from self._peers
|
||||
for (var i = 0; i < numWant; ++i) {
|
||||
for (var i = 0; i < numwant; ++i) {
|
||||
generateOffer()
|
||||
}
|
||||
|
||||
@ -280,8 +283,8 @@ WebSocketTracker.prototype._generateOffers = function (numWant, cb) {
|
||||
}
|
||||
|
||||
function checkDone () {
|
||||
if (offers.length === numWant) {
|
||||
debug('generated %s offers', numWant)
|
||||
if (offers.length === numwant) {
|
||||
debug('generated %s offers', numwant)
|
||||
cb(offers)
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ function testClientAnnounceWithNumWant (t, serverType) {
|
||||
})
|
||||
client2.start()
|
||||
client2.once('update', function () {
|
||||
var client3 = new Client(peerId3, port + 2, parsedTorrent, { numWant: 1 })
|
||||
var client3 = new Client(peerId3, port + 2, parsedTorrent, { numwant: 1 })
|
||||
client3.on('error', function (err) {
|
||||
t.error(err)
|
||||
})
|
||||
@ -228,10 +228,10 @@ function testClientAnnounceWithNumWant (t, serverType) {
|
||||
})
|
||||
}
|
||||
|
||||
test('http: client announce with numWant', function (t) {
|
||||
test('http: client announce with numwant', function (t) {
|
||||
testClientAnnounceWithNumWant(t, 'http')
|
||||
})
|
||||
|
||||
test('udp: client announce with numWant', function (t) {
|
||||
test('udp: client announce with numwant', function (t) {
|
||||
testClientAnnounceWithNumWant(t, 'udp')
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user