UNPKG

2.41 kBJavaScriptView Raw
1const socks = require('socks').SocksClient
2const toPull = require('stream-to-pull-stream')
3const debug = require('debug')('multiserver:onion')
4
5module.exports = function Onion(opts) {
6 if (!socks) {
7 // We are in browser
8 debug('onion dialing through socks proxy not supported in browser setting')
9 return {
10 name: 'onion',
11 scope() {
12 return 'public'
13 },
14 parse(s) {
15 return null
16 },
17 }
18 }
19
20 opts = opts || {}
21 const daemonProxyOpts = {
22 ipaddress: '127.0.0.1',
23 port: 9050,
24 type: 5,
25 }
26 const browserProxyOpts = {
27 ipaddress: '127.0.0.1',
28 port: 9150,
29 type: 5,
30 }
31
32 return {
33 name: 'onion',
34 scope: () => opts.scope || 'public',
35 server(onConnection, cb) {
36 cb(new Error('Use net plugin for onion server instead'))
37 },
38 client(opts, cb) {
39 let _socket, destroy
40
41 function tryConnect(connectOpts, onFail) {
42 socks.createConnection(connectOpts, function onConnected(err, result) {
43 if (err) return onFail(err)
44
45 const socket = result.socket
46
47 if (destroy) return socket.destroy()
48 _socket = socket
49
50 const duplexStream = toPull.duplex(socket)
51 duplexStream.address =
52 'onion:' +
53 connectOpts.destination.host +
54 ':' +
55 connectOpts.destination.port
56
57 cb(null, duplexStream)
58
59 // Remember to resume the socket stream.
60 socket.resume()
61 })
62 }
63
64 function connectOpts(proxyOpts) {
65 return {
66 proxy: proxyOpts,
67 command: 'connect',
68 destination: {
69 host: opts.host,
70 port: opts.port,
71 },
72 }
73 }
74
75 tryConnect(connectOpts(daemonProxyOpts), (err) => {
76 tryConnect(connectOpts(browserProxyOpts), (err) => {
77 cb(err)
78 })
79 })
80
81 return function closeOnionClient() {
82 if (_socket) _socket.destroy()
83 else destroy = true
84 }
85 },
86
87 // MUST be onion:<host>:<port>
88 parse(s) {
89 const ary = s.split(':')
90 if (ary.length < 3) return null
91 if ('onion' !== ary.shift()) return null
92 const port = +ary.pop()
93 if (isNaN(port)) return null
94 return {
95 name: 'onion',
96 host: ary.join(':') || 'localhost',
97 port: port,
98 }
99 },
100 stringify(scope) {
101 return null
102 },
103 }
104}