'use strict'; module.exports.create = function (deps, conf) { var network = deps.PromiseA.promisify(deps.recase.camelCopy(require('network'))); var loopback = require('./loopback').create(deps, conf); var dnsCtrl = require('./dns-ctrl').create(deps, conf); var localAddr, gateway; var tunnelActive = false; async function checkNetworkEnv() { // Since we can't detect the OS level events when a user plugs in an ethernet cable to recheck // what network environment we are in we check our local network address and the gateway to // determine if we need to run the loopback check and router configuration again. var gw = await network.getGatewayIpAsync(); var addr = await network.getPrivateIpAsync(); if (localAddr === addr && gateway === gw) { return; } localAddr = addr; gateway = gw; var loopResult = await loopback('seth.daplie.me'); var notLooped = Object.keys(loopResult.ports).filter(function (port) { return !loopResult.ports[port]; }); // if (notLooped.length) { // // TODO: try to automatically configure router to forward ports to us. // } // If we are on a public accress or all ports we are listening on are forwarded to us then // we don't need the tunnel and we can set the DNS records for all our domains to our public // address. Otherwise we need to use the tunnel to accept traffic. if (!notLooped.length) { if (tunnelActive) { deps.tunnelClients.disconnect(); tunnelActive = false; } } else { if (!tunnelActive) { var session = await getSession(); await deps.tunnelClients.start(session, conf.dns.domains); tunnelActive = true; } } } async function getSession() { var sessions = await deps.storage.owners.all(); var session = sessions.filter(function (sess) { return sess.token.scp.indexOf('dns') >= 0; })[0]; if (!session) { throw new Error('no sessions with DNS grants'); } // The OAUTH3 library stores some things on the root session object that we usually // just leave inside the token, but we need to pull those out before we use it here session.provider_uri = session.provider_uri || session.token.provider_uri || session.token.iss; session.client_uri = session.client_uri || session.token.azp; session.scope = session.scope || session.token.scp; return session; } var publicAddress; async function recheckPubAddr() { if (!conf.ddns.enabled) { return; } await checkNetworkEnv(); if (tunnelActive) { return; } var session = await getSession(); var directives = await deps.OAUTH3.discover(session.token.aud); var addr = await loopback.checkPublicAddr(directives.api); if (publicAddress === addr) { return; } if (conf.debug) { console.log('previous public address',publicAddress, 'does not match current public address', addr); } await dnsCtrl.setDeviceAddress(session, addr, conf.ddns.domains); publicAddress = addr; } recheckPubAddr(); setInterval(recheckPubAddr, 5*60*1000); return { loopbackServer: loopback.server , setDeviceAddress: dnsCtrl.setDeviceAddress , getDeviceAddresses: dnsCtrl.getDeviceAddresses , recheckPubAddr: recheckPubAddr }; };