| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var cluster = require('cluster'); | 
					
						
							|  |  |  | var PromiseA = require('bluebird'); | 
					
						
							|  |  |  | var memstore; | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  | var sqlstore; | 
					
						
							| 
									
										
										
										
											2015-11-28 05:06:19 +00:00
										 |  |  | var config; | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | // TODO
 | 
					
						
							|  |  |  | // var rootMasterKey;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateIps() { | 
					
						
							|  |  |  |   console.log('[UPDATE IP]'); | 
					
						
							| 
									
										
										
										
											2015-11-28 05:06:19 +00:00
										 |  |  |   var allMap = {}; | 
					
						
							|  |  |  |   var hostnames = config.redirects.reduce(function (all, redirect) { | 
					
						
							|  |  |  |     if (redirect.ip && !allMap[redirect.id]) { | 
					
						
							|  |  |  |       allMap[redirect.id] = true; | 
					
						
							|  |  |  |       all.push(redirect.id); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return all; | 
					
						
							|  |  |  |   }, []); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   require('./ddns-updater').update( | 
					
						
							|  |  |  |     config.ddns.services | 
					
						
							|  |  |  |   , hostnames | 
					
						
							|  |  |  |   , config.ddns.token | 
					
						
							|  |  |  |   ).then(function (results) { | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |     results.forEach(function (result) { | 
					
						
							|  |  |  |       if (result.error) { | 
					
						
							|  |  |  |         console.error(result); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         console.log('[SUCCESS]', result.service.hostname); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }).error(function (err) { | 
					
						
							|  |  |  |     console.error('[UPDATE IP] ERROR'); | 
					
						
							|  |  |  |     console.error(err); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function init(conf/*, state*/) { | 
					
						
							| 
									
										
										
										
											2015-11-28 05:06:19 +00:00
										 |  |  |   config = conf; | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   if (!conf.ipcKey) { | 
					
						
							|  |  |  |     conf.ipcKey = require('crypto').randomBytes(16).toString('base64'); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |   if (!conf.sqlite3Sock) { | 
					
						
							|  |  |  |     conf.sqlite3Sock = '/tmp/sqlite3.' + require('crypto').randomBytes(4).toString('hex') + '.sock'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!conf.memstoreSock) { | 
					
						
							|  |  |  |     conf.memstoreSock = '/tmp/memstore.' + require('crypto').randomBytes(4).toString('hex') + '.sock'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   try { | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |     require('fs').unlinkSync(conf.memstoreSock); | 
					
						
							|  |  |  |   } catch(e) { | 
					
						
							|  |  |  |     if ('ENOENT' !== e.code) { | 
					
						
							|  |  |  |       console.error(e.stack); | 
					
						
							|  |  |  |       console.error(JSON.stringify(e)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // ignore
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     require('fs').unlinkSync(conf.sqlite3Sock); | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   } catch(e) { | 
					
						
							|  |  |  |     if ('ENOENT' !== e.code) { | 
					
						
							|  |  |  |       console.error(e.stack); | 
					
						
							|  |  |  |       console.error(JSON.stringify(e)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // ignore
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var cstore = require('cluster-store'); | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |   var sqlite3 = require('sqlite3-cluster/server'); | 
					
						
							|  |  |  |   var promise = PromiseA.all([ | 
					
						
							|  |  |  |     cstore.create({ | 
					
						
							|  |  |  |       sock: conf.memstoreSock | 
					
						
							|  |  |  |     , serve: cluster.isMaster && conf.memstoreSock | 
					
						
							|  |  |  |     , store: cluster.isMaster && null //new require('express-session/session/memory')()
 | 
					
						
							|  |  |  |       // TODO implement
 | 
					
						
							|  |  |  |     , key: conf.ipcKey | 
					
						
							|  |  |  |     }).then(function (_memstore) { | 
					
						
							|  |  |  |       memstore = _memstore; | 
					
						
							|  |  |  |       return memstore; | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   , sqlite3.createServer({ | 
					
						
							|  |  |  |       verbose: null | 
					
						
							| 
									
										
										
										
											2015-11-28 05:06:19 +00:00
										 |  |  |     , sock: conf.sqlite3Sock | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |     , ipcKey: conf.ipcKey | 
					
						
							|  |  |  |     }).then(function (_sqlstore) { | 
					
						
							|  |  |  |       sqlstore = _sqlstore; | 
					
						
							|  |  |  |       return sqlstore; | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   ]).then(function (/*args*/) { | 
					
						
							|  |  |  |     return conf; | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       conf: conf | 
					
						
							|  |  |  |     , memstore: memstore // args[0]
 | 
					
						
							|  |  |  |     , sqlstore: sqlstore // args[1]
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     */ | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO check the IP every 5 minutes and update it every hour
 | 
					
						
							|  |  |  |   setInterval(updateIps, 60 * 60 * 1000); | 
					
						
							|  |  |  |   // we don't want this to load right away (extra procesing time)
 | 
					
						
							|  |  |  |   setTimeout(updateIps, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |   return promise; | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function touch(conf, state) { | 
					
						
							|  |  |  |   if (!state.initialize) { | 
					
						
							|  |  |  |     state.initialize = init(conf, state); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TODO if no xyz worker, start on xyz worker (unlock, for example)
 | 
					
						
							|  |  |  |   return state.initialize.then(function () { | 
					
						
							|  |  |  |     // TODO conf.locked = true|false;
 | 
					
						
							|  |  |  |     conf.initialized = true; | 
					
						
							|  |  |  |     return conf; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* | 
					
						
							|  |  |  |   setInterval(function () { | 
					
						
							|  |  |  |     console.log('SIGUSR1 to caddy'); | 
					
						
							|  |  |  |     return caddy.update(caddyConf); | 
					
						
							|  |  |  |   }, 10 * 60 * 1000); | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //var config = require('./device.json');
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // require('ssl-root-cas').inject();
 | 
					
						
							| 
									
										
										
										
											2015-11-12 11:14:59 +00:00
										 |  |  |   // TODO try SNI loopback.example.com as result of api.ipify.com with loopback token
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* | 
					
						
							|  |  |  |   function phoneHome() { | 
					
						
							|  |  |  |     var holepunch = require('./holepunch/beacon'); | 
					
						
							|  |  |  |     var ports; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ports = [ | 
					
						
							|  |  |  |       { private: 65022 | 
					
						
							|  |  |  |       , public: 65022 | 
					
						
							|  |  |  |       , protocol: 'tcp' | 
					
						
							|  |  |  |       , ttl: 0 | 
					
						
							|  |  |  |       , test: { service: 'ssh' } | 
					
						
							|  |  |  |       , testable: false | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     , { private: 650443 | 
					
						
							|  |  |  |       , public: 650443 | 
					
						
							|  |  |  |       , protocol: 'tcp' | 
					
						
							|  |  |  |       , ttl: 0 | 
					
						
							|  |  |  |       , test: { service: 'https' } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     , { private: 65080 | 
					
						
							|  |  |  |       , public: 65080 | 
					
						
							|  |  |  |       , protocol: 'tcp' | 
					
						
							|  |  |  |       , ttl: 0 | 
					
						
							|  |  |  |       , test: { service: 'http' } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO return a middleware
 | 
					
						
							|  |  |  |     holepunch.run(require('./redirects.json').reduce(function (all, redirect) { | 
					
						
							|  |  |  |       if (!all[redirect.from.hostname]) { | 
					
						
							|  |  |  |         all[redirect.from.hostname] = true; | 
					
						
							|  |  |  |         all.push(redirect.from.hostname); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (!all[redirect.to.hostname]) { | 
					
						
							|  |  |  |         all[redirect.to.hostname] = true; | 
					
						
							|  |  |  |         all.push(redirect.to.hostname); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return all; | 
					
						
							|  |  |  |     }, []), ports).catch(function () { | 
					
						
							|  |  |  |       console.error("Couldn't phone home. Oh well"); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports.init = init; | 
					
						
							|  |  |  | module.exports.touch = touch; |