holepunch.js/lib/pmp.js

118 lines
2.8 KiB
JavaScript
Raw Normal View History

2015-12-30 08:22:04 +00:00
'use strict';
var PromiseA = require('bluebird');
var natpmp = require('holepunch-nat-pmp');
function getGateway() {
var exec = require('child_process').exec;
var netroute;
var gw;
try {
netroute = require('netroute');
gw = netroute.getGateway();
} catch(e) {
}
if (gw) {
return PromiseA.resolve(gw);
}
return new PromiseA(function (resolve, reject) {
exec('ip route show default', function (err, stdout, stderr) {
var gw;
if (err || stderr) { reject(err || stderr); return; }
// default via 192.168.1.1 dev eth0
gw = stdout.replace(/^default via (\d+\.\d+\.\d+\.\d+) dev[\s\S]+/m, '$1');
console.log('Possible PMP gateway is', gw);
return gw;
});
});
}
function pmpForwardHelper(gw, portInfo) {
return new PromiseA(function (resolve, reject) {
// create a "client" instance connecting to your local gateway
var client = natpmp.connect(gw);
function setPortForward() {
// setup a new port mapping
client.portMapping({
private: portInfo.internal || portInfo.private
|| portInfo.external || portInfo.public
, public: portInfo.external || portInfo.public
|| portInfo.internal || portInfo.private
2015-12-30 08:46:22 +00:00
, ttl: portInfo.ttl || 7200 // 0 // 600
2015-12-30 08:22:04 +00:00
}, function (err, info) {
if (err) {
reject(err);
return;
}
console.log(info);
// {
// type: 'tcp',
// epoch: 8922109,
// private: 22,
// public: 2222,
// ...
// }
resolve();
});
}
// explicitly ask for the current external IP address
2015-12-30 16:48:33 +00:00
// TODO why did I use a setTimeout here? event loop / timing bug?
2015-12-30 08:22:04 +00:00
setTimeout(function () {
client.externalIp(function (err, info) {
2015-12-30 16:48:33 +00:00
console.error('[HP] Error: setTimeout client.externalIp:');
console.error(err.stack);
if (err) { return PromiseA.reject(err); }
2015-12-30 08:22:04 +00:00
console.log('Current external IP address: %s', info.ip.join('.'));
setPortForward();
});
});
});
}
function pmpForward(port) {
return getGateway().then(function (gw) {
return pmpForwardHelper(gw, port);
});
}
module.exports = function (args, ips, portInfo) {
return pmpForward(portInfo);
};
module.exports.pmpForward = pmpForward;
function usage() {
console.warn("");
console.warn("node helpers/pmp-forward [public port] [private port] [ttl]");
console.warn("");
}
function run() {
var pubPort = parseInt(process.argv[2], 10) || 0;
var privPort = parseInt(process.argv[3], 10) || pubPort;
var ttl = parseInt(process.argv[4], 10) || 0;
var options = { public: pubPort, private: privPort, ttl: ttl };
if (!pubPort) {
usage();
return;
}
exports.pmpForward(options).then(function () {
console.log('done');
});
}
if (require.main === module) {
run();
}