nat-upnp-rejetto 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -20,124 +11,112 @@ class Client {
20
11
  this.ssdp = new ssdp_1.default();
21
12
  this.timeout = options.timeout || 1800;
22
13
  }
23
- createMapping(options) {
24
- return __awaiter(this, void 0, void 0, function* () {
25
- return this.getGateway().then(({ gateway, address }) => {
26
- var _a;
27
- const ports = normalizeOptions(options);
28
- return gateway.run("AddPortMapping", [
29
- ["NewRemoteHost", ports.remote.host + ""],
30
- ["NewExternalPort", ports.remote.port + ""],
31
- [
32
- "NewProtocol",
33
- options.protocol ? options.protocol.toUpperCase() : "TCP",
34
- ],
35
- ["NewInternalPort", ports.internal.port + ""],
36
- ["NewInternalClient", ports.internal.host || address],
37
- ["NewEnabled", 1],
38
- ["NewPortMappingDescription", options.description || "node:nat:upnp"],
39
- ["NewLeaseDuration", (_a = options.ttl) !== null && _a !== void 0 ? _a : 60 * 30],
40
- ]);
41
- });
14
+ async createMapping(options) {
15
+ return this.getGateway().then(({ gateway, address }) => {
16
+ const ports = normalizeOptions(options);
17
+ return gateway.run("AddPortMapping", [
18
+ ["NewRemoteHost", ports.remote.host + ""],
19
+ ["NewExternalPort", ports.remote.port + ""],
20
+ [
21
+ "NewProtocol",
22
+ options.protocol ? options.protocol.toUpperCase() : "TCP",
23
+ ],
24
+ ["NewInternalPort", ports.internal.port + ""],
25
+ ["NewInternalClient", ports.internal.host || address],
26
+ ["NewEnabled", 1],
27
+ ["NewPortMappingDescription", options.description || "node:nat:upnp"],
28
+ ["NewLeaseDuration", options.ttl ?? 60 * 30],
29
+ ]);
42
30
  });
43
31
  }
44
- removeMapping(options) {
45
- return __awaiter(this, void 0, void 0, function* () {
46
- return this.getGateway().then(({ gateway }) => {
47
- const ports = normalizeOptions(options);
48
- return gateway.run("DeletePortMapping", [
49
- ["NewRemoteHost", ports.remote.host + ""],
50
- ["NewExternalPort", ports.remote.port + ""],
51
- [
52
- "NewProtocol",
53
- options.protocol ? options.protocol.toUpperCase() : "TCP",
54
- ],
55
- ]);
56
- });
32
+ async removeMapping(options) {
33
+ return this.getGateway().then(({ gateway }) => {
34
+ const ports = normalizeOptions(options);
35
+ return gateway.run("DeletePortMapping", [
36
+ ["NewRemoteHost", ports.remote.host + ""],
37
+ ["NewExternalPort", ports.remote.port + ""],
38
+ [
39
+ "NewProtocol",
40
+ options.protocol ? options.protocol.toUpperCase() : "TCP",
41
+ ],
42
+ ]);
57
43
  });
58
44
  }
59
- getMappings(options = {}) {
60
- return __awaiter(this, void 0, void 0, function* () {
61
- const { gateway, address } = yield this.getGateway();
62
- let i = 0;
63
- const results = [];
64
- while (true) {
65
- const data = yield gateway.run("GetGenericPortMappingEntry", [["NewPortMappingIndex", i++]])
66
- .catch(() => { });
67
- if (!data)
68
- break; // finished
69
- const key = Object.keys(data).find((k) => k.startsWith('GetGenericPortMappingEntryResponse'));
70
- if (!key) {
71
- throw new Error("Incorrect response");
72
- }
73
- const res = data[key];
74
- const result = {
75
- public: {
76
- host: res.NewRemoteHost || "",
77
- port: Number(res.NewExternalPort),
78
- },
79
- private: {
80
- host: res.NewInternalClient,
81
- port: Number(res.NewInternalPort),
82
- },
83
- protocol: res.NewProtocol.toLowerCase(),
84
- enabled: res.NewEnabled == 1,
85
- description: res.NewPortMappingDescription,
86
- ttl: Number(res.NewLeaseDuration),
87
- // temporary, so typescript will compile
88
- local: false,
89
- };
90
- result.local = result.private.host === address;
91
- if (options.local && !result.local) {
45
+ async getMappings(options = {}) {
46
+ const { gateway, address } = await this.getGateway();
47
+ let i = 0;
48
+ const results = [];
49
+ while (true) {
50
+ const data = await gateway.run("GetGenericPortMappingEntry", [["NewPortMappingIndex", i++]])
51
+ .catch(() => { });
52
+ if (!data)
53
+ break; // finished
54
+ const key = Object.keys(data).find((k) => k.startsWith('GetGenericPortMappingEntryResponse'));
55
+ if (!key) {
56
+ throw new Error("Incorrect response");
57
+ }
58
+ const res = data[key];
59
+ const result = {
60
+ public: {
61
+ host: res.NewRemoteHost || "",
62
+ port: Number(res.NewExternalPort),
63
+ },
64
+ private: {
65
+ host: res.NewInternalClient,
66
+ port: Number(res.NewInternalPort),
67
+ },
68
+ protocol: res.NewProtocol.toLowerCase(),
69
+ enabled: res.NewEnabled == 1,
70
+ description: res.NewPortMappingDescription,
71
+ ttl: Number(res.NewLeaseDuration),
72
+ // temporary, so typescript will compile
73
+ local: false,
74
+ };
75
+ result.local = result.private.host === address;
76
+ if (options.local && !result.local) {
77
+ continue;
78
+ }
79
+ if (options.description) {
80
+ if (typeof result.description !== "string")
92
81
  continue;
82
+ if (options.description instanceof RegExp) {
83
+ if (!options.description.test(result.description))
84
+ continue;
93
85
  }
94
- if (options.description) {
95
- if (typeof result.description !== "string")
86
+ else {
87
+ if (result.description.indexOf(options.description) === -1)
96
88
  continue;
97
- if (options.description instanceof RegExp) {
98
- if (!options.description.test(result.description))
99
- continue;
100
- }
101
- else {
102
- if (result.description.indexOf(options.description) === -1)
103
- continue;
104
- }
105
89
  }
106
- results.push(result);
107
90
  }
108
- return results;
109
- });
91
+ results.push(result);
92
+ }
93
+ return results;
110
94
  }
111
- getPublicIp() {
112
- return __awaiter(this, void 0, void 0, function* () {
113
- return this.getGateway().then(({ gateway, address }) => __awaiter(this, void 0, void 0, function* () {
114
- var _a;
115
- const data = yield gateway.run("GetExternalIPAddress", []);
116
- const key = Object.keys(data || {}).find((k) => /^GetExternalIPAddressResponse$/.test(k));
117
- if (!key)
118
- throw new Error("Incorrect response");
119
- return ((_a = data[key]) === null || _a === void 0 ? void 0 : _a.NewExternalIPAddress) + "";
120
- }));
95
+ async getPublicIp() {
96
+ return this.getGateway().then(async ({ gateway, address }) => {
97
+ const data = await gateway.run("GetExternalIPAddress", []);
98
+ const key = Object.keys(data || {}).find((k) => /^GetExternalIPAddressResponse$/.test(k));
99
+ if (!key)
100
+ throw new Error("Incorrect response");
101
+ return data[key]?.NewExternalIPAddress + "";
121
102
  });
122
103
  }
123
- getGateway() {
124
- return __awaiter(this, void 0, void 0, function* () {
125
- let timeouted = false;
126
- const p = this.ssdp.search("urn:schemas-upnp-org:device:InternetGatewayDevice:1");
127
- return new Promise((s, r) => {
128
- const timeout = setTimeout(() => {
129
- timeouted = true;
130
- p.emit("end");
131
- r(new Error("Connection timed out while searching for the gateway."));
132
- }, this.timeout);
133
- p.on("device", (info, address) => {
134
- if (timeouted)
135
- return;
136
- p.emit("end");
137
- clearTimeout(timeout);
138
- // Create gateway
139
- s({ gateway: new device_1.default(info.location), address });
140
- });
104
+ async getGateway() {
105
+ let timeouted = false;
106
+ const p = this.ssdp.search("urn:schemas-upnp-org:device:InternetGatewayDevice:1");
107
+ return new Promise((s, r) => {
108
+ const timeout = setTimeout(() => {
109
+ timeouted = true;
110
+ p.emit("end");
111
+ r(new Error("Connection timed out while searching for the gateway."));
112
+ }, this.timeout);
113
+ p.on("device", (info, address) => {
114
+ if (timeouted)
115
+ return;
116
+ p.emit("end");
117
+ clearTimeout(timeout);
118
+ // Create gateway
119
+ s({ gateway: new device_1.default(info.location), address });
141
120
  });
142
121
  });
143
122
  }
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -27,63 +18,55 @@ class Device {
27
18
  "urn:schemas-upnp-org:service:WANPPPConnection:1",
28
19
  ];
29
20
  }
30
- getXML(url) {
31
- return __awaiter(this, void 0, void 0, function* () {
32
- return httpRequest(url).then(consumers_1.text).then(data => new fast_xml_parser_1.XMLParser().parse(data));
33
- });
21
+ async getXML(url) {
22
+ return httpRequest(url).then(consumers_1.text).then(data => new fast_xml_parser_1.XMLParser().parse(data));
34
23
  }
35
- getService(types) {
36
- return __awaiter(this, void 0, void 0, function* () {
37
- return this.getXML(this.description).then(({ root: xml }) => {
38
- const services = this.parseDescription(xml).services.filter(({ serviceType }) => types.includes(serviceType));
39
- if (services.length === 0 ||
40
- !services[0].controlURL ||
41
- !services[0].SCPDURL) {
42
- throw new Error("Service not found");
43
- }
44
- const baseUrl = new url_1.URL(xml.baseURL, this.description);
45
- const prefix = (url) => new url_1.URL(url, baseUrl.toString()).toString();
46
- return {
47
- service: services[0].serviceType,
48
- SCPDURL: prefix(services[0].SCPDURL),
49
- controlURL: prefix(services[0].controlURL),
50
- };
51
- });
24
+ async getService(types) {
25
+ return this.getXML(this.description).then(({ root: xml }) => {
26
+ const services = this.parseDescription(xml).services.filter(({ serviceType }) => types.includes(serviceType));
27
+ if (services.length === 0 ||
28
+ !services[0].controlURL ||
29
+ !services[0].SCPDURL) {
30
+ throw new Error("Service not found");
31
+ }
32
+ const baseUrl = new url_1.URL(xml.baseURL, this.description);
33
+ const prefix = (url) => new url_1.URL(url, baseUrl.toString()).toString();
34
+ return {
35
+ service: services[0].serviceType,
36
+ SCPDURL: prefix(services[0].SCPDURL),
37
+ controlURL: prefix(services[0].controlURL),
38
+ };
52
39
  });
53
40
  }
54
- run(action, args) {
55
- return __awaiter(this, void 0, void 0, function* () {
56
- const info = yield this.getService(this.services);
57
- const body = `<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
58
- <s:Body><u:${action} xmlns:u=${JSON.stringify(info.service)}>${args.reduce((p, [a, b]) => p + `<${a !== null && a !== void 0 ? a : ''}>${b !== null && b !== void 0 ? b : ''}</${a !== null && a !== void 0 ? a : ''}>`, '')}</u:${action}>
41
+ async run(action, args) {
42
+ const info = await this.getService(this.services);
43
+ const body = `<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
44
+ <s:Body><u:${action} xmlns:u=${JSON.stringify(info.service)}>${args.reduce((p, [a, b]) => p + `<${a ?? ''}>${b ?? ''}</${a ?? ''}>`, '')}</u:${action}>
59
45
  </s:Body></s:Envelope>`;
60
- return httpRequest(info.controlURL, {
61
- method: 'post',
62
- headers: {
63
- "Content-Type": 'text/xml; charset="utf-8"',
64
- "Content-Length": "" + Buffer.byteLength(body),
65
- Connection: "close",
66
- SOAPAction: JSON.stringify(info.service + "#" + action),
67
- },
68
- }, body)
69
- .then(consumers_1.text, consumers_1.text).then(data => {
70
- var _a;
71
- const res = new fast_xml_parser_1.XMLParser({ removeNSPrefix: true }).parse(data).Envelope.Body;
72
- if (res.Fault)
73
- throw ((_a = res.Fault.detail) === null || _a === void 0 ? void 0 : _a.UPnPError) || res.Fault;
74
- return res;
75
- });
46
+ return httpRequest(info.controlURL, {
47
+ method: 'post',
48
+ headers: {
49
+ "Content-Type": 'text/xml; charset="utf-8"',
50
+ "Content-Length": "" + Buffer.byteLength(body),
51
+ Connection: "close",
52
+ SOAPAction: JSON.stringify(info.service + "#" + action),
53
+ },
54
+ }, body)
55
+ .then(consumers_1.text, consumers_1.text).then(data => {
56
+ const res = new fast_xml_parser_1.XMLParser({ removeNSPrefix: true }).parse(data).Envelope.Body;
57
+ if (res.Fault)
58
+ throw res.Fault.detail?.UPnPError || res.Fault;
59
+ return res;
76
60
  });
77
61
  }
78
62
  parseDescription(info) {
79
63
  const services = [];
80
64
  const devices = [];
81
65
  function traverseDevices(device) {
82
- var _a, _b, _c, _d;
83
66
  if (!device)
84
67
  return;
85
- const serviceList = (_b = (_a = device.serviceList) === null || _a === void 0 ? void 0 : _a.service) !== null && _b !== void 0 ? _b : [];
86
- const deviceList = (_d = (_c = device.deviceList) === null || _c === void 0 ? void 0 : _c.device) !== null && _d !== void 0 ? _d : [];
68
+ const serviceList = device.serviceList?.service ?? [];
69
+ const deviceList = device.deviceList?.device ?? [];
87
70
  devices.push(device);
88
71
  if (Array.isArray(serviceList)) {
89
72
  services.push(...serviceList);
@@ -108,5 +91,5 @@ class Device {
108
91
  exports.Device = Device;
109
92
  exports.default = Device;
110
93
  function httpRequest(url, options = {}, body = '') {
111
- return new Promise((resolve, reject) => (url.startsWith('https:') ? node_https_1.default : node_http_1.default).request(url, options, (res) => __awaiter(this, void 0, void 0, function* () { return !res.statusCode || res.statusCode >= 400 ? reject(res) : resolve(res); })).on('error', reject).end(body));
94
+ return new Promise((resolve, reject) => (url.startsWith('https:') ? node_https_1.default : node_http_1.default).request(url, options, async (res) => !res.statusCode || res.statusCode >= 400 ? reject(res) : resolve(res)).on('error', reject).end(body));
112
95
  }
@@ -9,9 +9,8 @@ const os_1 = __importDefault(require("os"));
9
9
  const events_1 = __importDefault(require("events"));
10
10
  class Ssdp {
11
11
  constructor(options) {
12
- var _a;
13
12
  this.options = options;
14
- this.sourcePort = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.sourcePort) || 0;
13
+ this.sourcePort = this.options?.sourcePort || 0;
15
14
  this.bound = false;
16
15
  this.boundCount = 0;
17
16
  this.closed = false;
@@ -21,10 +20,9 @@ class Ssdp {
21
20
  this.ssdpEmitter = new events_1.default();
22
21
  // Create sockets on all external interfaces
23
22
  const interfaces = os_1.default.networkInterfaces();
24
- this.sockets = Object.keys(interfaces).reduce((arr, key) => {
25
- var _a, _b;
26
- return arr.concat((_b = (_a = interfaces[key]) === null || _a === void 0 ? void 0 : _a.filter((item) => !item.internal).map((item) => this.createSocket(item))) !== null && _b !== void 0 ? _b : []);
27
- }, []);
23
+ this.sockets = Object.keys(interfaces).reduce((arr, key) => arr.concat(interfaces[key]
24
+ ?.filter((item) => !item.internal)
25
+ .map((item) => this.createSocket(item)) ?? []), []);
28
26
  }
29
27
  createSocket(iface) {
30
28
  const socket = dgram_1.default.createSocket(iface.family === "IPv4" ? "udp4" : "udp6");
@@ -116,8 +114,7 @@ function parseMimeHeader(headerStr) {
116
114
  const lines = headerStr.split(/\r\n/g);
117
115
  // Parse headers from lines to hashmap
118
116
  return lines.reduce((headers, line) => {
119
- var _a;
120
- const [_, key, value] = (_a = line.match(/^([^:]*)\s*:\s*(.*)$/)) !== null && _a !== void 0 ? _a : [];
117
+ const [_, key, value] = line.match(/^([^:]*)\s*:\s*(.*)$/) ?? [];
121
118
  if (key && value) {
122
119
  headers[key.toLowerCase()] = value;
123
120
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nat-upnp-rejetto",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "main": "build/src/index",
5
5
  "author": "Fedor Indutny <fedor@indutny.com>, SimplyLinn <https://github.com/SimplyLinn>, Kaden Sharpin <http://github.com/kaden-sharpin>, Massimo Melina <a@rejetto.com>",
6
6
  "homepage": "https://github.com/kaden-sharpin/nat-upnp-ts",
@@ -19,6 +19,6 @@
19
19
  "test": "tsc && node ./build/test/index.test.js"
20
20
  },
21
21
  "dependencies": {
22
- "fast-xml-parser": "^4.5.0"
22
+ "fast-xml-parser": "^5.3.4"
23
23
  }
24
24
  }