Skip to content

Commit 889b5a1

Browse files
committed
Provide http and https agents for proxy.
Change proxy options structure and auto populate socks HTTP agents.
1 parent 7f738ae commit 889b5a1

File tree

6 files changed

+77
-35
lines changed

6 files changed

+77
-35
lines changed

README.md

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,43 @@ var optionalOpts = {
7373
customParam: 'blah' // custom parameters supported
7474
}
7575
},
76-
// NodeJS HTTP agent implementation (used to proxy HTTP and Websocket requests in node)
77-
httpAgent: {},
78-
// Socks proxy options (used to proxy UDP requests in node)
79-
socksProxyOpts: {
80-
// Configuration from socks module (https://github.com/JoshGlazebrook/socks)
81-
proxy: {
82-
// IP Address of Proxy (Required)
83-
ipaddress: "1.2.3.4",
84-
// TCP Port of Proxy (Required)
85-
port: 1080,
86-
// Proxy Type 5 (Required)
87-
// Type 4 does not support UDP association relay
88-
type: 5,
8976

90-
// Authentication used for SOCKS 5 (when it's required) (Optional)
91-
authentication: {
92-
username: "Josh",
93-
password: "somepassword"
94-
}
95-
}
77+
proxyOpts: {
78+
// Socks proxy options (used to proxy requests in node)
79+
socksProxyOpts: {
80+
// Configuration from socks module (https://github.com/JoshGlazebrook/socks)
81+
proxy: {
82+
// IP Address of Proxy (Required)
83+
ipaddress: "1.2.3.4",
84+
// TCP Port of Proxy (Required)
85+
port: 1080,
86+
// Proxy Type [4, 5] (Required)
87+
// Note: 4 works for both 4 and 4a.
88+
// Type 4 does not support UDP association relay
89+
type: 5,
90+
91+
// SOCKS 4 Specific:
92+
93+
// UserId used when making a SOCKS 4/4a request. (Optional)
94+
userid: "someuserid",
95+
96+
// SOCKS 5 Specific:
97+
98+
// Authentication used for SOCKS 5 (when it's required) (Optional)
99+
authentication: {
100+
username: "Josh",
101+
password: "somepassword"
102+
}
103+
},
104+
105+
// Amount of time to wait for a connection to be established. (Optional)
106+
// - defaults to 10000ms (10 seconds)
107+
timeout: 10000
108+
},
109+
// NodeJS HTTP agents (used to proxy HTTP and Websocket requests in node)
110+
// Populated with Socks.Agent if socksProxyOpts is provided
111+
httpAgent: {},
112+
httpsAgent: {}
96113
}
97114
}
98115

client.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var inherits = require('inherits')
88
var once = require('once')
99
var parallel = require('run-parallel')
1010
var Peer = require('simple-peer')
11+
var Socks = require('socks')
1112
var uniq = require('uniq')
1213
var url = require('url')
1314

@@ -31,8 +32,7 @@ inherits(Client, EventEmitter)
3132
* @param {function} opts.getAnnounceOpts callback to provide data to tracker
3233
* @param {number} opts.rtcConfig RTCPeerConnection configuration object
3334
* @param {number} opts.wrtc custom webrtc impl (useful in node.js)
34-
* @param {object} opts.httpAgent HTTP agent impl (used to proxy http requests in node.js)
35-
* @param {object} opts.socksProxyOpts socks proxy options (used to proxy UDP requests in node.js)
35+
* @param {object} opts.proxyOpts proxy options (useful in node.js)
3636
*/
3737
function Client (opts) {
3838
var self = this
@@ -64,9 +64,16 @@ function Client (opts) {
6464

6565
self._rtcConfig = opts.rtcConfig
6666
self._wrtc = opts.wrtc
67-
self._httpAgent = opts.httpAgent
68-
self._socksProxyOpts = opts.socksProxyOpts
6967
self._getAnnounceOpts = opts.getAnnounceOpts
68+
self._proxyOpts = opts.proxyOpts
69+
70+
// Create HTTP agents from socks proxy if needed
71+
if (self._proxyOpts && self._proxyOpts.socksProxy && !self._proxyOpts.httpAgent) {
72+
self._proxyOpts.httpAgent = new Socks.Agent(self._proxyOpts.socksProxy, false)
73+
}
74+
if (self._proxyOpts && self._proxyOpts.socksProxy && !self._proxyOpts.httpsAgent) {
75+
self._proxyOpts.httpsAgent = new Socks.Agent(self._proxyOpts.socksProxy, true)
76+
}
7077

7178
debug('new client %s', self.infoHash)
7279

lib/client/http-tracker.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var debug = require('debug')('bittorrent-tracker:http-tracker')
66
var extend = require('xtend')
77
var get = require('simple-get')
88
var inherits = require('inherits')
9+
var url = require('url')
910

1011
var common = require('../common')
1112
var Tracker = require('./tracker')
@@ -87,9 +88,15 @@ HTTPTracker.prototype.destroy = function (cb) {
8788

8889
HTTPTracker.prototype._request = function (requestUrl, params, cb) {
8990
var self = this
91+
var parsedUrl = url.parse(requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params))
92+
var agent
93+
if (self.client._proxyOpts) {
94+
agent = parsedUrl.protocol === 'https:'
95+
? self.client._proxyOpts.httpsAgent : self.client._proxyOpts.httpAgent
96+
}
9097
var u = {
91-
url: requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params),
92-
agent: self.client._httpAgent
98+
url: parsedUrl,
99+
agent: agent
93100
}
94101

95102
get.concat(u, function (err, res, data) {

lib/client/udp-tracker.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,23 @@ UDPTracker.prototype._request = function (opts) {
7575
// Contains the host/port of the socks relay
7676
var relay
7777
var transactionId = genTransactionId()
78-
if (self.client._socksProxyOpts) {
79-
if (!self.client._socksProxyOpts.proxy) {
80-
self.client._socksProxyOpts.proxy = {}
78+
79+
var proxyOpts = self.client._proxyOpts && self.client._proxyOpts.socksProxy
80+
if (proxyOpts) {
81+
if (!proxyOpts.proxy) {
82+
proxyOpts.proxy = {}
8183
}
8284
// UDP requests uses the associate command
83-
self.client._socksProxyOpts.proxy.command = 'associate'
84-
if (!self.client._socksProxyOpts.target) {
85+
proxyOpts.proxy.command = 'associate'
86+
if (!proxyOpts.target) {
8587
// This should contain client IP and port but can be set to 0 if we don't have this information
86-
self.client._socksProxyOpts.target = {
88+
proxyOpts.target = {
8789
host: '0.0.0.0',
8890
port: 0
8991
}
9092
}
9193

92-
Socks.createConnection(self.client._socksProxyOpts, onGotConnection)
94+
Socks.createConnection(proxyOpts, onGotConnection)
9395
} else {
9496
onGotConnection(null)
9597
}
@@ -141,7 +143,7 @@ UDPTracker.prototype._request = function (opts) {
141143

142144
function onSocketMessage (msg) {
143145
if (self.destroyed) return
144-
if (self.client._socksProxyOpts) msg = msg.slice(10)
146+
if (proxySocket) msg = msg.slice(10)
145147
if (msg.length < 8 || msg.readUInt32BE(4) !== transactionId.readUInt32BE(0)) {
146148
return onError(new Error('tracker sent invalid transaction id'))
147149
}

lib/client/websocket-tracker.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var hat = require('hat')
66
var inherits = require('inherits')
77
var Peer = require('simple-peer')
88
var Socket = require('simple-websocket')
9+
var url = require('url')
910

1011
var common = require('../common')
1112
var Tracker = require('./tracker')
@@ -167,7 +168,13 @@ WebSocketTracker.prototype._openSocket = function () {
167168
if (self.socket) {
168169
socketPool[self.announceUrl].consumers += 1
169170
} else {
170-
self.socket = socketPool[self.announceUrl] = new Socket(self.announceUrl, { agent: self.client._httpAgent })
171+
var parsedUrl = url.parse(self.announceUrl)
172+
var agent
173+
if (self.client._proxyOpts) {
174+
agent = parsedUrl.protocol === 'wss:'
175+
? self.client._proxyOpts.httpsAgent : self.client._proxyOpts.httpAgent
176+
}
177+
self.socket = socketPool[self.announceUrl] = new Socket(self.announceUrl, { agent: agent })
171178
self.socket.consumers = 1
172179
self.socket.on('connect', self._onSocketConnectBound)
173180
}

test/client.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,9 @@ function testClientStartHttpAgent (t, serverType) {
399399
peerId: peerId1,
400400
port: port,
401401
wrtc: {},
402-
httpAgent: agent
402+
proxyOpts: {
403+
httpAgent: agent
404+
}
403405
})
404406

405407
if (serverType === 'ws') common.mockWebsocketTracker(client)

0 commit comments

Comments
 (0)