bittorrent-tracker/lib/common-node.js
Feross Aboukhadijeh 0aadcc1cbb Wait up to 1s for pending requests before destroy()
If the user calls:

client.stop()
client.destroy()

We should ensure that the final 'stopped' message reaches the tracker
server, even though the client will not get the response (because they
destroyed the client and no more events will be emitted).

If there are pending requests when destroy() is called, then a 1s timer
is set after which point all requests are forcibly cleaned up. If the
requests complete before the 1s timer fires, then cleanup happens right
away (so we're not stuck waiting for the 1s timer).

So, destroy() can happen one of three ways:

- immediately, if no pending requests exist
- after exactly 1s, if pending requests exist and they don't complete
within 1s
- less than 1s, if pending requests exist and they all complete before
the 1s timer fires
2017-01-20 18:41:28 -08:00

79 lines
2.1 KiB
JavaScript

/**
* Functions/constants needed by both the client and server (but only in node).
* These are separate from common.js so they can be skipped when bundling for the browser.
*/
var Buffer = require('safe-buffer').Buffer
var querystring = require('querystring')
exports.IPV4_RE = /^[\d.]+$/
exports.IPV6_RE = /^[\da-fA-F:]+$/
exports.REMOVE_IPV4_MAPPED_IPV6_RE = /^::ffff:/
exports.CONNECTION_ID = Buffer.concat([ toUInt32(0x417), toUInt32(0x27101980) ])
exports.ACTIONS = { CONNECT: 0, ANNOUNCE: 1, SCRAPE: 2, ERROR: 3 }
exports.EVENTS = { update: 0, completed: 1, started: 2, stopped: 3 }
exports.EVENT_IDS = {
0: 'update',
1: 'completed',
2: 'started',
3: 'stopped'
}
exports.EVENT_NAMES = {
update: 'update',
completed: 'complete',
started: 'start',
stopped: 'stop'
}
/**
* Client request timeout. How long to wait before considering a request to a
* tracker server to have timed out.
*/
exports.REQUEST_TIMEOUT = 15000
/**
* Client destroy timeout. How long to wait before forcibly cleaning up all
* pending requests, open sockets, etc.
*/
exports.DESTROY_TIMEOUT = 1000
function toUInt32 (n) {
var buf = Buffer.allocUnsafe(4)
buf.writeUInt32BE(n, 0)
return buf
}
exports.toUInt32 = toUInt32
/**
* `querystring.parse` using `unescape` instead of decodeURIComponent, since bittorrent
* clients send non-UTF8 querystrings
* @param {string} q
* @return {Object}
*/
exports.querystringParse = function (q) {
var saved = querystring.unescape
querystring.unescape = unescape // global
var ret = querystring.parse(q)
querystring.unescape = saved
return ret
}
/**
* `querystring.stringify` using `escape` instead of encodeURIComponent, since bittorrent
* clients send non-UTF8 querystrings
* @param {Object} obj
* @return {string}
*/
exports.querystringStringify = function (obj) {
var saved = querystring.escape
querystring.escape = escape // global
var ret = querystring.stringify(obj)
ret = ret.replace(/[@*/+]/g, function (char) {
// `escape` doesn't encode the characters @*/+ so we do it manually
return '%' + char.charCodeAt(0).toString(16).toUpperCase()
})
querystring.escape = saved
return ret
}