Comparing version 0.2.11 to 1.0.0
@@ -1,3 +0,3 @@ | ||
var nat = require('../nat-upnp'), | ||
async = require('async'); | ||
var nat = require('../nat-upnp'); | ||
var async = require('async'); | ||
@@ -9,3 +9,3 @@ var client = exports; | ||
this.timeout = 1800; | ||
}; | ||
} | ||
@@ -39,12 +39,12 @@ client.create = function create() { | ||
gateway.run('AddPortMapping', [ | ||
['NewRemoteHost', ports.remote.host], | ||
['NewExternalPort', ports.remote.port], | ||
['NewProtocol', options.protocol ? | ||
options.protocol.toUpperCase() : 'TCP'], | ||
['NewInternalPort', ports.internal.port], | ||
['NewInternalClient', ports.internal.host || address], | ||
['NewEnabled', 1], | ||
['NewPortMappingDescription', options.description || 'node:nat:upnp'], | ||
['NewLeaseDuration', typeof options.ttl === 'number' ? | ||
options.ttl : 60 * 30] | ||
[ 'NewRemoteHost', ports.remote.host ], | ||
[ 'NewExternalPort', ports.remote.port ], | ||
[ 'NewProtocol', options.protocol ? | ||
options.protocol.toUpperCase() : 'TCP' ], | ||
[ 'NewInternalPort', ports.internal.port ], | ||
[ 'NewInternalClient', ports.internal.host || address ], | ||
[ 'NewEnabled', 1 ], | ||
[ 'NewPortMappingDescription', options.description || 'node:nat:upnp' ], | ||
[ 'NewLeaseDuration', typeof options.ttl === 'number' ? | ||
options.ttl : 60 * 30 ] | ||
], callback); | ||
@@ -57,3 +57,3 @@ }); | ||
this.findGateway(function(err, gateway, address) { | ||
this.findGateway(function(err, gateway/*, address*/) { | ||
if (err) return callback(err); | ||
@@ -64,6 +64,6 @@ | ||
gateway.run('DeletePortMapping', [ | ||
['NewRemoteHost', ports.remote.host], | ||
['NewExternalPort', ports.remote.port], | ||
['NewProtocol', options.protocol ? | ||
options.protocol.toUpperCase() : 'TCP'] | ||
[ 'NewRemoteHost', ports.remote.host ], | ||
[ 'NewExternalPort', ports.remote.port ], | ||
[ 'NewProtocol', options.protocol ? | ||
options.protocol.toUpperCase() : 'TCP' ] | ||
], callback); | ||
@@ -83,5 +83,5 @@ }); | ||
if (err) return callback(err); | ||
var i = 0, | ||
end = false, | ||
results = []; | ||
var i = 0; | ||
var end = false; | ||
var results = []; | ||
@@ -92,3 +92,3 @@ async.whilst(function() { | ||
gateway.run('GetGenericPortMappingEntry', [ | ||
['NewPortMappingIndex', ++i] | ||
[ 'NewPortMappingIndex', ++i ] | ||
], function(err, data) { | ||
@@ -120,3 +120,3 @@ if (err) { | ||
protocol: data.NewProtocol.toLowerCase(), | ||
enabled: data.NewEnabled == 1, | ||
enabled: data.NewEnabled === 1, | ||
description: data.NewPortMappingDescription, | ||
@@ -151,3 +151,3 @@ ttl: parseInt(data.NewLeaseDuration, 10) | ||
callback(null, results); | ||
}) | ||
}); | ||
}); | ||
@@ -157,3 +157,3 @@ }; | ||
Client.prototype.externalIp = function externalIp(callback) { | ||
this.findGateway(function(err, gateway, address) { | ||
this.findGateway(function(err, gateway/*, address*/) { | ||
if (err) return callback(err); | ||
@@ -178,5 +178,5 @@ gateway.run('GetExternalIPAddress', [], function(err, data) { | ||
Client.prototype.findGateway = function findGateway(callback) { | ||
var timeout, | ||
timeouted = false, | ||
p = this.ssdp.search( | ||
var timeout; | ||
var timeouted = false; | ||
var p = this.ssdp.search( | ||
'urn:schemas-upnp-org:device:InternetGatewayDevice:1' | ||
@@ -191,3 +191,3 @@ ); | ||
p.on('device', function(info, address) { | ||
p.on('device', function (info, address) { | ||
if (timeouted) return; | ||
@@ -194,0 +194,0 @@ p.emit('end'); |
@@ -1,14 +0,12 @@ | ||
var dgram = require('dgram'), | ||
util = require('util'), | ||
os = require('os'), | ||
net = require('net'), | ||
netroute = require('netroute'), | ||
ip = require('ip'), | ||
EventEmitter = require('events').EventEmitter; | ||
var dgram = require('dgram'); | ||
var util = require('util'); | ||
var os = require('os'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var ssdp = exports; | ||
function Ssdp() { | ||
function Ssdp(opts) { | ||
EventEmitter.call(this); | ||
this._opts = opts || {}; | ||
this._sourcePort = this._opts.sourcePort || 0; | ||
this.multicast = '239.255.255.250'; | ||
@@ -23,3 +21,3 @@ this.port = 1900; | ||
this.createSockets(); | ||
}; | ||
} | ||
util.inherits(Ssdp, EventEmitter); | ||
@@ -31,5 +29,17 @@ | ||
Ssdp.parseMimeHeader = function (headerStr) { | ||
var lines = headerStr.split(/\r\n/g); | ||
// Parse headers from lines to hashmap | ||
return lines.reduce(function(headers, line) { | ||
line.replace(/^([^:]*)\s*:\s*(.*)$/, function (a, key, value) { | ||
headers[key.toLowerCase()] = value; | ||
}); | ||
return headers; | ||
}, {}); | ||
}; | ||
Ssdp.prototype.createSockets = function createSockets() { | ||
var self = this, | ||
interfaces = os.networkInterfaces(); | ||
var self = this; | ||
var interfaces = os.networkInterfaces(); | ||
@@ -62,4 +72,4 @@ this.sockets = Object.keys(interfaces).reduce(function(a, key) { | ||
var self = this, | ||
query = new Buffer('M-SEARCH * HTTP/1.1\r\n' + | ||
var self = this; | ||
var query = new Buffer('M-SEARCH * HTTP/1.1\r\n' + | ||
'HOST: ' + this.multicast + ':' + this.port + '\r\n' + | ||
@@ -93,4 +103,4 @@ 'MAN: "ssdp:discover"\r\n' + | ||
Ssdp.prototype.createSocket = function createSocket(interface) { | ||
var self = this, | ||
socket = dgram.createSocket(interface.family === 'IPv4' ? | ||
var self = this; | ||
var socket = dgram.createSocket(interface.family === 'IPv4' ? | ||
'udp4' : 'udp6'); | ||
@@ -110,9 +120,7 @@ | ||
function onready() { | ||
if (self._boundCount === self.sockets.length) return; | ||
if (self._boundCount < self.sockets.length) return; | ||
self._bound = true; | ||
self._queue.forEach(function(item) { | ||
if (item.action === 'search') { | ||
return self.search(item.device, item.promise); | ||
} | ||
return self[item.action](item.device, item.promise); | ||
}); | ||
@@ -122,3 +130,3 @@ } | ||
socket.on('listening', function() { | ||
self._boundCount++; | ||
self._boundCount += 1; | ||
onready(); | ||
@@ -134,3 +142,3 @@ }); | ||
socket.address = interface.address; | ||
socket.bind(self.port, interface.address); | ||
socket.bind(self._sourcePort, interface.address); | ||
}); | ||
@@ -141,66 +149,15 @@ | ||
// TODO create separate logic for parsing unsolicited upnp broadcasts, | ||
// if and when that need arises | ||
Ssdp.prototype.parseResponse = function parseResponse(response, addr, remote) { | ||
response = response.split(/\r\n/g); | ||
var status = response[0], | ||
headers = response.slice(1); | ||
// Ignore incorrect packets | ||
if (!/^(HTTP|NOTIFY)/.test(status)) return; | ||
if (!/^(HTTP|NOTIFY)/m.test(response)) return; | ||
// Parse headers from lines to hashmap | ||
headers = headers.reduce(function(headers, line) { | ||
line.replace(/^([^:]*)\s*:\s*(.*)$/, function(a, key, value) { | ||
headers[key.toLowerCase()] = value; | ||
}); | ||
return headers; | ||
}, {}); | ||
var headers = Ssdp.parseMimeHeader(response); | ||
// We do not have interest in headers without location | ||
if (!headers.location) return; | ||
// We are only interested in messages that can be matched against the original | ||
// search target | ||
if (!headers.st) return; | ||
var interfaces = os.networkInterfaces(), | ||
routes = netroute.getInfo(), | ||
local; | ||
local = routes.IPv4.concat(routes.IPv6).filter(function(route) { | ||
if (route.gateway) { | ||
if (ip.isEqual(remote.address, route.gateway)) return true; | ||
} | ||
// Remove /24 part from address | ||
if (route.destination) { | ||
route.destination = route.destination.replace(/\/\d+$/, ''); | ||
} | ||
if (net.isIP(route.destination) && route.netmask) { | ||
return ip.isEqual(ip.mask(remote.address, route.netmask), | ||
ip.mask(route.destination, route.netmask)); | ||
} | ||
if (net.isIP(route.destination)) { | ||
return ip.isEqual(remote.address, route.destination) || | ||
ip.isEqual(route.destination, '::'); | ||
} | ||
}).map(function(route) { | ||
return interfaces[route.interface].filter(function(addr) { | ||
return net.isIP(addr.address) === net.isIP(route.gateway) || | ||
net.isIP(addr.address) === net.isIP(route.destination) || | ||
net.isIP(addr.address) && net.isIP(route.netmask) && | ||
net.isIP(route.gateway) && | ||
ip.isEqual(ip.mask(addr.address, route.netmask), | ||
ip.mask(route.gateway, route.netmask)); | ||
}).map(function(addr) { | ||
return addr.address; | ||
}); | ||
}).reduce(function(prev, next) { | ||
return prev.concat(next); | ||
}, []); | ||
if (local.length === 0) { | ||
local = addr; | ||
} else { | ||
local = local[0]; | ||
} | ||
this.emit('_device', headers, local); | ||
this.emit('_device', headers, remote.address); | ||
}; | ||
@@ -207,0 +164,0 @@ |
{ | ||
"name": "nat-upnp", | ||
"version": "0.2.11", | ||
"version": "1.0.0", | ||
"main": "lib/nat-upnp", | ||
@@ -12,6 +12,7 @@ "author": "Fedor Indutny <fedor@indutny.com>", | ||
"devDependencies": { | ||
"jscs": "^1.11.2", | ||
"mocha": "~1.3.2" | ||
}, | ||
"scripts": { | ||
"test": "mocha --timeout 60000 --reporter spec test/*-test.js" | ||
"test": "jscs lib/*.js test/*.js && mocha --timeout 60000 --reporter spec test/*-test.js" | ||
}, | ||
@@ -22,5 +23,4 @@ "dependencies": { | ||
"async": "~0.1.22", | ||
"netroute": "~0.2.2", | ||
"ip": "~0.0.1" | ||
} | ||
} |
@@ -1,5 +0,5 @@ | ||
var assert = require('assert'), | ||
async = require('async'), | ||
net = require('net'), | ||
natUpnp = require('..'); | ||
var assert = require('assert'); | ||
var async = require('async'); | ||
var net = require('net'); | ||
var natUpnp = require('..'); | ||
@@ -6,0 +6,0 @@ describe('NAT-UPNP/Client', function() { |
@@ -1,3 +0,3 @@ | ||
var assert = require('assert'), | ||
natUpnp = require('..'); | ||
var assert = require('assert'); | ||
var natUpnp = require('..'); | ||
@@ -4,0 +4,0 @@ describe('NAT-UPNP/Ssdp', function() { |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
20242
4
11
0
2
2
514
- Removednetroute@~0.2.2
- Removedbindings@1.0.0(transitive)
- Removednan@1.9.0(transitive)
- Removednetroute@0.2.5(transitive)