bittorrent-tracker
Advanced tools
Comparing version 9.17.4 to 9.18.0
@@ -0,1 +1,8 @@ | ||
# [9.18.0](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.4...v9.18.0) (2021-08-20) | ||
### Features | ||
* add proxy support for tracker clients ([#356](https://github.com/webtorrent/bittorrent-tracker/issues/356)) ([ad64dc3](https://github.com/webtorrent/bittorrent-tracker/commit/ad64dc3a68cddccc2c1f05d0d8bb833f2c4860b2)) | ||
## [9.17.4](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.3...v9.17.4) (2021-07-22) | ||
@@ -2,0 +9,0 @@ |
@@ -27,2 +27,3 @@ const debug = require('debug')('bittorrent-tracker:client') | ||
* @param {number} opts.wrtc custom webrtc impl (useful in node.js) | ||
* @param {object} opts.proxyOpts proxy options (useful in node.js) | ||
*/ | ||
@@ -58,2 +59,3 @@ class Client extends EventEmitter { | ||
this._userAgent = opts.userAgent | ||
this._proxyOpts = opts.proxyOpts | ||
@@ -60,0 +62,0 @@ // Support lazy 'wrtc' module initialization |
const arrayRemove = require('unordered-array-remove') | ||
const bencode = require('bencode') | ||
const clone = require('clone') | ||
const compact2string = require('compact2string') | ||
const debug = require('debug')('bittorrent-tracker:http-tracker') | ||
const get = require('simple-get') | ||
const Socks = require('socks') | ||
@@ -113,4 +115,10 @@ const common = require('../common') | ||
const self = this | ||
const u = requestUrl + (!requestUrl.includes('?') ? '?' : '&') + | ||
common.querystringStringify(params) | ||
const parsedUrl = new URL(requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params)) | ||
let agent | ||
if (this.client._proxyOpts) { | ||
agent = parsedUrl.protocol === 'https:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent | ||
if (!agent && this.client._proxyOpts.socksProxy) { | ||
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'https:')) | ||
} | ||
} | ||
@@ -120,3 +128,4 @@ this.cleanupFns.push(cleanup) | ||
let request = get.concat({ | ||
url: u, | ||
url: parsedUrl.toString(), | ||
agent: agent, | ||
timeout: common.REQUEST_TIMEOUT, | ||
@@ -123,0 +132,0 @@ headers: { |
const arrayRemove = require('unordered-array-remove') | ||
const BN = require('bn.js') | ||
const clone = require('clone') | ||
const compact2string = require('compact2string') | ||
@@ -7,2 +8,3 @@ const debug = require('debug')('bittorrent-tracker:udp-tracker') | ||
const randombytes = require('randombytes') | ||
const Socks = require('socks') | ||
@@ -81,24 +83,62 @@ const common = require('../common') | ||
let timeout | ||
// Socket used to connect to the socks server to create a relay, null if socks is disabled | ||
let proxySocket | ||
// Socket used to connect to the tracker or to the socks relay if socks is enabled | ||
let socket | ||
// Contains the host/port of the socks relay | ||
let relay | ||
let transactionId = genTransactionId() | ||
let socket = dgram.createSocket('udp4') | ||
let timeout = setTimeout(() => { | ||
// does not matter if `stopped` event arrives, so supress errors | ||
if (opts.event === 'stopped') cleanup() | ||
else onError(new Error(`tracker request timed out (${opts.event})`)) | ||
timeout = null | ||
}, common.REQUEST_TIMEOUT) | ||
if (timeout.unref) timeout.unref() | ||
const proxyOpts = this.client._proxyOpts && clone(this.client._proxyOpts.socksProxy) | ||
if (proxyOpts) { | ||
if (!proxyOpts.proxy) proxyOpts.proxy = {} | ||
// UDP requests uses the associate command | ||
proxyOpts.proxy.command = 'associate' | ||
if (!proxyOpts.target) { | ||
// This should contain client IP and port but can be set to 0 if we don't have this information | ||
proxyOpts.target = { | ||
host: '0.0.0.0', | ||
port: 0 | ||
} | ||
} | ||
if (proxyOpts.proxy.type === 5) { | ||
Socks.createConnection(proxyOpts, onGotConnection) | ||
} else { | ||
debug('Ignoring Socks proxy for UDP request because type 5 is required') | ||
onGotConnection(null) | ||
} | ||
} else { | ||
onGotConnection(null) | ||
} | ||
this.cleanupFns.push(cleanup) | ||
send(Buffer.concat([ | ||
common.CONNECTION_ID, | ||
common.toUInt32(common.ACTIONS.CONNECT), | ||
transactionId | ||
])) | ||
function onGotConnection (err, s, info) { | ||
if (err) return onError(err) | ||
socket.once('error', onError) | ||
socket.on('message', onSocketMessage) | ||
proxySocket = s | ||
socket = dgram.createSocket('udp4') | ||
relay = info | ||
timeout = setTimeout(() => { | ||
// does not matter if `stopped` event arrives, so supress errors | ||
if (opts.event === 'stopped') cleanup() | ||
else onError(new Error(`tracker request timed out (${opts.event})`)) | ||
timeout = null | ||
}, common.REQUEST_TIMEOUT) | ||
if (timeout.unref) timeout.unref() | ||
send(Buffer.concat([ | ||
common.CONNECTION_ID, | ||
common.toUInt32(common.ACTIONS.CONNECT), | ||
transactionId | ||
]), relay) | ||
socket.once('error', onError) | ||
socket.on('message', onSocketMessage) | ||
} | ||
function cleanup () { | ||
@@ -116,2 +156,6 @@ if (timeout) { | ||
socket = null | ||
if (proxySocket) { | ||
try { proxySocket.close() } catch (err) {} | ||
proxySocket = null | ||
} | ||
} | ||
@@ -134,2 +178,3 @@ if (self.maybeDestroyCleanup) self.maybeDestroyCleanup() | ||
function onSocketMessage (msg) { | ||
if (proxySocket) msg = msg.slice(10) | ||
if (msg.length < 8 || msg.readUInt32BE(4) !== transactionId.readUInt32BE(0)) { | ||
@@ -218,4 +263,9 @@ return onError(new Error('tracker sent invalid transaction id')) | ||
function send (message) { | ||
socket.send(message, 0, message.length, port, hostname) | ||
function send (message, proxyInfo) { | ||
if (proxyInfo) { | ||
const pack = Socks.createUDPFrame({ host: hostname, port: port }, message) | ||
socket.send(pack, 0, pack.length, proxyInfo.port, proxyInfo.host) | ||
} else { | ||
socket.send(message, 0, message.length, port, hostname) | ||
} | ||
} | ||
@@ -240,3 +290,3 @@ | ||
toUInt16(self.client._port) | ||
])) | ||
]), relay) | ||
} | ||
@@ -256,3 +306,3 @@ | ||
infoHash | ||
])) | ||
]), relay) | ||
} | ||
@@ -259,0 +309,0 @@ } |
@@ -0,1 +1,2 @@ | ||
const clone = require('clone') | ||
const debug = require('debug')('bittorrent-tracker:websocket-tracker') | ||
@@ -5,2 +6,3 @@ const Peer = require('simple-peer') | ||
const Socket = require('simple-websocket') | ||
const Socks = require('socks') | ||
@@ -180,3 +182,11 @@ const common = require('../common') | ||
} else { | ||
this.socket = socketPool[this.announceUrl] = new Socket(this.announceUrl) | ||
const parsedUrl = new URL(this.announceUrl) | ||
let agent | ||
if (this.client._proxyOpts) { | ||
agent = parsedUrl.protocol === 'wss:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent | ||
if (!agent && this.client._proxyOpts.socksProxy) { | ||
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'wss:')) | ||
} | ||
} | ||
this.socket = socketPool[this.announceUrl] = new Socket({ url: this.announceUrl, agent: agent }) | ||
this.socket.consumers = 1 | ||
@@ -183,0 +193,0 @@ this.socket.once('connect', this._onSocketConnectBound) |
{ | ||
"name": "bittorrent-tracker", | ||
"description": "Simple, robust, BitTorrent tracker (client & server) implementation", | ||
"version": "9.17.4", | ||
"version": "9.18.0", | ||
"author": { | ||
@@ -17,3 +17,4 @@ "name": "WebTorrent LLC", | ||
"./lib/client/udp-tracker.js": false, | ||
"./server.js": false | ||
"./server.js": false, | ||
"socks": false | ||
}, | ||
@@ -32,2 +33,3 @@ "chromeapp": { | ||
"chrome-dgram": "^3.0.6", | ||
"clone": "^1.0.2", | ||
"compact2string": "^1.4.1", | ||
@@ -47,2 +49,3 @@ "debug": "^4.1.1", | ||
"simple-websocket": "^9.1.0", | ||
"socks": "^1.1.9", | ||
"string2compact": "^1.3.0", | ||
@@ -55,6 +58,6 @@ "unordered-array-remove": "^1.0.2", | ||
"magnet-uri": "6.2.0", | ||
"semantic-release": "17.4.4", | ||
"semantic-release": "17.4.5", | ||
"standard": "*", | ||
"tape": "5.2.2", | ||
"webtorrent-fixtures": "1.7.3", | ||
"tape": "5.3.1", | ||
"webtorrent-fixtures": "1.7.5", | ||
"wrtc": "0.4.7" | ||
@@ -61,0 +64,0 @@ }, |
@@ -68,2 +68,8 @@ # bittorrent-tracker [![ci][ci-image]][ci-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] | ||
var optionalOpts = { | ||
// RTCPeerConnection config object (only used in browser) | ||
rtcConfig: {}, | ||
// User-Agent header for http requests | ||
userAgent: '', | ||
// Custom webrtc impl, useful in node to specify [wrtc](https://npmjs.com/package/wrtc) | ||
wrtc: {}, | ||
getAnnounceOpts: function () { | ||
@@ -79,8 +85,40 @@ // Provide a callback that will be called whenever announce() is called | ||
}, | ||
// RTCPeerConnection config object (only used in browser) | ||
rtcConfig: {}, | ||
// User-Agent header for http requests | ||
userAgent: '', | ||
// Custom webrtc impl, useful in node to specify [wrtc](https://npmjs.com/package/wrtc) | ||
wrtc: {}, | ||
// Proxy config object | ||
proxyOpts: { | ||
// Socks proxy options (used to proxy requests in node) | ||
socksProxy: { | ||
// Configuration from socks module (https://github.com/JoshGlazebrook/socks) | ||
proxy: { | ||
// IP Address of Proxy (Required) | ||
ipaddress: "1.2.3.4", | ||
// TCP Port of Proxy (Required) | ||
port: 1080, | ||
// Proxy Type [4, 5] (Required) | ||
// Note: 4 works for both 4 and 4a. | ||
// Type 4 does not support UDP association relay | ||
type: 5, | ||
// SOCKS 4 Specific: | ||
// UserId used when making a SOCKS 4/4a request. (Optional) | ||
userid: "someuserid", | ||
// SOCKS 5 Specific: | ||
// Authentication used for SOCKS 5 (when it's required) (Optional) | ||
authentication: { | ||
username: "Josh", | ||
password: "somepassword" | ||
} | ||
}, | ||
// Amount of time to wait for a connection to be established. (Optional) | ||
// - defaults to 10000ms (10 seconds) | ||
timeout: 10000 | ||
}, | ||
// NodeJS HTTP agents (used to proxy HTTP and Websocket requests in node) | ||
// Populated with Socks.Agent if socksProxy is provided | ||
httpAgent: {}, | ||
httpsAgent: {} | ||
}, | ||
} | ||
@@ -87,0 +125,0 @@ |
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
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
104996
2371
324
25
+ Addedclone@^1.0.2
+ Addedsocks@^1.1.9
+ Addedclone@1.0.4(transitive)
+ Addedsmart-buffer@1.1.15(transitive)
+ Addedsocks@1.1.10(transitive)