launch.js.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>launch.js - Documentation</title>
  6. <script src="scripts/prettify/prettify.js"></script>
  7. <script src="scripts/prettify/lang-css.js"></script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
  13. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  14. </head>
  15. <body>
  16. <input type="checkbox" id="nav-trigger" class="nav-trigger" />
  17. <label for="nav-trigger" class="navicon-button x">
  18. <div class="navicon"></div>
  19. </label>
  20. <label for="nav-trigger" class="overlay"></label>
  21. <nav>
  22. <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ControlServer.html">ControlServer</a><ul class='methods'><li data-type='method'><a href="ControlServer.html#.instance_info">instance_info</a></li><li data-type='method'><a href="ControlServer.html#close">close</a></li><li data-type='method'><a href="ControlServer.html#createDNSServer">createDNSServer</a></li><li data-type='method'><a href="ControlServer.html#createHTTPServer">createHTTPServer</a></li><li data-type='method'><a href="ControlServer.html#createSOCKSServer">createSOCKSServer</a></li><li data-type='method'><a href="ControlServer.html#createTorPool">createTorPool</a></li><li data-type='method'><a href="ControlServer.html#listen">listen</a></li><li data-type='method'><a href="ControlServer.html#listenTcp">listenTcp</a></li><li data-type='method'><a href="ControlServer.html#listenWs">listenWs</a></li></ul></li><li><a href="DNSServer.html">DNSServer</a><ul class='methods'><li data-type='method'><a href="DNSServer.html#listen">listen</a></li></ul></li><li><a href="HTTPServer.html">HTTPServer</a><ul class='methods'><li data-type='method'><a href="HTTPServer.html#listen">listen</a></li></ul></li><li><a href="SOCKSServer.html">SOCKSServer</a><ul class='methods'><li data-type='method'><a href="SOCKSServer.html#listen">listen</a></li></ul></li><li><a href="TorPool.html">TorPool</a><ul class='methods'><li data-type='method'><a href="TorPool.html#add">add</a></li><li data-type='method'><a href="TorPool.html#add_instance_to_group">add_instance_to_group</a></li><li data-type='method'><a href="TorPool.html#add_instance_to_group_at">add_instance_to_group_at</a></li><li data-type='method'><a href="TorPool.html#add_instance_to_group_by_name">add_instance_to_group_by_name</a></li><li data-type='method'><a href="TorPool.html#create">create</a></li><li data-type='method'><a href="TorPool.html#create_instance">create_instance</a></li><li data-type='method'><a href="TorPool.html#exit">exit</a></li><li data-type='method'><a href="TorPool.html#get_config_at">get_config_at</a></li><li data-type='method'><a href="TorPool.html#get_config_by_name">get_config_by_name</a></li><li data-type='method'><a href="TorPool.html#instance_at">instance_at</a></li><li data-type='method'><a href="TorPool.html#instance_by_name">instance_by_name</a></li><li data-type='method'><a href="TorPool.html#instances_by_group">instances_by_group</a></li><li data-type='method'><a href="TorPool.html#new_identites">new_identites</a></li><li data-type='method'><a href="TorPool.html#new_identites_by_group">new_identites_by_group</a></li><li data-type='method'><a href="TorPool.html#new_identity_at">new_identity_at</a></li><li data-type='method'><a href="TorPool.html#new_identity_by_name">new_identity_by_name</a></li><li data-type='method'><a href="TorPool.html#next">next</a></li><li data-type='method'><a href="TorPool.html#next_by_group">next_by_group</a></li><li data-type='method'><a href="TorPool.html#remove">remove</a></li><li data-type='method'><a href="TorPool.html#remove_at">remove_at</a></li><li data-type='method'><a href="TorPool.html#remove_by_name">remove_by_name</a></li><li data-type='method'><a href="TorPool.html#remove_instance_from_group">remove_instance_from_group</a></li><li data-type='method'><a href="TorPool.html#remove_instance_from_group_at">remove_instance_from_group_at</a></li><li data-type='method'><a href="TorPool.html#remove_instance_from_group_by_name">remove_instance_from_group_by_name</a></li><li data-type='method'><a href="TorPool.html#set_config_all">set_config_all</a></li><li data-type='method'><a href="TorPool.html#set_config_at">set_config_at</a></li><li data-type='method'><a href="TorPool.html#set_config_by_group">set_config_by_group</a></li><li data-type='method'><a href="TorPool.html#set_config_by_name">set_config_by_name</a></li><li data-type='method'><a href="TorPool.html#signal_all">signal_all</a></li><li data-type='method'><a href="TorPool.html#signal_at">signal_at</a></li><li data-type='method'><a href="TorPool.html#signal_by_group">signal_by_group</a></li><li data-type='method'><a href="TorPool.html#signal_by_name">signal_by_name</a></li></ul></li><li><a href="TorProcess.html">TorProcess</a><ul class='methods'><li data-type='method'><a href="TorProcess.html#create">create</a></li><li data-type='method'><a href="TorProcess.html#exit">exit</a></li><li data-type='method'><a href="TorProcess.html#get_config">get_config</a></li><li data-type='method'><a href="TorProcess.html#new_identity">new_identity</a></li><li data-type='method'><a href="TorProcess.html#set_config">set_config</a></li><li data-type='method'><a href="TorProcess.html#signal">signal</a></li></ul></li></ul><h3>Modules</h3><ul><li><a href="module-tor-router.html">tor-router</a></li><li><a href="module-tor-router_ControlServer.html">tor-router/ControlServer</a></li><li><a href="module-tor-router_default_config.html">tor-router/default_config</a></li><li><a href="module-tor-router_default_ports.html">tor-router/default_ports</a></li><li><a href="module-tor-router_DNSServer.html">tor-router/DNSServer</a></li><li><a href="module-tor-router_HTTPServer.html">tor-router/HTTPServer</a></li><li><a href="module-tor-router_launch.html">tor-router/launch</a></li><li><a href="module-tor-router_nconf_load_env.html">tor-router/nconf_load_env</a></li><li><a href="module-tor-router_SOCKSServer.html">tor-router/SOCKSServer</a></li><li><a href="module-tor-router_TorPool.html">tor-router/TorPool</a></li><li><a href="module-tor-router_TorProcess.html">tor-router/TorProcess</a></li><li><a href="module-tor-router_winston_silent_logger.html">tor-router/winston_silent_logger</a></li></ul><h3>Events</h3><ul><li><a href="DNSServer.html#event:instance-connection">instance-connection</a></li><li><a href="HTTPServer.html#event:instance-connection">instance-connection</a></li><li><a href="SOCKSServer.html#event:instance-connection">instance-connection</a></li><li><a href="TorPool.html#event:instance_created">instance_created</a></li><li><a href="TorProcess.html#event:control_listen">control_listen</a></li><li><a href="TorProcess.html#event:controller_ready">controller_ready</a></li><li><a href="TorProcess.html#event:dns_listen">dns_listen</a></li><li><a href="TorProcess.html#event:error">error</a></li><li><a href="TorProcess.html#event:process_exit">process_exit</a></li><li><a href="TorProcess.html#event:ready">ready</a></li><li><a href="TorProcess.html#event:socks_listen">socks_listen</a></li></ul><h3>Global</h3><ul><li><a href="global.html#assembleHost">assembleHost</a></li><li><a href="global.html#cleanUp">cleanUp</a></li><li><a href="global.html#env_whitelist">env_whitelist</a></li><li><a href="global.html#logger">logger</a></li><li><a href="global.html#main">main</a></li><li><a href="global.html#nconf">nconf</a></li><li><a href="global.html#REALM">REALM</a></li><li><a href="global.html#setup_nconf_env">setup_nconf_env</a></li><li><a href="global.html#TOR_ROUTER_PROXY_AGENT">TOR_ROUTER_PROXY_AGENT</a></li></ul>
  23. </nav>
  24. <div id="main">
  25. <h1 class="page-title">launch.js</h1>
  26. <section>
  27. <article>
  28. <pre class="prettyprint source linenums"><code>const fs = require('fs');
  29. const { Provider } = require('nconf');
  30. const yargs = require('yargs');
  31. const winston = require('winston')
  32. const Promise = require('bluebird');
  33. const { ControlServer } = require('./');
  34. const default_ports = require('./default_ports');
  35. const package_json = JSON.parse(fs.readFileSync(`${__dirname}/../package.json`, 'utf8'));
  36. /**
  37. * @typedef Host
  38. * @property {string} hostname - The hostname
  39. * @property {number} port - The port
  40. * @private
  41. */
  42. /**
  43. * Extracts the host and port components from a string
  44. * @param {string} host
  45. * @returns {Host}
  46. * @private
  47. */
  48. function extractHost (host) {
  49. if (typeof(host) === 'number')
  50. return { hostname: (typeof(default_ports.default_host) === 'string' ? default_ports.default_host : ''), port: host };
  51. else if (typeof(host) === 'string' &amp;&amp; host.indexOf(':') !== -1)
  52. return { hostname: host.split(':').shift(), port: Number(host.split(':').pop()) };
  53. else
  54. return null;
  55. }
  56. /**
  57. * Takes an object with a hostname and port returns a formatted string
  58. * @param {Host} host
  59. * @returns {string} - Formatted host (e.g. "0.0.0.0:1234")
  60. */
  61. function assembleHost(host) {
  62. return `${typeof(host.hostname) === 'string' ? host.hostname : '' }:${host.port}`;
  63. }
  64. /**
  65. * Main function for the application
  66. * @param {Provider} nconf - Instance of `nconf.Provider` used for configuration.
  67. * @param {Logger} [logger] - Winston logger to be used for logging. If not provided will disable logging.
  68. * @async
  69. * @returns {Promise}
  70. */
  71. async function main(nconf, logger) {
  72. Promise.promisifyAll(nconf);
  73. let instances = nconf.get('instances');
  74. let socks_host = typeof(nconf.get('socksHost')) !== 'boolean' ? extractHost(nconf.get('socksHost')) : nconf.get('socksHost');
  75. let dns_host = typeof(nconf.get('dnsHost')) !== 'boolean' ? extractHost(nconf.get('dnsHost')) : nconf.get('dnsHost');
  76. let http_host = typeof(nconf.get('httpHost')) !== 'boolean' ? extractHost(nconf.get('httpHost')) : nconf.get('httpHost');
  77. let control_host = typeof(nconf.get('controlHost')) !== 'boolean' ? extractHost(nconf.get('controlHost')) : nconf.get('controlHost');
  78. let control_host_ws = typeof(nconf.get('websocketControlHost')) !== 'boolean' ? extractHost(nconf.get('websocketControlHost')) : nconf.get('websocketControlHost');
  79. if (nconf.get('proxyByName') &amp;&amp; nconf.get('proxyByName') === true)
  80. nconf.set('proxyByName', 'individual');
  81. if (typeof(control_host) === 'boolean') {
  82. control_host = extractHost(9077);
  83. nconf.set('controlHost', assembleHost(control_host));
  84. }
  85. if (typeof(control_host_ws) === 'boolean') {
  86. control_host_ws = extractHost(9078);
  87. nconf.set('websocketControlPort', assembleHost(control_host_ws));
  88. }
  89. let control = new ControlServer(nconf, logger);
  90. try {
  91. await control.listenTcp(control_host.port, control_host.hostname);
  92. if (control_host_ws) {
  93. control.listenWs(control_host_ws.port, control_host_ws.hostname);
  94. }
  95. if (socks_host) {
  96. if (typeof(socks_host) === 'boolean') {
  97. socks_host = extractHost(default_ports.socks);
  98. nconf.set('socksHost', assembleHost(socks_host));
  99. }
  100. control.createSOCKSServer(socks_host.port, socks_host.hostname);
  101. }
  102. if (http_host) {
  103. if (typeof(http_host) === 'boolean') {
  104. http_host = extractHost(default_ports.http);
  105. nconf.set('httpHost', assembleHost(http_host));
  106. }
  107. control.createHTTPServer(http_host.port, http_host.hostname);
  108. }
  109. if (dns_host) {
  110. if (typeof(dns_host) === 'boolean') {
  111. dns_host = extractHost(default_ports.dns);
  112. nconf.set('dnsPort', assembleHost(dns_host));
  113. }
  114. control.createDNSServer(dns_host.port, dns_host.hostname);
  115. }
  116. if (instances) {
  117. logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instance(s)...`);
  118. await control.tor_pool.create(instances);
  119. logger.info('[tor]: tor started');
  120. }
  121. } catch (error) {
  122. logger.error(`[global]: error starting application: ${error.stack}`);
  123. process.exit(1);
  124. }
  125. /**
  126. * Kills all tor processes and exits, logging an error if one occurs.
  127. * @function cleanUp
  128. *
  129. * @param {Error} error - Error or exit code
  130. */
  131. const cleanUp = (async (error) => {
  132. let thereWasAnExitError = false;
  133. let { handleError } = this;
  134. try {
  135. await control.tor_pool.exit();
  136. } catch (exitError) {
  137. logger.error(`[global]: error closing tor instances: ${exitError.message}`);
  138. thereWasAnExitError = true;
  139. }
  140. if (error instanceof Error) {
  141. logger.error(`[global]: error shutting down: ${error.message}`);
  142. } else {
  143. error = 0;
  144. }
  145. process.exit(Number(Boolean(error || thereWasAnExitError)));
  146. });
  147. process.title = 'tor-router';
  148. process.on('SIGHUP', () => {
  149. control.tor_pool.new_identites();
  150. });
  151. process.on('exit', cleanUp);
  152. process.on('SIGINT', cleanUp);
  153. process.on('uncaughtException', cleanUp.bind({ handleError: true }));
  154. }
  155. /**
  156. * Instance of `nconf.Provider`
  157. * @type {Provider}
  158. */
  159. let nconf = new Provider();
  160. let argv_config =
  161. yargs
  162. .version(package_json.version)
  163. .usage('Usage: tor-router [arguments]')
  164. .options({
  165. f: {
  166. alias: 'config',
  167. describe: 'Path to a config file to use',
  168. demand: false
  169. },
  170. c: {
  171. alias: 'controlHost',
  172. describe: `Host the control server will bind to, handling TCP connections [default: ${default_ports.default_host}:9077]`,
  173. demand: false
  174. // ,default: 9077
  175. },
  176. w: {
  177. alias: 'websocketControlHost',
  178. describe: 'Host the control server will bind to, handling WebSocket connections. If no hostname is specified will bind to localhost',
  179. demand: false
  180. },
  181. j: {
  182. alias: 'instances',
  183. describe: 'Number of instances using the default config',
  184. demand: false
  185. // ,default: 1
  186. },
  187. s: {
  188. alias: 'socksHost',
  189. describe: 'Host the SOCKS5 Proxy server will bind to. If no hostname is specified will bind to localhost',
  190. demand: false,
  191. // ,default: default_ports.socks
  192. },
  193. d: {
  194. alias: 'dnsHost',
  195. describe: 'Host the DNS Proxy server will bind to. If no hostname is specified will bind to localhost',
  196. demand: false
  197. },
  198. h: {
  199. alias: 'httpHost',
  200. describe: 'Host the HTTP Proxy server will bind to. If no hostname is specified will bind to localhost',
  201. demand: false
  202. },
  203. l: {
  204. alias: 'logLevel',
  205. describe: 'Controls the verbosity of console log output. Default level is "info". Set to "verbose" to see all network traffic logged or "null" to disable logging completely [default: info]',
  206. demand: false
  207. // ,default: "info"
  208. },
  209. p: {
  210. alias: 'parentDataDirectory',
  211. describe: 'Parent directory that will contain the data directories for the instances',
  212. demand: false
  213. },
  214. b: {
  215. alias: "loadBalanceMethod",
  216. describe: 'Method that will be used to sort the instances between each request. Currently supports "round_robin" and "weighted". [default: round_robin]',
  217. demand: false
  218. },
  219. t: {
  220. alias: "torPath",
  221. describe: "Provide the path for the Tor executable that will be used",
  222. demand: false
  223. },
  224. n: {
  225. alias: 'proxyByName',
  226. describe: 'Allow connecting to a specific instance identified by the username field when connecting to a proxy',
  227. demand: false
  228. }
  229. });
  230. require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
  231. nconf
  232. .argv(argv_config);
  233. let nconf_config = nconf.get('config');
  234. if (nconf_config) {
  235. if (!require('fs').existsSync(nconf_config)) {
  236. console.error(`[global]: config file "${nconf_config}" does not exist. exiting.`);
  237. process.exit(1);
  238. }
  239. nconf.file(nconf_config);
  240. } else {
  241. nconf.use('memory');
  242. }
  243. nconf.defaults(require(`${__dirname}/../src/default_config.js`));
  244. let logLevel = nconf.get('logLevel');
  245. /**
  246. * Instnace of `winston.Logger`
  247. * @type {Logger}
  248. */
  249. let logger = winston.createLogger({
  250. level: logLevel,
  251. format: winston.format.simple(),
  252. silent: (logLevel === 'null'),
  253. transports: [ new (winston.transports.Console)({ level: (logLevel !== 'null' ? logLevel : void(0)), silent: (logLevel === 'null') }) ]
  254. });
  255. /**
  256. * Exports the main function for the application, a configured `nconf.Provider` instance and a winston logger
  257. * @module tor-router/launch
  258. */
  259. module.exports = { main, nconf, logger };</code></pre>
  260. </article>
  261. </section>
  262. </div>
  263. <br class="clear">
  264. <footer>
  265. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Tue Sep 25 2018 12:53:23 GMT-0400 (Eastern Daylight Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
  266. </footer>
  267. <script>prettyPrint();</script>
  268. <script src="scripts/linenumber.js"></script>
  269. </body>
  270. </html>