matterbridge 3.5.0-dev-20260119-f9ea00e → 3.5.1-dev-20260121-22e98b4
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.
- package/CHANGELOG.md +133 -117
- package/bin/mb_coap.js +1 -1
- package/bin/mb_mdns.js +1 -1
- package/dist/broadcastServer.js +1 -2
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +1 -5
- package/dist/cliHistory.js +1 -1
- package/dist/deviceManager.js +1 -1
- package/dist/frontend.js +2 -7
- package/dist/helpers.js +1 -1
- package/dist/matterNode.js +1 -5
- package/dist/matterbridge.js +14 -18
- package/dist/matterbridgeEndpoint.d.ts +2 -0
- package/dist/matterbridgeEndpoint.js +41 -2
- package/dist/matterbridgeEndpointHelpers.js +1 -3
- package/dist/matterbridgePlatform.js +1 -2
- package/dist/{dgram/mb_mdns.js → mb_mdns.js} +13 -1
- package/dist/pluginManager.js +3 -4
- package/dist/{utils/spawn.js → spawn.js} +2 -2
- package/dist/update.js +6 -7
- package/dist/utils/export.d.ts +1 -12
- package/dist/utils/export.js +1 -12
- package/dist/workerGlobalPrefix.js +1 -3
- package/frontend/build/assets/index.js +4 -4
- package/frontend/package.json +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +5 -5
- package/dist/dgram/coap.d.ts +0 -34
- package/dist/dgram/coap.js +0 -252
- package/dist/dgram/dgram.d.ts +0 -45
- package/dist/dgram/dgram.js +0 -251
- package/dist/dgram/mdns.d.ts +0 -188
- package/dist/dgram/mdns.js +0 -702
- package/dist/dgram/multicast.d.ts +0 -18
- package/dist/dgram/multicast.js +0 -118
- package/dist/dgram/unicast.d.ts +0 -11
- package/dist/dgram/unicast.js +0 -40
- package/dist/utils/colorUtils.d.ts +0 -24
- package/dist/utils/colorUtils.js +0 -187
- package/dist/utils/commandLine.d.ts +0 -6
- package/dist/utils/commandLine.js +0 -63
- package/dist/utils/copyDirectory.d.ts +0 -2
- package/dist/utils/copyDirectory.js +0 -39
- package/dist/utils/createDirectory.d.ts +0 -2
- package/dist/utils/createDirectory.js +0 -21
- package/dist/utils/createZip.d.ts +0 -1
- package/dist/utils/createZip.js +0 -69
- package/dist/utils/deepCopy.d.ts +0 -1
- package/dist/utils/deepCopy.js +0 -40
- package/dist/utils/deepEqual.d.ts +0 -1
- package/dist/utils/deepEqual.js +0 -58
- package/dist/utils/error.d.ts +0 -3
- package/dist/utils/error.js +0 -12
- package/dist/utils/format.d.ts +0 -4
- package/dist/utils/format.js +0 -29
- package/dist/utils/hex.d.ts +0 -4
- package/dist/utils/hex.js +0 -118
- package/dist/utils/inspector.d.ts +0 -24
- package/dist/utils/inspector.js +0 -200
- package/dist/utils/isValid.d.ts +0 -10
- package/dist/utils/isValid.js +0 -69
- package/dist/utils/network.d.ts +0 -25
- package/dist/utils/network.js +0 -193
- package/dist/utils/tracker.d.ts +0 -52
- package/dist/utils/tracker.js +0 -201
- package/dist/utils/wait.d.ts +0 -3
- package/dist/utils/wait.js +0 -73
- /package/dist/{dgram/mb_coap.d.ts → mb_coap.d.ts} +0 -0
- /package/dist/{dgram/mb_coap.js → mb_coap.js} +0 -0
- /package/dist/{dgram/mb_mdns.d.ts → mb_mdns.d.ts} +0 -0
- /package/dist/{utils/spawn.d.ts → spawn.d.ts} +0 -0
package/dist/dgram/mdns.js
DELETED
|
@@ -1,702 +0,0 @@
|
|
|
1
|
-
import { BLUE, CYAN, db, GREEN, idn, MAGENTA, nf, rs } from 'node-ansi-logger';
|
|
2
|
-
import { hasParameter } from '../utils/commandLine.js';
|
|
3
|
-
import { Multicast } from './multicast.js';
|
|
4
|
-
export var DnsRecordType;
|
|
5
|
-
(function (DnsRecordType) {
|
|
6
|
-
DnsRecordType[DnsRecordType["A"] = 1] = "A";
|
|
7
|
-
DnsRecordType[DnsRecordType["NS"] = 2] = "NS";
|
|
8
|
-
DnsRecordType[DnsRecordType["MD"] = 3] = "MD";
|
|
9
|
-
DnsRecordType[DnsRecordType["MF"] = 4] = "MF";
|
|
10
|
-
DnsRecordType[DnsRecordType["CNAME"] = 5] = "CNAME";
|
|
11
|
-
DnsRecordType[DnsRecordType["SOA"] = 6] = "SOA";
|
|
12
|
-
DnsRecordType[DnsRecordType["MB"] = 7] = "MB";
|
|
13
|
-
DnsRecordType[DnsRecordType["MG"] = 8] = "MG";
|
|
14
|
-
DnsRecordType[DnsRecordType["MR"] = 9] = "MR";
|
|
15
|
-
DnsRecordType[DnsRecordType["NULL"] = 10] = "NULL";
|
|
16
|
-
DnsRecordType[DnsRecordType["WKS"] = 11] = "WKS";
|
|
17
|
-
DnsRecordType[DnsRecordType["PTR"] = 12] = "PTR";
|
|
18
|
-
DnsRecordType[DnsRecordType["HINFO"] = 13] = "HINFO";
|
|
19
|
-
DnsRecordType[DnsRecordType["MINFO"] = 14] = "MINFO";
|
|
20
|
-
DnsRecordType[DnsRecordType["MX"] = 15] = "MX";
|
|
21
|
-
DnsRecordType[DnsRecordType["TXT"] = 16] = "TXT";
|
|
22
|
-
DnsRecordType[DnsRecordType["RP"] = 17] = "RP";
|
|
23
|
-
DnsRecordType[DnsRecordType["AFSDB"] = 18] = "AFSDB";
|
|
24
|
-
DnsRecordType[DnsRecordType["X25"] = 19] = "X25";
|
|
25
|
-
DnsRecordType[DnsRecordType["ISDN"] = 20] = "ISDN";
|
|
26
|
-
DnsRecordType[DnsRecordType["RT"] = 21] = "RT";
|
|
27
|
-
DnsRecordType[DnsRecordType["NSAP"] = 22] = "NSAP";
|
|
28
|
-
DnsRecordType[DnsRecordType["NSAP_PTR"] = 23] = "NSAP_PTR";
|
|
29
|
-
DnsRecordType[DnsRecordType["SIG"] = 24] = "SIG";
|
|
30
|
-
DnsRecordType[DnsRecordType["KEY"] = 25] = "KEY";
|
|
31
|
-
DnsRecordType[DnsRecordType["PX"] = 26] = "PX";
|
|
32
|
-
DnsRecordType[DnsRecordType["GPOS"] = 27] = "GPOS";
|
|
33
|
-
DnsRecordType[DnsRecordType["AAAA"] = 28] = "AAAA";
|
|
34
|
-
DnsRecordType[DnsRecordType["LOC"] = 29] = "LOC";
|
|
35
|
-
DnsRecordType[DnsRecordType["NXT"] = 30] = "NXT";
|
|
36
|
-
DnsRecordType[DnsRecordType["EID"] = 31] = "EID";
|
|
37
|
-
DnsRecordType[DnsRecordType["NIMLOC"] = 32] = "NIMLOC";
|
|
38
|
-
DnsRecordType[DnsRecordType["SRV"] = 33] = "SRV";
|
|
39
|
-
DnsRecordType[DnsRecordType["ATMA"] = 34] = "ATMA";
|
|
40
|
-
DnsRecordType[DnsRecordType["NAPTR"] = 35] = "NAPTR";
|
|
41
|
-
DnsRecordType[DnsRecordType["KX"] = 36] = "KX";
|
|
42
|
-
DnsRecordType[DnsRecordType["CERT"] = 37] = "CERT";
|
|
43
|
-
DnsRecordType[DnsRecordType["A6"] = 38] = "A6";
|
|
44
|
-
DnsRecordType[DnsRecordType["DNAME"] = 39] = "DNAME";
|
|
45
|
-
DnsRecordType[DnsRecordType["SINK"] = 40] = "SINK";
|
|
46
|
-
DnsRecordType[DnsRecordType["OPT"] = 41] = "OPT";
|
|
47
|
-
DnsRecordType[DnsRecordType["APL"] = 42] = "APL";
|
|
48
|
-
DnsRecordType[DnsRecordType["DS"] = 43] = "DS";
|
|
49
|
-
DnsRecordType[DnsRecordType["SSHFP"] = 44] = "SSHFP";
|
|
50
|
-
DnsRecordType[DnsRecordType["IPSECKEY"] = 45] = "IPSECKEY";
|
|
51
|
-
DnsRecordType[DnsRecordType["RRSIG"] = 46] = "RRSIG";
|
|
52
|
-
DnsRecordType[DnsRecordType["NSEC"] = 47] = "NSEC";
|
|
53
|
-
DnsRecordType[DnsRecordType["DNSKEY"] = 48] = "DNSKEY";
|
|
54
|
-
DnsRecordType[DnsRecordType["DHCID"] = 49] = "DHCID";
|
|
55
|
-
DnsRecordType[DnsRecordType["NSEC3"] = 50] = "NSEC3";
|
|
56
|
-
DnsRecordType[DnsRecordType["NSEC3PARAM"] = 51] = "NSEC3PARAM";
|
|
57
|
-
DnsRecordType[DnsRecordType["TLSA"] = 52] = "TLSA";
|
|
58
|
-
DnsRecordType[DnsRecordType["SMIMEA"] = 53] = "SMIMEA";
|
|
59
|
-
DnsRecordType[DnsRecordType["HIP"] = 55] = "HIP";
|
|
60
|
-
DnsRecordType[DnsRecordType["NINFO"] = 56] = "NINFO";
|
|
61
|
-
DnsRecordType[DnsRecordType["RKEY"] = 57] = "RKEY";
|
|
62
|
-
DnsRecordType[DnsRecordType["TALINK"] = 58] = "TALINK";
|
|
63
|
-
DnsRecordType[DnsRecordType["CDS"] = 59] = "CDS";
|
|
64
|
-
DnsRecordType[DnsRecordType["CDNSKEY"] = 60] = "CDNSKEY";
|
|
65
|
-
DnsRecordType[DnsRecordType["OPENPGPKEY"] = 61] = "OPENPGPKEY";
|
|
66
|
-
DnsRecordType[DnsRecordType["CSYNC"] = 62] = "CSYNC";
|
|
67
|
-
DnsRecordType[DnsRecordType["ZONEMD"] = 63] = "ZONEMD";
|
|
68
|
-
DnsRecordType[DnsRecordType["SVCB"] = 64] = "SVCB";
|
|
69
|
-
DnsRecordType[DnsRecordType["HTTPS"] = 65] = "HTTPS";
|
|
70
|
-
DnsRecordType[DnsRecordType["SPF"] = 99] = "SPF";
|
|
71
|
-
DnsRecordType[DnsRecordType["UINFO"] = 100] = "UINFO";
|
|
72
|
-
DnsRecordType[DnsRecordType["UID"] = 101] = "UID";
|
|
73
|
-
DnsRecordType[DnsRecordType["GID"] = 102] = "GID";
|
|
74
|
-
DnsRecordType[DnsRecordType["UNSPEC"] = 103] = "UNSPEC";
|
|
75
|
-
DnsRecordType[DnsRecordType["NID"] = 104] = "NID";
|
|
76
|
-
DnsRecordType[DnsRecordType["L32"] = 105] = "L32";
|
|
77
|
-
DnsRecordType[DnsRecordType["L64"] = 106] = "L64";
|
|
78
|
-
DnsRecordType[DnsRecordType["LP"] = 107] = "LP";
|
|
79
|
-
DnsRecordType[DnsRecordType["EUI48"] = 108] = "EUI48";
|
|
80
|
-
DnsRecordType[DnsRecordType["EUI64"] = 109] = "EUI64";
|
|
81
|
-
DnsRecordType[DnsRecordType["TKEY"] = 249] = "TKEY";
|
|
82
|
-
DnsRecordType[DnsRecordType["TSIG"] = 250] = "TSIG";
|
|
83
|
-
DnsRecordType[DnsRecordType["IXFR"] = 251] = "IXFR";
|
|
84
|
-
DnsRecordType[DnsRecordType["AXFR"] = 252] = "AXFR";
|
|
85
|
-
DnsRecordType[DnsRecordType["MAILB"] = 253] = "MAILB";
|
|
86
|
-
DnsRecordType[DnsRecordType["MAILA"] = 254] = "MAILA";
|
|
87
|
-
DnsRecordType[DnsRecordType["ANY"] = 255] = "ANY";
|
|
88
|
-
DnsRecordType[DnsRecordType["URI"] = 256] = "URI";
|
|
89
|
-
DnsRecordType[DnsRecordType["CAA"] = 257] = "CAA";
|
|
90
|
-
DnsRecordType[DnsRecordType["AVC"] = 258] = "AVC";
|
|
91
|
-
DnsRecordType[DnsRecordType["DOA"] = 259] = "DOA";
|
|
92
|
-
DnsRecordType[DnsRecordType["AMTRELAY"] = 260] = "AMTRELAY";
|
|
93
|
-
DnsRecordType[DnsRecordType["ZONEVERSION"] = 261] = "ZONEVERSION";
|
|
94
|
-
DnsRecordType[DnsRecordType["TA"] = 32768] = "TA";
|
|
95
|
-
DnsRecordType[DnsRecordType["DLV"] = 32769] = "DLV";
|
|
96
|
-
})(DnsRecordType || (DnsRecordType = {}));
|
|
97
|
-
export var DnsClass;
|
|
98
|
-
(function (DnsClass) {
|
|
99
|
-
DnsClass[DnsClass["IN"] = 1] = "IN";
|
|
100
|
-
DnsClass[DnsClass["CH"] = 3] = "CH";
|
|
101
|
-
DnsClass[DnsClass["HS"] = 4] = "HS";
|
|
102
|
-
DnsClass[DnsClass["ANY"] = 255] = "ANY";
|
|
103
|
-
})(DnsClass || (DnsClass = {}));
|
|
104
|
-
export var DnsClassFlag;
|
|
105
|
-
(function (DnsClassFlag) {
|
|
106
|
-
DnsClassFlag[DnsClassFlag["FLUSH"] = 32768] = "FLUSH";
|
|
107
|
-
DnsClassFlag[DnsClassFlag["QU"] = 32768] = "QU";
|
|
108
|
-
})(DnsClassFlag || (DnsClassFlag = {}));
|
|
109
|
-
export function isMdns(message) {
|
|
110
|
-
if (!message || message.length < 12)
|
|
111
|
-
return false;
|
|
112
|
-
const id = message.readUInt16BE(0);
|
|
113
|
-
return id === 0;
|
|
114
|
-
}
|
|
115
|
-
export function isMdnsQuery(message) {
|
|
116
|
-
if (message.length < 12)
|
|
117
|
-
return false;
|
|
118
|
-
const id = message.readUInt16BE(0);
|
|
119
|
-
const flags = message.readUInt16BE(2);
|
|
120
|
-
const qr = (flags & 0x8000) >> 15;
|
|
121
|
-
return id == 0 && qr === 0;
|
|
122
|
-
}
|
|
123
|
-
export function isMdnsResponse(message) {
|
|
124
|
-
if (message.length < 12)
|
|
125
|
-
return false;
|
|
126
|
-
const id = message.readUInt16BE(0);
|
|
127
|
-
const flags = message.readUInt16BE(2);
|
|
128
|
-
const qr = (flags & 0x8000) >> 15;
|
|
129
|
-
return id == 0 && qr === 1;
|
|
130
|
-
}
|
|
131
|
-
export class Mdns extends Multicast {
|
|
132
|
-
deviceQueries = new Map();
|
|
133
|
-
deviceResponses = new Map();
|
|
134
|
-
filters = [];
|
|
135
|
-
constructor(name, multicastAddress, multicastPort, socketType, reuseAddr = true, interfaceName, interfaceAddress, outgoingInterfaceAddress) {
|
|
136
|
-
super(name, multicastAddress, multicastPort, socketType, reuseAddr, interfaceName, interfaceAddress, outgoingInterfaceAddress);
|
|
137
|
-
}
|
|
138
|
-
onQuery(rinfo, _query) {
|
|
139
|
-
this.log.debug(`mDNS query received from ${BLUE}${rinfo.family}${db} ${BLUE}${rinfo.address}${db}:${BLUE}${rinfo.port}${db}`);
|
|
140
|
-
}
|
|
141
|
-
onResponse(rinfo, _response) {
|
|
142
|
-
this.log.debug(`mDNS response received from ${BLUE}${rinfo.family}${db} ${BLUE}${rinfo.address}${db}:${BLUE}${rinfo.port}${db}`);
|
|
143
|
-
}
|
|
144
|
-
onMessage(msg, rinfo) {
|
|
145
|
-
if (this.filters.length === 0)
|
|
146
|
-
this.log.info(`Dgram mDNS server received a mDNS message from ${BLUE}${rinfo.family}${nf} ${BLUE}${rinfo.address}${nf}:${BLUE}${rinfo.port}${nf}`);
|
|
147
|
-
try {
|
|
148
|
-
const result = this.decodeMdnsMessage(msg);
|
|
149
|
-
if (result.qr === 0) {
|
|
150
|
-
this.deviceQueries.set(rinfo.address, { rinfo, query: result });
|
|
151
|
-
this.onQuery(rinfo, result);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
const ptr = result.answers?.find((record) => record.name === '_shelly._tcp.local' && record.type === 12) ||
|
|
155
|
-
result.answers?.find((record) => record.name === '_http._tcp.local' && record.type === 12) ||
|
|
156
|
-
result.answers?.find((record) => record.type === 12) ||
|
|
157
|
-
result.answers?.find((record) => record.type === 16) ||
|
|
158
|
-
result.answers
|
|
159
|
-
? result.answers[0]
|
|
160
|
-
: undefined;
|
|
161
|
-
this.deviceResponses.set(rinfo.address, { rinfo, response: result, dataPTR: ptr?.type === 12 ? ptr?.data : ptr?.name });
|
|
162
|
-
this.onResponse(rinfo, result);
|
|
163
|
-
}
|
|
164
|
-
if (this.filters.length > 0) {
|
|
165
|
-
this.log.debug(`mDNS message filtered out by filters: ${this.filters.join(', ')}`);
|
|
166
|
-
for (const filter of this.filters) {
|
|
167
|
-
const foundInQuestions = result.questions?.some((q) => q.name.includes(filter));
|
|
168
|
-
const foundInAnswers = result.answers?.some((a) => a.name.includes(filter) || a.data.includes(filter));
|
|
169
|
-
const foundInAdditionals = result.additionals?.some((a) => a.name.includes(filter) || a.data.includes(filter));
|
|
170
|
-
if (foundInQuestions || foundInAnswers || foundInAdditionals) {
|
|
171
|
-
this.log.info(`Dgram mDNS server received a mDNS message from ${BLUE}${rinfo.family}${nf} ${BLUE}${rinfo.address}${nf}:${BLUE}${rinfo.port}${nf}`);
|
|
172
|
-
this.logMdnsMessage(result);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
this.log.debug(`mDNS message does not match any filter, ignoring.`);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
this.logMdnsMessage(result);
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
this.log.error(`Error decoding mDNS message: ${error instanceof Error ? error.message : error}`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
decodeMdnsMessage(msg) {
|
|
186
|
-
if (msg.length < 12) {
|
|
187
|
-
throw new Error('mDNS message too short');
|
|
188
|
-
}
|
|
189
|
-
const id = msg.readUInt16BE(0);
|
|
190
|
-
const flags = msg.readUInt16BE(2);
|
|
191
|
-
const qr = (flags & 0x8000) >> 15;
|
|
192
|
-
const opcode = (flags & 0x7800) >> 11;
|
|
193
|
-
const aa = Boolean(flags & 0x0400);
|
|
194
|
-
const tc = Boolean(flags & 0x0200);
|
|
195
|
-
const rd = Boolean(flags & 0x0100);
|
|
196
|
-
const ra = Boolean(flags & 0x0080);
|
|
197
|
-
const z = (flags & 0x0070) >> 4;
|
|
198
|
-
const rcode = flags & 0x000f;
|
|
199
|
-
const qdCount = msg.readUInt16BE(4);
|
|
200
|
-
const anCount = msg.readUInt16BE(6);
|
|
201
|
-
const nsCount = msg.readUInt16BE(8);
|
|
202
|
-
const arCount = msg.readUInt16BE(10);
|
|
203
|
-
const mdnsMessage = {
|
|
204
|
-
id,
|
|
205
|
-
qr,
|
|
206
|
-
opcode,
|
|
207
|
-
aa,
|
|
208
|
-
tc,
|
|
209
|
-
rd,
|
|
210
|
-
ra,
|
|
211
|
-
z,
|
|
212
|
-
rcode,
|
|
213
|
-
qdCount,
|
|
214
|
-
anCount,
|
|
215
|
-
nsCount,
|
|
216
|
-
arCount,
|
|
217
|
-
questions: [],
|
|
218
|
-
answers: [],
|
|
219
|
-
authorities: [],
|
|
220
|
-
additionals: [],
|
|
221
|
-
};
|
|
222
|
-
let offset = 12;
|
|
223
|
-
for (let i = 0; i < qdCount; i++) {
|
|
224
|
-
const qnameResult = this.decodeDnsName(msg, offset);
|
|
225
|
-
const qname = qnameResult.name;
|
|
226
|
-
offset = qnameResult.newOffset;
|
|
227
|
-
const qtype = msg.readUInt16BE(offset);
|
|
228
|
-
offset += 2;
|
|
229
|
-
const qclass = msg.readUInt16BE(offset);
|
|
230
|
-
offset += 2;
|
|
231
|
-
mdnsMessage.questions?.push({ name: qname, type: qtype, class: qclass });
|
|
232
|
-
}
|
|
233
|
-
for (let i = 0; i < anCount; i++) {
|
|
234
|
-
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
235
|
-
mdnsMessage.answers?.push(rrResult.record);
|
|
236
|
-
offset = rrResult.newOffset;
|
|
237
|
-
}
|
|
238
|
-
for (let i = 0; i < nsCount; i++) {
|
|
239
|
-
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
240
|
-
mdnsMessage.authorities?.push(rrResult.record);
|
|
241
|
-
offset = rrResult.newOffset;
|
|
242
|
-
}
|
|
243
|
-
for (let i = 0; i < arCount; i++) {
|
|
244
|
-
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
245
|
-
mdnsMessage.additionals?.push(rrResult.record);
|
|
246
|
-
offset = rrResult.newOffset;
|
|
247
|
-
}
|
|
248
|
-
return mdnsMessage;
|
|
249
|
-
}
|
|
250
|
-
decodeDnsName(msg, offset) {
|
|
251
|
-
const labels = [];
|
|
252
|
-
let jumped = false;
|
|
253
|
-
let originalOffset = offset;
|
|
254
|
-
let iterations = 0;
|
|
255
|
-
while (true) {
|
|
256
|
-
if (iterations++ > 1000) {
|
|
257
|
-
throw new Error('Too many iterations while decoding DNS name. Possible malformed message.');
|
|
258
|
-
}
|
|
259
|
-
if (offset >= msg.length) {
|
|
260
|
-
throw new Error('Offset exceeds buffer length while decoding DNS name.');
|
|
261
|
-
}
|
|
262
|
-
const len = msg.readUInt8(offset);
|
|
263
|
-
if (len === 0) {
|
|
264
|
-
offset++;
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
if ((len & 0xc0) === 0xc0) {
|
|
268
|
-
if (offset + 1 >= msg.length) {
|
|
269
|
-
throw new Error('Incomplete pointer encountered while decoding DNS name.');
|
|
270
|
-
}
|
|
271
|
-
const pointer = ((len & 0x3f) << 8) | msg.readUInt8(offset + 1);
|
|
272
|
-
if (!jumped) {
|
|
273
|
-
originalOffset = offset + 2;
|
|
274
|
-
}
|
|
275
|
-
offset = pointer;
|
|
276
|
-
jumped = true;
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
offset++;
|
|
280
|
-
if (offset + len > msg.length) {
|
|
281
|
-
throw new Error('Label length exceeds buffer bounds while decoding DNS name.');
|
|
282
|
-
}
|
|
283
|
-
labels.push(msg.toString('utf8', offset, offset + len));
|
|
284
|
-
offset += len;
|
|
285
|
-
}
|
|
286
|
-
return { name: labels.join('.'), newOffset: jumped ? originalOffset : offset };
|
|
287
|
-
}
|
|
288
|
-
encodeDnsName(name) {
|
|
289
|
-
const labels = name.split('.');
|
|
290
|
-
const buffers = labels.map((label) => {
|
|
291
|
-
const lenBuf = Buffer.alloc(1);
|
|
292
|
-
lenBuf.writeUInt8(label.length, 0);
|
|
293
|
-
return Buffer.concat([lenBuf, Buffer.from(label)]);
|
|
294
|
-
});
|
|
295
|
-
return Buffer.concat([...buffers, Buffer.from([0])]);
|
|
296
|
-
}
|
|
297
|
-
encodeTxtRdata(txt) {
|
|
298
|
-
const parts = txt.map((entry) => {
|
|
299
|
-
const value = Buffer.from(entry, 'utf8');
|
|
300
|
-
if (value.length > 255)
|
|
301
|
-
throw new Error(`TXT entry too long: ${entry}`);
|
|
302
|
-
return Buffer.concat([Buffer.from([value.length]), value]);
|
|
303
|
-
});
|
|
304
|
-
return Buffer.concat(parts);
|
|
305
|
-
}
|
|
306
|
-
encodeSrvRdata(priority, weight, port, target) {
|
|
307
|
-
const fixed = Buffer.alloc(6);
|
|
308
|
-
fixed.writeUInt16BE(priority, 0);
|
|
309
|
-
fixed.writeUInt16BE(weight, 2);
|
|
310
|
-
fixed.writeUInt16BE(port, 4);
|
|
311
|
-
return Buffer.concat([fixed, this.encodeDnsName(target)]);
|
|
312
|
-
}
|
|
313
|
-
encodeA(ipv4) {
|
|
314
|
-
const parts = ipv4.split('.').map((p) => Number(p));
|
|
315
|
-
if (parts.length !== 4 || parts.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {
|
|
316
|
-
throw new Error(`Invalid IPv4 address: ${ipv4}`);
|
|
317
|
-
}
|
|
318
|
-
return Buffer.from(parts);
|
|
319
|
-
}
|
|
320
|
-
encodeAAAA(ipv6WithOptionalScope) {
|
|
321
|
-
const ipv6 = ipv6WithOptionalScope.split('%')[0];
|
|
322
|
-
const [left, right] = ipv6.split('::');
|
|
323
|
-
const leftParts = left ? left.split(':').filter(Boolean) : [];
|
|
324
|
-
const rightParts = right ? right.split(':').filter(Boolean) : [];
|
|
325
|
-
if (ipv6.includes('::')) {
|
|
326
|
-
const missing = 8 - (leftParts.length + rightParts.length);
|
|
327
|
-
if (missing < 0)
|
|
328
|
-
throw new Error(`Invalid IPv6 address: ${ipv6WithOptionalScope}`);
|
|
329
|
-
const groups = [...leftParts, ...Array(missing).fill('0'), ...rightParts];
|
|
330
|
-
return Buffer.from(groups.flatMap((g) => {
|
|
331
|
-
const word = parseInt(g, 16);
|
|
332
|
-
if (!Number.isFinite(word) || word < 0 || word > 0xffff) {
|
|
333
|
-
throw new Error(`Invalid IPv6 group: ${g}`);
|
|
334
|
-
}
|
|
335
|
-
return [(word >> 8) & 0xff, word & 0xff];
|
|
336
|
-
}));
|
|
337
|
-
}
|
|
338
|
-
const groups = ipv6.split(':');
|
|
339
|
-
if (groups.length !== 8)
|
|
340
|
-
throw new Error(`Invalid IPv6 address: ${ipv6WithOptionalScope}`);
|
|
341
|
-
return Buffer.from(groups.flatMap((g) => {
|
|
342
|
-
if (!g)
|
|
343
|
-
throw new Error(`Invalid IPv6 group: ${g}`);
|
|
344
|
-
const word = parseInt(g, 16);
|
|
345
|
-
if (!Number.isFinite(word) || word < 0 || word > 0xffff)
|
|
346
|
-
throw new Error(`Invalid IPv6 group: ${g}`);
|
|
347
|
-
return [(word >> 8) & 0xff, word & 0xff];
|
|
348
|
-
}));
|
|
349
|
-
}
|
|
350
|
-
decodeResourceRecord(msg, offset) {
|
|
351
|
-
const nameResult = this.decodeDnsName(msg, offset);
|
|
352
|
-
const name = nameResult.name;
|
|
353
|
-
offset = nameResult.newOffset;
|
|
354
|
-
const type = msg.readUInt16BE(offset);
|
|
355
|
-
offset += 2;
|
|
356
|
-
const rrclass = msg.readUInt16BE(offset);
|
|
357
|
-
offset += 2;
|
|
358
|
-
const ttl = msg.readUInt32BE(offset);
|
|
359
|
-
offset += 4;
|
|
360
|
-
const rdlength = msg.readUInt16BE(offset);
|
|
361
|
-
offset += 2;
|
|
362
|
-
let data = '';
|
|
363
|
-
if (type === 12) {
|
|
364
|
-
const ptrResult = this.decodeDnsName(msg, offset);
|
|
365
|
-
data = ptrResult.name;
|
|
366
|
-
offset += rdlength;
|
|
367
|
-
}
|
|
368
|
-
else if (type === 16) {
|
|
369
|
-
const txtStrings = [];
|
|
370
|
-
const end = offset + rdlength;
|
|
371
|
-
while (offset < end) {
|
|
372
|
-
const txtLen = msg[offset];
|
|
373
|
-
offset++;
|
|
374
|
-
const txt = msg.slice(offset, offset + txtLen).toString('utf8');
|
|
375
|
-
txtStrings.push(txt);
|
|
376
|
-
offset += txtLen;
|
|
377
|
-
}
|
|
378
|
-
data = txtStrings.join(', ');
|
|
379
|
-
}
|
|
380
|
-
else if (type === 33) {
|
|
381
|
-
const priority = msg.readUInt16BE(offset);
|
|
382
|
-
const weight = msg.readUInt16BE(offset + 2);
|
|
383
|
-
const port = msg.readUInt16BE(offset + 4);
|
|
384
|
-
offset += 6;
|
|
385
|
-
const srvTargetResult = this.decodeDnsName(msg, offset);
|
|
386
|
-
data = JSON.stringify({
|
|
387
|
-
priority,
|
|
388
|
-
weight,
|
|
389
|
-
port,
|
|
390
|
-
target: srvTargetResult.name,
|
|
391
|
-
});
|
|
392
|
-
offset = srvTargetResult.newOffset;
|
|
393
|
-
}
|
|
394
|
-
else if (type === 1) {
|
|
395
|
-
const ipBytes = msg.slice(offset, offset + 4);
|
|
396
|
-
data = Array.from(ipBytes).join('.');
|
|
397
|
-
offset += 4;
|
|
398
|
-
}
|
|
399
|
-
else if (type === 28) {
|
|
400
|
-
const ipBytes = msg.slice(offset, offset + 16);
|
|
401
|
-
const ipv6Parts = [];
|
|
402
|
-
for (let i = 0; i < 16; i += 2) {
|
|
403
|
-
ipv6Parts.push(ipBytes.readUInt16BE(i).toString(16));
|
|
404
|
-
}
|
|
405
|
-
data = ipv6Parts.join(':');
|
|
406
|
-
offset += 16;
|
|
407
|
-
}
|
|
408
|
-
else if (type === 47) {
|
|
409
|
-
const { name: nextDomain, newOffset } = this.decodeDnsName(msg, offset);
|
|
410
|
-
const nextDomainLength = newOffset - offset;
|
|
411
|
-
offset = newOffset;
|
|
412
|
-
const bitmapLength = rdlength - nextDomainLength;
|
|
413
|
-
const bitmapData = msg.slice(offset, offset + bitmapLength);
|
|
414
|
-
const types = [];
|
|
415
|
-
let bitmapOffset = 0;
|
|
416
|
-
while (bitmapOffset < bitmapData.length) {
|
|
417
|
-
const windowBlock = bitmapData[bitmapOffset];
|
|
418
|
-
const windowLength = bitmapData[bitmapOffset + 1];
|
|
419
|
-
bitmapOffset += 2;
|
|
420
|
-
for (let i = 0; i < windowLength; i++) {
|
|
421
|
-
const octet = bitmapData[bitmapOffset + i];
|
|
422
|
-
for (let bit = 0; bit < 8; bit++) {
|
|
423
|
-
if (octet & (0x80 >> bit)) {
|
|
424
|
-
const typeCode = windowBlock * 256 + i * 8 + bit;
|
|
425
|
-
types.push(this.dnsTypeToString(typeCode));
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
bitmapOffset += windowLength;
|
|
430
|
-
}
|
|
431
|
-
data = JSON.stringify({
|
|
432
|
-
nextDomain,
|
|
433
|
-
types,
|
|
434
|
-
});
|
|
435
|
-
offset += bitmapLength;
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
data = msg.slice(offset, offset + rdlength).toString('hex');
|
|
439
|
-
offset += rdlength;
|
|
440
|
-
}
|
|
441
|
-
return {
|
|
442
|
-
record: { name, type, class: rrclass, ttl, data },
|
|
443
|
-
newOffset: offset,
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
sendQuery(questions) {
|
|
447
|
-
const header = Buffer.alloc(12);
|
|
448
|
-
header.writeUInt16BE(0, 0);
|
|
449
|
-
header.writeUInt16BE(0, 2);
|
|
450
|
-
header.writeUInt16BE(questions.length, 4);
|
|
451
|
-
header.writeUInt16BE(0, 6);
|
|
452
|
-
header.writeUInt16BE(0, 8);
|
|
453
|
-
header.writeUInt16BE(0, 10);
|
|
454
|
-
const questionBuffers = questions.map(({ name, type: qtype, class: qclass, unicastResponse = false }) => {
|
|
455
|
-
const qname = this.encodeDnsName(name);
|
|
456
|
-
const qfields = Buffer.alloc(4);
|
|
457
|
-
qfields.writeUInt16BE(qtype, 0);
|
|
458
|
-
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 : qclass, 2);
|
|
459
|
-
return Buffer.concat([qname, qfields]);
|
|
460
|
-
});
|
|
461
|
-
const query = Buffer.concat([header, ...questionBuffers]);
|
|
462
|
-
if (hasParameter('v') || hasParameter('verbose')) {
|
|
463
|
-
const decoded = this.decodeMdnsMessage(query);
|
|
464
|
-
this.logMdnsMessage(decoded, undefined, 'Sending query mDNS message');
|
|
465
|
-
}
|
|
466
|
-
this.socket.send(query, 0, query.length, this.multicastPort, this.multicastAddress, (error) => {
|
|
467
|
-
if (error) {
|
|
468
|
-
this.log.error(`Dgram mDNS server failed to send query message: ${error instanceof Error ? error.message : error}`);
|
|
469
|
-
this.emit('error', error);
|
|
470
|
-
}
|
|
471
|
-
else {
|
|
472
|
-
this.log.debug(`Dgram mDNS server sent query message`);
|
|
473
|
-
this.emit('sent', query, this.multicastAddress, this.multicastPort);
|
|
474
|
-
}
|
|
475
|
-
});
|
|
476
|
-
return query;
|
|
477
|
-
}
|
|
478
|
-
sendResponse(answers) {
|
|
479
|
-
if (!Array.isArray(answers) || answers.length === 0) {
|
|
480
|
-
throw new Error('sendResponse requires a non-empty answers array');
|
|
481
|
-
}
|
|
482
|
-
const header = Buffer.alloc(12);
|
|
483
|
-
header.writeUInt16BE(0, 0);
|
|
484
|
-
header.writeUInt16BE(0x8400, 2);
|
|
485
|
-
header.writeUInt16BE(0, 4);
|
|
486
|
-
header.writeUInt16BE(answers.length, 6);
|
|
487
|
-
header.writeUInt16BE(0, 8);
|
|
488
|
-
header.writeUInt16BE(0, 10);
|
|
489
|
-
const answerBuffers = answers.map(({ name, rtype, rclass, ttl, rdata }) => {
|
|
490
|
-
const aname = this.encodeDnsName(name);
|
|
491
|
-
const answerFixed = Buffer.alloc(10);
|
|
492
|
-
answerFixed.writeUInt16BE(rtype, 0);
|
|
493
|
-
answerFixed.writeUInt16BE(rclass, 2);
|
|
494
|
-
answerFixed.writeUInt32BE(ttl, 4);
|
|
495
|
-
answerFixed.writeUInt16BE(rdata.length, 8);
|
|
496
|
-
return Buffer.concat([aname, answerFixed, rdata]);
|
|
497
|
-
});
|
|
498
|
-
const response = Buffer.concat([header, ...answerBuffers]);
|
|
499
|
-
if (hasParameter('v') || hasParameter('verbose')) {
|
|
500
|
-
const decoded = this.decodeMdnsMessage(response);
|
|
501
|
-
this.logMdnsMessage(decoded, undefined, 'Sending response mDNS message');
|
|
502
|
-
}
|
|
503
|
-
this.socket.send(response, 0, response.length, this.multicastPort, this.multicastAddress, (error) => {
|
|
504
|
-
if (error) {
|
|
505
|
-
this.log.error(`Dgram mDNS server failed to send response message: ${error instanceof Error ? error.message : error}`);
|
|
506
|
-
this.emit('error', error);
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
this.log.debug(`Dgram mDNS server sent response message`);
|
|
510
|
-
this.emit('sent', response, this.multicastAddress, this.multicastPort);
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
return response;
|
|
514
|
-
}
|
|
515
|
-
dnsTypeToString(type) {
|
|
516
|
-
const typeMap = {
|
|
517
|
-
[1]: 'A',
|
|
518
|
-
[2]: 'NS',
|
|
519
|
-
[3]: 'MD',
|
|
520
|
-
[4]: 'MF',
|
|
521
|
-
[5]: 'CNAME',
|
|
522
|
-
[6]: 'SOA',
|
|
523
|
-
[7]: 'MB',
|
|
524
|
-
[8]: 'MG',
|
|
525
|
-
[9]: 'MR',
|
|
526
|
-
[10]: 'NULL',
|
|
527
|
-
[11]: 'WKS',
|
|
528
|
-
[12]: 'PTR',
|
|
529
|
-
[13]: 'HINFO',
|
|
530
|
-
[14]: 'MINFO',
|
|
531
|
-
[15]: 'MX',
|
|
532
|
-
[16]: 'TXT',
|
|
533
|
-
[17]: 'RP',
|
|
534
|
-
[18]: 'AFSDB',
|
|
535
|
-
[19]: 'X25',
|
|
536
|
-
[20]: 'ISDN',
|
|
537
|
-
[21]: 'RT',
|
|
538
|
-
[22]: 'NSAP',
|
|
539
|
-
[23]: 'NSAP_PTR',
|
|
540
|
-
[24]: 'SIG',
|
|
541
|
-
[25]: 'KEY',
|
|
542
|
-
[26]: 'PX',
|
|
543
|
-
[27]: 'GPOS',
|
|
544
|
-
[28]: 'AAAA',
|
|
545
|
-
[29]: 'LOC',
|
|
546
|
-
[30]: 'NXT',
|
|
547
|
-
[31]: 'EID',
|
|
548
|
-
[32]: 'NIMLOC',
|
|
549
|
-
[33]: 'SRV',
|
|
550
|
-
[34]: 'ATMA',
|
|
551
|
-
[35]: 'NAPTR',
|
|
552
|
-
[36]: 'KX',
|
|
553
|
-
[37]: 'CERT',
|
|
554
|
-
[38]: 'A6',
|
|
555
|
-
[39]: 'DNAME',
|
|
556
|
-
[40]: 'SINK',
|
|
557
|
-
[41]: 'OPT',
|
|
558
|
-
[42]: 'APL',
|
|
559
|
-
[43]: 'DS',
|
|
560
|
-
[44]: 'SSHFP',
|
|
561
|
-
[45]: 'IPSECKEY',
|
|
562
|
-
[46]: 'RRSIG',
|
|
563
|
-
[47]: 'NSEC',
|
|
564
|
-
[48]: 'DNSKEY',
|
|
565
|
-
[49]: 'DHCID',
|
|
566
|
-
[50]: 'NSEC3',
|
|
567
|
-
[51]: 'NSEC3PARAM',
|
|
568
|
-
[52]: 'TLSA',
|
|
569
|
-
[53]: 'SMIMEA',
|
|
570
|
-
[55]: 'HIP',
|
|
571
|
-
[56]: 'NINFO',
|
|
572
|
-
[57]: 'RKEY',
|
|
573
|
-
[58]: 'TALINK',
|
|
574
|
-
[59]: 'CDS',
|
|
575
|
-
[60]: 'CDNSKEY',
|
|
576
|
-
[61]: 'OPENPGPKEY',
|
|
577
|
-
[62]: 'CSYNC',
|
|
578
|
-
[63]: 'ZONEMD',
|
|
579
|
-
[64]: 'SVCB',
|
|
580
|
-
[65]: 'HTTPS',
|
|
581
|
-
[99]: 'SPF',
|
|
582
|
-
[100]: 'UINFO',
|
|
583
|
-
[101]: 'UID',
|
|
584
|
-
[102]: 'GID',
|
|
585
|
-
[103]: 'UNSPEC',
|
|
586
|
-
[104]: 'NID',
|
|
587
|
-
[105]: 'L32',
|
|
588
|
-
[106]: 'L64',
|
|
589
|
-
[107]: 'LP',
|
|
590
|
-
[108]: 'EUI48',
|
|
591
|
-
[109]: 'EUI64',
|
|
592
|
-
[249]: 'TKEY',
|
|
593
|
-
[250]: 'TSIG',
|
|
594
|
-
[251]: 'IXFR',
|
|
595
|
-
[252]: 'AXFR',
|
|
596
|
-
[253]: 'MAILB',
|
|
597
|
-
[254]: 'MAILA',
|
|
598
|
-
[255]: 'ANY',
|
|
599
|
-
[256]: 'URI',
|
|
600
|
-
[257]: 'CAA',
|
|
601
|
-
[258]: 'AVC',
|
|
602
|
-
[259]: 'DOA',
|
|
603
|
-
[260]: 'AMTRELAY',
|
|
604
|
-
[261]: 'ZONEVERSION',
|
|
605
|
-
[32768]: 'TA',
|
|
606
|
-
[32769]: 'DLV',
|
|
607
|
-
};
|
|
608
|
-
return typeMap[type] ?? `TYPE${type}`;
|
|
609
|
-
}
|
|
610
|
-
dnsResponseClassToString(cls) {
|
|
611
|
-
const isFlush = !!(cls & 32768);
|
|
612
|
-
const baseClass = cls & 0x7fff;
|
|
613
|
-
let classStr;
|
|
614
|
-
switch (baseClass) {
|
|
615
|
-
case 1:
|
|
616
|
-
classStr = 'IN';
|
|
617
|
-
break;
|
|
618
|
-
case 3:
|
|
619
|
-
classStr = 'CH';
|
|
620
|
-
break;
|
|
621
|
-
case 4:
|
|
622
|
-
classStr = 'HS';
|
|
623
|
-
break;
|
|
624
|
-
case 255:
|
|
625
|
-
classStr = 'ANY';
|
|
626
|
-
break;
|
|
627
|
-
default:
|
|
628
|
-
classStr = `CLASS${baseClass}`;
|
|
629
|
-
}
|
|
630
|
-
return isFlush ? `${classStr}|FLUSH` : classStr;
|
|
631
|
-
}
|
|
632
|
-
dnsQuestionClassToString(cls) {
|
|
633
|
-
const isQU = !!(cls & 32768);
|
|
634
|
-
const baseClass = cls & 0x7fff;
|
|
635
|
-
let classStr;
|
|
636
|
-
switch (baseClass) {
|
|
637
|
-
case 1:
|
|
638
|
-
classStr = 'IN';
|
|
639
|
-
break;
|
|
640
|
-
case 3:
|
|
641
|
-
classStr = 'CH';
|
|
642
|
-
break;
|
|
643
|
-
case 4:
|
|
644
|
-
classStr = 'HS';
|
|
645
|
-
break;
|
|
646
|
-
case 255:
|
|
647
|
-
classStr = 'ANY';
|
|
648
|
-
break;
|
|
649
|
-
default:
|
|
650
|
-
classStr = `CLASS${baseClass}`;
|
|
651
|
-
}
|
|
652
|
-
return isQU ? `${classStr}|QU` : classStr;
|
|
653
|
-
}
|
|
654
|
-
logMdnsMessage(msg, log = this.log, text = 'Decoded mDNS message') {
|
|
655
|
-
log.info(`${text}: ID ${MAGENTA}${msg.id}${nf}, QR ${GREEN}${msg.qr === 0 ? 'Query' : 'Response'}${nf}, OPCODE ${MAGENTA}${msg.opcode}${nf}, AA ${MAGENTA}${msg.aa}${nf}, TC ${MAGENTA}${msg.tc}${nf}, RD ${MAGENTA}${msg.rd}${nf}, RA ${MAGENTA}${msg.ra}${nf}, Z ${MAGENTA}${msg.z}${nf}, RCODE ${MAGENTA}${msg.rcode}${nf}, QDCount ${MAGENTA}${msg.qdCount}${nf}, ANCount ${MAGENTA}${msg.anCount}${nf}, NSCount ${MAGENTA}${msg.nsCount}${nf}, ARCount ${MAGENTA}${msg.arCount}${nf}`);
|
|
656
|
-
msg.questions?.forEach((question) => {
|
|
657
|
-
log.info(`Question: ${CYAN}${question.name}${nf} type ${idn}${this.dnsTypeToString(question.type)}${rs}${nf} class ${CYAN}${this.dnsQuestionClassToString(question.class)}${nf}`);
|
|
658
|
-
});
|
|
659
|
-
msg.answers?.forEach((answer) => {
|
|
660
|
-
log.info(`Answer: ${CYAN}${answer.name}${nf} type ${idn}${this.dnsTypeToString(answer.type)}${rs}${nf} class ${CYAN}${this.dnsResponseClassToString(answer.class)}${nf} ttl ${CYAN}${answer.ttl}${nf} data ${CYAN}${answer.data}${nf}`);
|
|
661
|
-
});
|
|
662
|
-
msg.authorities?.forEach((authority) => {
|
|
663
|
-
log.info(`Authority: ${CYAN}${authority.name}${nf} type ${idn}${this.dnsTypeToString(authority.type)}${rs}${nf} class ${CYAN}${this.dnsResponseClassToString(authority.class)}${nf} ttl ${CYAN}${authority.ttl}${nf} data ${CYAN}${authority.data}${nf}`);
|
|
664
|
-
});
|
|
665
|
-
msg.additionals?.forEach((additional) => {
|
|
666
|
-
log.info(`Additional: ${CYAN}${additional.name}${nf} type ${idn}${this.dnsTypeToString(additional.type)}${rs}${nf} class ${CYAN}${this.dnsResponseClassToString(additional.class)}${nf} ttl ${CYAN}${additional.ttl}${nf} data ${CYAN}${additional.data}${nf}`);
|
|
667
|
-
});
|
|
668
|
-
log.info(`---\n`);
|
|
669
|
-
}
|
|
670
|
-
logDevices() {
|
|
671
|
-
this.log.info(`Discovered query devices: ${MAGENTA}${this.deviceQueries.size}${nf}`);
|
|
672
|
-
const deviceQueryArray = Array.from(this.deviceQueries.entries());
|
|
673
|
-
deviceQueryArray.sort(([addressA], [addressB]) => {
|
|
674
|
-
const partsA = addressA.split('.').map(Number);
|
|
675
|
-
const partsB = addressB.split('.').map(Number);
|
|
676
|
-
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
677
|
-
const diff = (partsA[i] || 0) - (partsB[i] || 0);
|
|
678
|
-
if (diff !== 0)
|
|
679
|
-
return diff;
|
|
680
|
-
}
|
|
681
|
-
return 0;
|
|
682
|
-
});
|
|
683
|
-
deviceQueryArray.forEach(([rinfo, response]) => {
|
|
684
|
-
this.log.info(`- ${MAGENTA}${rinfo}${nf} family ${BLUE}${response.rinfo.family}${nf} address ${BLUE}${response.rinfo.address}${nf} port ${BLUE}${response.rinfo.port}${nf}`);
|
|
685
|
-
});
|
|
686
|
-
this.log.info(`Discovered response devices: ${MAGENTA}${this.deviceResponses.size}${nf}`);
|
|
687
|
-
const deviceResponseArray = Array.from(this.deviceResponses.entries());
|
|
688
|
-
deviceResponseArray.sort(([addressA], [addressB]) => {
|
|
689
|
-
const partsA = addressA.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
690
|
-
const partsB = addressB.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
691
|
-
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
692
|
-
const diff = (partsA[i] || 0) - (partsB[i] || 0);
|
|
693
|
-
if (diff !== 0)
|
|
694
|
-
return diff;
|
|
695
|
-
}
|
|
696
|
-
return 0;
|
|
697
|
-
});
|
|
698
|
-
deviceResponseArray.forEach(([rinfo, response]) => {
|
|
699
|
-
this.log.info(`- ${MAGENTA}${rinfo}${nf} family ${BLUE}${response.rinfo.family}${nf} address ${BLUE}${response.rinfo.address}${nf} port ${BLUE}${response.rinfo.port}${nf} PTR ${GREEN}${response.dataPTR}${nf}`);
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
}
|