From eda766e48c684fe2a524e77f47cf4fb780e320fd Mon Sep 17 00:00:00 2001 From: tigerbot Date: Tue, 31 Oct 2017 18:10:46 -0600 Subject: [PATCH] moved tunnel client manager into DDNS directory where it's used --- lib/ddns/index.js | 9 ++-- lib/{ => ddns}/tunnel-client-manager.js | 48 +++++++++++++++++- lib/tcp/index.js | 66 +------------------------ 3 files changed, 53 insertions(+), 70 deletions(-) rename lib/{ => ddns}/tunnel-client-manager.js (69%) diff --git a/lib/ddns/index.js b/lib/ddns/index.js index dbcb3c2..dfad146 100644 --- a/lib/ddns/index.js +++ b/lib/ddns/index.js @@ -5,6 +5,7 @@ module.exports.create = function (deps, conf) { var network = deps.PromiseA.promisifyAll(deps.recase.camelCopy(require('network'))); var loopback = require('./loopback').create(deps, conf); var dnsCtrl = require('./dns-ctrl').create(deps, conf); + var tunnelClients = require('./tunnel-client-manager').create(deps, conf); var equal = require('deep-equal'); var loopbackDomain; @@ -44,7 +45,7 @@ module.exports.create = function (deps, conf) { async function startTunnel(tunnelSession, mod, domainList) { try { var dnsSession = await getSession(mod.tokenId); - var tunnelDomain = await deps.tunnelClients.start(tunnelSession || dnsSession, domainList); + var tunnelDomain = await tunnelClients.start(tunnelSession || dnsSession, domainList); var addrList; try { @@ -82,12 +83,12 @@ module.exports.create = function (deps, conf) { tunnelActive = true; } async function disconnectTunnels() { - deps.tunnelClients.disconnect(); + tunnelClients.disconnect(); tunnelActive = false; await Promise.resolve(); } async function checkTunnelTokens() { - var oldTokens = deps.tunnelClients.current(); + var oldTokens = tunnelClients.current(); var newTokens = await iterateAllModules(function checkTokens(mod, domainList) { if (mod.type !== 'dns@oauth3.org') { return null; } @@ -103,7 +104,7 @@ module.exports.create = function (deps, conf) { } }); - await Promise.all(Object.values(oldTokens).map(deps.tunnelClients.remove)); + await Promise.all(Object.values(oldTokens).map(tunnelClients.remove)); if (!newTokens.length) { return; } diff --git a/lib/tunnel-client-manager.js b/lib/ddns/tunnel-client-manager.js similarity index 69% rename from lib/tunnel-client-manager.js rename to lib/ddns/tunnel-client-manager.js index 8153245..01f9290 100644 --- a/lib/tunnel-client-manager.js +++ b/lib/ddns/tunnel-client-manager.js @@ -6,6 +6,52 @@ module.exports.create = function (deps, config) { var activeTunnels = {}; var activeDomains = {}; + var customNet = { + createConnection: function (opts, cb) { + console.log('[gl.tunnel] creating connection'); + + // here "reader" means the socket that looks like the connection being accepted + // here "writer" means the remote-looking part of the socket that driving the connection + var writer; + + function usePair(err, reader) { + if (err) { + process.nextTick(function () { + writer.emit('error', err); + }); + return; + } + + var wrapOpts = Object.assign({localAddress: '127.0.0.2', localPort: 'tunnel-0'}, opts); + wrapOpts.firstChunk = opts.data; + wrapOpts.hyperPeek = !!opts.data; + + // Also override the remote and local address info. We use `defineProperty` because + // otherwise we run into problems of setting properties with only getters defined. + Object.defineProperty(reader, 'remoteAddress', { value: wrapOpts.remoteAddress }); + Object.defineProperty(reader, 'remotePort', { value: wrapOpts.remotePort }); + Object.defineProperty(reader, 'remoteFamiliy', { value: wrapOpts.remoteFamiliy }); + Object.defineProperty(reader, 'localAddress', { value: wrapOpts.localAddress }); + Object.defineProperty(reader, 'localPort', { value: wrapOpts.localPort }); + Object.defineProperty(reader, 'localFamiliy', { value: wrapOpts.localFamiliy }); + + deps.tcp.handler(reader, wrapOpts); + process.nextTick(function () { + // this cb will cause the stream to emit its (actually) first data event + // (even though it already gave a peek into that first data chunk) + console.log('[tunnel] callback, data should begin to flow'); + cb(); + }); + } + + // We used to use `stream-pair` for non-tls connections, but there are places + // that require properties/functions to be present on the socket that aren't + // present on a JSStream so it caused problems. + writer = require('socket-pair').create(usePair); + return writer; + } + }; + function fillData(data) { if (typeof data === 'string') { data = { jwt: data }; @@ -70,7 +116,7 @@ module.exports.create = function (deps, config) { // get the promise that should tell us more about if it worked or not. activeTunnels[data.tunnelUrl] = stunnel.connect({ stunneld: data.tunnelUrl - , net: deps.tunnel.net + , net: customNet // NOTE: the ports here aren't that important since we are providing a custom // `net.createConnection` that doesn't actually use the port. What is important // is that any services we are interested in are listed in this object and have diff --git a/lib/tcp/index.js b/lib/tcp/index.js index d5d88c7..fb69fc9 100644 --- a/lib/tcp/index.js +++ b/lib/tcp/index.js @@ -165,71 +165,6 @@ module.exports.create = function (deps, config) { modules.tls = require('./tls').create(deps, config, modules); modules.http = require('./http').create(deps, config, modules); - deps.tunnel = deps.tunnel || {}; - deps.tunnel.net = { - createConnection: function (opts, cb) { - console.log('[gl.tunnel] creating connection'); - - // here "reader" means the socket that looks like the connection being accepted - // here "writer" means the remote-looking part of the socket that driving the connection - var writer; - var wrapOpts = {}; - - function usePair(err, reader) { - if (err) { - process.nextTick(function () { - writer.emit('error', err); - }); - return; - } - - // this has the normal net/tcp stuff plus our custom stuff - // opts = { address, port, - // hostname, servername, tls, encrypted, data, localAddress, localPort, remoteAddress, remotePort, remoteFamily } - Object.keys(opts).forEach(function (key) { - wrapOpts[key] = opts[key]; - try { - reader[key] = opts[key]; - } catch(e) { - // can't set real socket getters, like remoteAddr - } - }); - - // A few more extra specialty options - wrapOpts.localAddress = wrapOpts.localAddress || '127.0.0.2'; // TODO use the tunnel's external address - wrapOpts.localPort = wrapOpts.localPort || 'tunnel-0'; - try { - reader._remoteAddress = wrapOpts.remoteAddress; - reader._remotePort = wrapOpts.remotePort; - reader._remoteFamily = wrapOpts.remoteFamily; - reader._localAddress = wrapOpts.localAddress; - reader._localPort = wrapOpts.localPort; - reader._localFamily = wrapOpts.localFamily; - } catch(e) { - } - - tcpHandler(reader, wrapOpts); - - process.nextTick(function () { - // this cb will cause the stream to emit its (actually) first data event - // (even though it already gave a peek into that first data chunk) - console.log('[tunnel] callback, data should begin to flow'); - cb(); - }); - } - - wrapOpts.firstChunk = opts.data; - wrapOpts.hyperPeek = !!opts.data; - - // We used to use `stream-pair` for non-tls connections, but there are places - // that require properties/functions to be present on the socket that aren't - // present on a JSStream so it caused problems. - writer = require('socket-pair').create(usePair); - return writer; - } - }; - deps.tunnelClients = require('../tunnel-client-manager').create(deps, config); - function updateListeners() { var current = listeners.list(); var wanted = config.tcp.bind; @@ -297,6 +232,7 @@ module.exports.create = function (deps, config) { var result = { updateConf + , handler: tcpHandler }; Object.defineProperty(result, 'mainPort', {enumerable: true, get: () => mainPort});