changed loopback endpoint to check all ports

This commit is contained in:
tigerbot 2017-06-26 18:12:00 -06:00
parent 000d36e76a
commit f37730c97d
4 changed files with 89 additions and 50 deletions

View File

@ -186,11 +186,11 @@ module.exports.create = function (deps, config) {
return; return;
} }
if (Array.isArray(bindList)) { if (Array.isArray(bindList)) {
bindList.forEach(function (port) { bindList.filter(Number).forEach(function (port) {
tcpPortMap[port] = true; tcpPortMap[port] = true;
}); });
} }
else { else if (Number(bindList)) {
tcpPortMap[bindList] = true; tcpPortMap[bindList] = true;
} }
} }

View File

@ -5,23 +5,37 @@ module.exports.create = function () {
var request = PromiseA.promisify(require('request')); var request = PromiseA.promisify(require('request'));
var pending = {}; var pending = {};
function loopback(session, opts) { function checkPublicAddr(host) {
return request({
method: 'GET'
, url: 'https://'+host+'/api/org.oauth3.tunnel/checkip'
, json: true
}).then(function (result) {
if (!result.body) {
return PromiseA.reject(new Error('No response body in request for public address'));
}
if (result.body.error) {
var err = new Error(result.body.error.message);
return PromiseA.reject(Object.assign(err, result.body.error));
}
console.log(result.body, result.body.address);
return result.body.address;
});
}
function checkSinglePort(host, address, port) {
var crypto = require('crypto'); var crypto = require('crypto');
var token = crypto.randomBytes(8).toString('hex'); var token = crypto.randomBytes(8).toString('hex');
var keyAuth = crypto.randomBytes(32).toString('hex'); var keyAuth = crypto.randomBytes(32).toString('hex');
pending[token] = keyAuth; pending[token] = keyAuth;
var host; var opts = {
if (!opts) { address: address
opts = session; , port: port
host = 'api.oauth3.org'; , token: token
} else { , keyAuthorization: keyAuth
host = 'api.' + ((session.token || {}).aud || 'oauth3.org'); , iat: Date.now()
} };
opts.token = token;
opts.keyAuthorization = keyAuth;
opts.iat = Date.now();
return request({ return request({
method: 'POST' method: 'POST'
@ -29,11 +43,44 @@ module.exports.create = function () {
, json: opts , json: opts
}) })
.then(function (result) { .then(function (result) {
if (result.body.error) { delete pending[token];
var err = new Error(result.body.error.message); if (!result.body) {
return PromiseA.reject(Object.assign(err, result.body.error)); return PromiseA.reject(new Error('No response body in loopback request for port '+port));
} }
return result.body.success; // If the loopback requests don't go to us then there are all kinds of ways it could
// error, but none of them really provide much extra information so we don't do
// anything that will break the PromiseA.all out and mask the other results.
if (result.body.error) {
console.log('error on remote side of port '+port+' loopback', result.body.error);
}
return !!result.body.success;
}, function (err) {
delete pending[token];
throw err;
});
}
function loopback(session) {
var host;
if (!session) {
host = 'api.oauth3.org';
} else {
host = 'api.' + ((session.token || {}).aud || 'oauth3.org');
}
return checkPublicAddr(host).then(function (address) {
console.log('checking to see if', address, 'gets back to us');
var ports = require('./servers').listeners.tcp.list();
return PromiseA.all(ports.map(function (port) {
return checkSinglePort(host, address, port);
}))
.then(function (values) {
var result = {error: null, address: address};
ports.forEach(function (port, ind) {
result[port] = values[ind];
});
return result;
});
}); });
} }

View File

@ -46,20 +46,18 @@ module.exports.addTcpListener = function (port, handler) {
conn.__proto = 'tcp'; conn.__proto = 'tcp';
stat.handler(conn); stat.handler(conn);
}); });
server.on('error', function (e) { server.on('close', function () {
console.log('TCP server on port %d closed', port);
delete serversMap[port]; delete serversMap[port];
});
server.on('error', function (e) {
if (!resolved) { if (!resolved) {
reject(e); reject(e);
return; } else if (handler.onError) {
}
if (handler.onError) {
handler.onError(e); handler.onError(e);
return; } else {
throw e;
} }
throw e;
}); });
server.listen(port, function () { server.listen(port, function () {
@ -75,29 +73,20 @@ module.exports.closeTcpListener = function (port) {
resolve(); resolve();
return; return;
} }
stat.server.on('close', function () { stat.server.once('close', resolve);
// once the clients close too
delete serversMap[port];
if (stat._closing) {
stat._closing(); // resolve
stat._closing = null;
}
stat = null;
});
stat._closing = resolve;
stat.server.close(); stat.server.close();
}); });
}; };
module.exports.destroyTcpListener = function (port) { module.exports.destroyTcpListener = function (port) {
var stat = serversMap[port]; var stat = serversMap[port];
delete serversMap[port]; if (stat) {
stat.server.destroy(); stat.server.destroy();
if (stat._closing) {
stat._closing();
stat._closing = null;
} }
stat = null;
}; };
module.exports.listTcpListeners = function () {
return Object.keys(serversMap).map(Number).filter(Boolean);
};
module.exports.addUdpListener = function (port, handler) { module.exports.addUdpListener = function (port, handler) {
return new PromiseA(function (resolve, reject) { return new PromiseA(function (resolve, reject) {
@ -162,6 +151,9 @@ module.exports.closeUdpListener = function (port) {
stat.server.close(); stat.server.close();
}); });
}; };
module.exports.listUdpListeners = function () {
return Object.keys(dgramMap).map(Number).filter(Boolean);
};
module.exports.listeners = { module.exports.listeners = {
@ -169,9 +161,11 @@ module.exports.listeners = {
add: module.exports.addTcpListener add: module.exports.addTcpListener
, close: module.exports.closeTcpListener , close: module.exports.closeTcpListener
, destroy: module.exports.destroyTcpListener , destroy: module.exports.destroyTcpListener
, list: module.exports.listTcpListeners
} }
, udp: { , udp: {
add: module.exports.addUdpListener add: module.exports.addUdpListener
, close: module.exports.closeUdpListener , close: module.exports.closeUdpListener
, list: module.exports.listUdpListeners
} }
}; };

View File

@ -309,20 +309,18 @@ module.exports.create = function (deps, conf) {
}); });
} }
, loopback: function (req, res) { , loopback: function (req, res) {
if (handleCors(req, res, 'POST')) { if (handleCors(req, res, 'GET')) {
return; return;
} }
isAuthorized(req, res, function () { isAuthorized(req, res, function () {
jsonParser(req, res, function () {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
deps.loopback(req.body) deps.loopback()
.then(function (success) { .then(function (result) {
res.end(JSON.stringify({error: null, success: success})); res.end(JSON.stringify(result));
}, function (err) { }, function (err) {
res.end(JSON.stringify({error: {message: err.message, code: err.code}})) res.end(JSON.stringify({error: {message: err.message, code: err.code}}));
}); });
}); });
});
} }
, paywall_check: function (req, res) { , paywall_check: function (req, res) {
if (handleCors(req, res, 'GET')) { if (handleCors(req, res, 'GET')) {