matterbridge 3.1.7-dev-20250723-8e073ce → 3.1.7
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 +8 -17
- package/README-SERVICE.md +1 -0
- package/dist/cli.d.ts +26 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +91 -2
- package/dist/cli.js.map +1 -0
- package/dist/cliEmitter.d.ts +34 -0
- package/dist/cliEmitter.d.ts.map +1 -0
- package/dist/cliEmitter.js +30 -0
- package/dist/cliEmitter.js.map +1 -0
- package/dist/clusters/export.d.ts +2 -0
- package/dist/clusters/export.d.ts.map +1 -0
- package/dist/clusters/export.js +2 -0
- package/dist/clusters/export.js.map +1 -0
- package/dist/defaultConfigSchema.d.ts +28 -0
- package/dist/defaultConfigSchema.d.ts.map +1 -0
- package/dist/defaultConfigSchema.js +24 -0
- package/dist/defaultConfigSchema.js.map +1 -0
- package/dist/deviceManager.d.ts +112 -0
- package/dist/deviceManager.d.ts.map +1 -0
- package/dist/deviceManager.js +94 -1
- package/dist/deviceManager.js.map +1 -0
- package/dist/devices/batteryStorage.d.ts +48 -0
- package/dist/devices/batteryStorage.d.ts.map +1 -0
- package/dist/devices/batteryStorage.js +48 -1
- package/dist/devices/batteryStorage.js.map +1 -0
- package/dist/devices/dishwasher.d.ts +91 -0
- package/dist/devices/dishwasher.d.ts.map +1 -0
- package/dist/devices/dishwasher.js +78 -3
- package/dist/devices/dishwasher.js.map +1 -0
- package/dist/devices/evse.d.ts +75 -0
- package/dist/devices/evse.d.ts.map +1 -0
- package/dist/devices/evse.js +74 -10
- package/dist/devices/evse.js.map +1 -0
- package/dist/devices/export.d.ts +11 -0
- package/dist/devices/export.d.ts.map +1 -0
- package/dist/devices/export.js +2 -0
- package/dist/devices/export.js.map +1 -0
- package/dist/devices/extractorHood.d.ts +46 -0
- package/dist/devices/extractorHood.d.ts.map +1 -0
- package/dist/devices/extractorHood.js +42 -0
- package/dist/devices/extractorHood.js.map +1 -0
- package/dist/devices/heatPump.d.ts +47 -0
- package/dist/devices/heatPump.d.ts.map +1 -0
- package/dist/devices/heatPump.js +50 -2
- package/dist/devices/heatPump.js.map +1 -0
- package/dist/devices/laundryDryer.d.ts +87 -0
- package/dist/devices/laundryDryer.d.ts.map +1 -0
- package/dist/devices/laundryDryer.js +83 -6
- package/dist/devices/laundryDryer.js.map +1 -0
- package/dist/devices/laundryWasher.d.ts +242 -0
- package/dist/devices/laundryWasher.d.ts.map +1 -0
- package/dist/devices/laundryWasher.js +91 -7
- package/dist/devices/laundryWasher.js.map +1 -0
- package/dist/devices/roboticVacuumCleaner.d.ts +112 -0
- package/dist/devices/roboticVacuumCleaner.d.ts.map +1 -0
- package/dist/devices/roboticVacuumCleaner.js +93 -7
- package/dist/devices/roboticVacuumCleaner.js.map +1 -0
- package/dist/devices/solarPower.d.ts +40 -0
- package/dist/devices/solarPower.d.ts.map +1 -0
- package/dist/devices/solarPower.js +38 -0
- package/dist/devices/solarPower.js.map +1 -0
- package/dist/devices/waterHeater.d.ts +111 -0
- package/dist/devices/waterHeater.d.ts.map +1 -0
- package/dist/devices/waterHeater.js +82 -2
- package/dist/devices/waterHeater.js.map +1 -0
- package/dist/dgram/coap.d.ts +205 -0
- package/dist/dgram/coap.d.ts.map +1 -0
- package/dist/dgram/coap.js +126 -13
- package/dist/dgram/coap.js.map +1 -0
- package/dist/dgram/dgram.d.ts +140 -0
- package/dist/dgram/dgram.d.ts.map +1 -0
- package/dist/dgram/dgram.js +113 -2
- package/dist/dgram/dgram.js.map +1 -0
- package/dist/dgram/mb_coap.d.ts +24 -0
- package/dist/dgram/mb_coap.d.ts.map +1 -0
- package/dist/dgram/mb_coap.js +41 -3
- package/dist/dgram/mb_coap.js.map +1 -0
- package/dist/dgram/mb_mdns.d.ts +24 -0
- package/dist/dgram/mb_mdns.d.ts.map +1 -0
- package/dist/dgram/mb_mdns.js +51 -13
- package/dist/dgram/mb_mdns.js.map +1 -0
- package/dist/dgram/mdns.d.ts +288 -0
- package/dist/dgram/mdns.d.ts.map +1 -0
- package/dist/dgram/mdns.js +300 -135
- package/dist/dgram/mdns.js.map +1 -0
- package/dist/dgram/multicast.d.ts +65 -0
- package/dist/dgram/multicast.d.ts.map +1 -0
- package/dist/dgram/multicast.js +60 -1
- package/dist/dgram/multicast.js.map +1 -0
- package/dist/dgram/unicast.d.ts +56 -0
- package/dist/dgram/unicast.d.ts.map +1 -0
- package/dist/dgram/unicast.js +54 -0
- package/dist/dgram/unicast.js.map +1 -0
- package/dist/frontend.d.ts +304 -0
- package/dist/frontend.d.ts.map +1 -0
- package/dist/frontend.js +435 -21
- package/dist/frontend.js.map +1 -0
- package/dist/globalMatterbridge.d.ts +59 -0
- package/dist/globalMatterbridge.d.ts.map +1 -0
- package/dist/globalMatterbridge.js +47 -0
- package/dist/globalMatterbridge.js.map +1 -0
- package/dist/helpers.d.ts +48 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +53 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -1
- package/dist/index.js.map +1 -0
- package/dist/logger/export.d.ts +2 -0
- package/dist/logger/export.d.ts.map +1 -0
- package/dist/logger/export.js +1 -0
- package/dist/logger/export.js.map +1 -0
- package/dist/matter/behaviors.d.ts +2 -0
- package/dist/matter/behaviors.d.ts.map +1 -0
- package/dist/matter/behaviors.js +2 -0
- package/dist/matter/behaviors.js.map +1 -0
- package/dist/matter/clusters.d.ts +2 -0
- package/dist/matter/clusters.d.ts.map +1 -0
- package/dist/matter/clusters.js +2 -0
- package/dist/matter/clusters.js.map +1 -0
- package/dist/matter/devices.d.ts +2 -0
- package/dist/matter/devices.d.ts.map +1 -0
- package/dist/matter/devices.js +2 -0
- package/dist/matter/devices.js.map +1 -0
- package/dist/matter/endpoints.d.ts +2 -0
- package/dist/matter/endpoints.d.ts.map +1 -0
- package/dist/matter/endpoints.js +2 -0
- package/dist/matter/endpoints.js.map +1 -0
- package/dist/matter/export.d.ts +5 -0
- package/dist/matter/export.d.ts.map +1 -0
- package/dist/matter/export.js +3 -0
- package/dist/matter/export.js.map +1 -0
- package/dist/matter/types.d.ts +3 -0
- package/dist/matter/types.d.ts.map +1 -0
- package/dist/matter/types.js +3 -0
- package/dist/matter/types.js.map +1 -0
- package/dist/matterbridge.d.ts +463 -0
- package/dist/matterbridge.d.ts.map +1 -0
- package/dist/matterbridge.js +843 -58
- package/dist/matterbridge.js.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts +42 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.js +36 -0
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
- package/dist/matterbridgeBehaviors.d.ts +1351 -0
- package/dist/matterbridgeBehaviors.d.ts.map +1 -0
- package/dist/matterbridgeBehaviors.js +65 -5
- package/dist/matterbridgeBehaviors.js.map +1 -0
- package/dist/matterbridgeDeviceTypes.d.ts +709 -0
- package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
- package/dist/matterbridgeDeviceTypes.js +579 -15
- package/dist/matterbridgeDeviceTypes.js.map +1 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +42 -0
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
- package/dist/matterbridgeDynamicPlatform.js +36 -0
- package/dist/matterbridgeDynamicPlatform.js.map +1 -0
- package/dist/matterbridgeEndpoint.d.ts +1348 -0
- package/dist/matterbridgeEndpoint.d.ts.map +1 -0
- package/dist/matterbridgeEndpoint.js +1220 -51
- package/dist/matterbridgeEndpoint.js.map +1 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +406 -0
- package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
- package/dist/matterbridgeEndpointHelpers.js +353 -18
- package/dist/matterbridgeEndpointHelpers.js.map +1 -0
- package/dist/matterbridgePlatform.d.ts +310 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +233 -0
- package/dist/matterbridgePlatform.js.map +1 -0
- package/dist/matterbridgeTypes.d.ts +195 -0
- package/dist/matterbridgeTypes.d.ts.map +1 -0
- package/dist/matterbridgeTypes.js +25 -0
- package/dist/matterbridgeTypes.js.map +1 -0
- package/dist/pluginManager.d.ts +270 -0
- package/dist/pluginManager.d.ts.map +1 -0
- package/dist/pluginManager.js +249 -3
- package/dist/pluginManager.js.map +1 -0
- package/dist/shelly.d.ts +174 -0
- package/dist/shelly.d.ts.map +1 -0
- package/dist/shelly.js +168 -7
- package/dist/shelly.js.map +1 -0
- package/dist/storage/export.d.ts +2 -0
- package/dist/storage/export.d.ts.map +1 -0
- package/dist/storage/export.js +1 -0
- package/dist/storage/export.js.map +1 -0
- package/dist/update.d.ts +59 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +54 -0
- package/dist/update.js.map +1 -0
- package/dist/utils/colorUtils.d.ts +117 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/colorUtils.js +263 -2
- package/dist/utils/colorUtils.js.map +1 -0
- package/dist/utils/commandLine.d.ts +59 -0
- package/dist/utils/commandLine.d.ts.map +1 -0
- package/dist/utils/commandLine.js +54 -0
- package/dist/utils/commandLine.js.map +1 -0
- package/dist/utils/copyDirectory.d.ts +33 -0
- package/dist/utils/copyDirectory.d.ts.map +1 -0
- package/dist/utils/copyDirectory.js +38 -1
- package/dist/utils/copyDirectory.js.map +1 -0
- package/dist/utils/createDirectory.d.ts +34 -0
- package/dist/utils/createDirectory.d.ts.map +1 -0
- package/dist/utils/createDirectory.js +33 -0
- package/dist/utils/createDirectory.js.map +1 -0
- package/dist/utils/createZip.d.ts +39 -0
- package/dist/utils/createZip.d.ts.map +1 -0
- package/dist/utils/createZip.js +47 -2
- package/dist/utils/createZip.js.map +1 -0
- package/dist/utils/deepCopy.d.ts +32 -0
- package/dist/utils/deepCopy.d.ts.map +1 -0
- package/dist/utils/deepCopy.js +39 -0
- package/dist/utils/deepCopy.js.map +1 -0
- package/dist/utils/deepEqual.d.ts +54 -0
- package/dist/utils/deepEqual.d.ts.map +1 -0
- package/dist/utils/deepEqual.js +72 -1
- package/dist/utils/deepEqual.js.map +1 -0
- package/dist/utils/error.d.ts +44 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +41 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/export.d.ts +12 -0
- package/dist/utils/export.d.ts.map +1 -0
- package/dist/utils/export.js +1 -0
- package/dist/utils/export.js.map +1 -0
- package/dist/utils/hex.d.ts +49 -0
- package/dist/utils/hex.d.ts.map +1 -0
- package/dist/utils/hex.js +58 -0
- package/dist/utils/hex.js.map +1 -0
- package/dist/utils/isvalid.d.ts +103 -0
- package/dist/utils/isvalid.d.ts.map +1 -0
- package/dist/utils/isvalid.js +101 -0
- package/dist/utils/isvalid.js.map +1 -0
- package/dist/utils/network.d.ts +74 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +81 -5
- package/dist/utils/network.js.map +1 -0
- package/dist/utils/spawn.d.ts +33 -0
- package/dist/utils/spawn.d.ts.map +1 -0
- package/dist/utils/spawn.js +40 -0
- package/dist/utils/spawn.js.map +1 -0
- package/dist/utils/wait.d.ts +56 -0
- package/dist/utils/wait.d.ts.map +1 -0
- package/dist/utils/wait.js +62 -9
- package/dist/utils/wait.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
package/dist/dgram/mdns.js
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description This file contains the class Mdns.
|
|
3
|
+
* @file mdns.ts
|
|
4
|
+
* @author Luca Liguori
|
|
5
|
+
* @created 2025-03-22
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
* @license Apache-2.0
|
|
8
|
+
*
|
|
9
|
+
* Copyright 2025, 2026, 2027 Luca Liguori.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License.
|
|
22
|
+
*/
|
|
23
|
+
// AnsiLogger imports
|
|
1
24
|
import { BLUE, CYAN, db, er, GREEN, idn, MAGENTA, nf, rs } from 'node-ansi-logger';
|
|
25
|
+
// Net imports
|
|
2
26
|
import { Multicast } from './multicast.js';
|
|
3
27
|
export var DnsRecordType;
|
|
4
28
|
(function (DnsRecordType) {
|
|
@@ -90,6 +114,7 @@ export var DnsRecordType;
|
|
|
90
114
|
DnsRecordType[DnsRecordType["DOA"] = 259] = "DOA";
|
|
91
115
|
DnsRecordType[DnsRecordType["AMTRELAY"] = 260] = "AMTRELAY";
|
|
92
116
|
DnsRecordType[DnsRecordType["ZONEVERSION"] = 261] = "ZONEVERSION";
|
|
117
|
+
// 262-32767 are unassigned/reserved
|
|
93
118
|
DnsRecordType[DnsRecordType["TA"] = 32768] = "TA";
|
|
94
119
|
DnsRecordType[DnsRecordType["DLV"] = 32769] = "DLV";
|
|
95
120
|
})(DnsRecordType || (DnsRecordType = {}));
|
|
@@ -103,11 +128,23 @@ export var DnsClass;
|
|
|
103
128
|
export var DnsClassFlag;
|
|
104
129
|
(function (DnsClassFlag) {
|
|
105
130
|
DnsClassFlag[DnsClassFlag["FLUSH"] = 32768] = "FLUSH";
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
106
132
|
DnsClassFlag[DnsClassFlag["QU"] = 32768] = "QU";
|
|
107
133
|
})(DnsClassFlag || (DnsClassFlag = {}));
|
|
108
134
|
export class Mdns extends Multicast {
|
|
109
135
|
deviceQueries = new Map();
|
|
110
136
|
deviceResponses = new Map();
|
|
137
|
+
/**
|
|
138
|
+
* Creates an instance of the Mdns class.
|
|
139
|
+
*
|
|
140
|
+
* @param {string} name - The internal name of the mDNS server for the logs.
|
|
141
|
+
* @param {string} multicastAddress - The multicast address for mDNS (i.e. 224.0.0.251 for udp4 or ff02::fb for udp6).
|
|
142
|
+
* @param {number} multicastPort - The port for mDNS (i.e. 5353).
|
|
143
|
+
* @param {('udp4' | 'udp6')} socketType - The type of socket to create (either 'udp4' or 'udp6').
|
|
144
|
+
* @param {boolean} [reuseAddr] - Whether to reuse the address. Defaults to true.
|
|
145
|
+
* @param {string} [interfaceName] - The optional name of the network interface to use.
|
|
146
|
+
* @param {string} [interfaceAddress] - The optional IP address of the network interface to use.
|
|
147
|
+
*/
|
|
111
148
|
constructor(name, multicastAddress, multicastPort, socketType, reuseAddr = true, interfaceName, interfaceAddress) {
|
|
112
149
|
super(name, multicastAddress, multicastPort, socketType, reuseAddr, interfaceName, interfaceAddress);
|
|
113
150
|
}
|
|
@@ -126,10 +163,14 @@ export class Mdns extends Multicast {
|
|
|
126
163
|
this.onQuery(rinfo, result);
|
|
127
164
|
}
|
|
128
165
|
else {
|
|
129
|
-
const ptr = result.answers?.find((record) => record.name === '_shelly._tcp.local' && record.type === 12) ||
|
|
130
|
-
result.answers?.find((record) => record.name === '_http._tcp.local' && record.type === 12) ||
|
|
131
|
-
result.answers?.find((record) => record.type === 12)
|
|
132
|
-
|
|
166
|
+
const ptr = result.answers?.find((record) => record.name === '_shelly._tcp.local' && record.type === 12 /* DnsRecordType.PTR */) ||
|
|
167
|
+
result.answers?.find((record) => record.name === '_http._tcp.local' && record.type === 12 /* DnsRecordType.PTR */) ||
|
|
168
|
+
result.answers?.find((record) => record.type === 12 /* DnsRecordType.PTR */) ||
|
|
169
|
+
result.answers?.find((record) => record.type === 16 /* DnsRecordType.TXT */) ||
|
|
170
|
+
result.answers
|
|
171
|
+
? result.answers[0]
|
|
172
|
+
: undefined; // Fallback to the first answer if no PTR or TXT found
|
|
173
|
+
this.deviceResponses.set(rinfo.address, { rinfo, response: result, dataPTR: ptr?.type === 12 /* DnsRecordType.PTR */ ? ptr?.data : ptr?.name });
|
|
133
174
|
this.onResponse(rinfo, result);
|
|
134
175
|
}
|
|
135
176
|
this.logMdnsMessage(result);
|
|
@@ -138,20 +179,28 @@ export class Mdns extends Multicast {
|
|
|
138
179
|
this.log.error(`Error decoding mDNS message: ${error instanceof Error ? error.message : error}`);
|
|
139
180
|
}
|
|
140
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Decodes an mDNS message, including the header, question section, answer section,
|
|
184
|
+
* authority section, and additional section.
|
|
185
|
+
*
|
|
186
|
+
* @param {Buffer} msg - The raw mDNS message buffer.
|
|
187
|
+
* @returns {MdnsMessage} An object representing the decoded mDNS message.
|
|
188
|
+
* @throws Error if the message is too short.
|
|
189
|
+
*/
|
|
141
190
|
decodeMdnsMessage(msg) {
|
|
142
191
|
if (msg.length < 12) {
|
|
143
192
|
throw new Error('mDNS message too short');
|
|
144
193
|
}
|
|
145
194
|
const id = msg.readUInt16BE(0);
|
|
146
195
|
const flags = msg.readUInt16BE(2);
|
|
147
|
-
const qr = (flags & 0x8000) >> 15;
|
|
148
|
-
const opcode = (flags & 0x7800) >> 11;
|
|
149
|
-
const aa = Boolean(flags & 0x0400);
|
|
150
|
-
const tc = Boolean(flags & 0x0200);
|
|
151
|
-
const rd = Boolean(flags & 0x0100);
|
|
152
|
-
const ra = Boolean(flags & 0x0080);
|
|
153
|
-
const z = (flags & 0x0070) >> 4;
|
|
154
|
-
const rcode = flags & 0x000f;
|
|
196
|
+
const qr = (flags & 0x8000) >> 15; // Bit 15: 0=query, 1=response.
|
|
197
|
+
const opcode = (flags & 0x7800) >> 11; // Bits 14-11.
|
|
198
|
+
const aa = Boolean(flags & 0x0400); // Bit 10.
|
|
199
|
+
const tc = Boolean(flags & 0x0200); // Bit 9.
|
|
200
|
+
const rd = Boolean(flags & 0x0100); // Bit 8.
|
|
201
|
+
const ra = Boolean(flags & 0x0080); // Bit 7.
|
|
202
|
+
const z = (flags & 0x0070) >> 4; // Bits 6-4.
|
|
203
|
+
const rcode = flags & 0x000f; // Bits 3-0.
|
|
155
204
|
const qdCount = msg.readUInt16BE(4);
|
|
156
205
|
const anCount = msg.readUInt16BE(6);
|
|
157
206
|
const nsCount = msg.readUInt16BE(8);
|
|
@@ -176,6 +225,7 @@ export class Mdns extends Multicast {
|
|
|
176
225
|
additionals: [],
|
|
177
226
|
};
|
|
178
227
|
let offset = 12;
|
|
228
|
+
// Decode the question section.
|
|
179
229
|
for (let i = 0; i < qdCount; i++) {
|
|
180
230
|
const qnameResult = this.decodeDnsName(msg, offset);
|
|
181
231
|
const qname = qnameResult.name;
|
|
@@ -186,16 +236,19 @@ export class Mdns extends Multicast {
|
|
|
186
236
|
offset += 2;
|
|
187
237
|
mdnsMessage.questions?.push({ name: qname, type: qtype, class: qclass });
|
|
188
238
|
}
|
|
239
|
+
// Decode the answer section.
|
|
189
240
|
for (let i = 0; i < anCount; i++) {
|
|
190
241
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
191
242
|
mdnsMessage.answers?.push(rrResult.record);
|
|
192
243
|
offset = rrResult.newOffset;
|
|
193
244
|
}
|
|
245
|
+
// Decode the authority (NS) section.
|
|
194
246
|
for (let i = 0; i < nsCount; i++) {
|
|
195
247
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
196
248
|
mdnsMessage.authorities?.push(rrResult.record);
|
|
197
249
|
offset = rrResult.newOffset;
|
|
198
250
|
}
|
|
251
|
+
// Decode the additional records section.
|
|
199
252
|
for (let i = 0; i < arCount; i++) {
|
|
200
253
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
201
254
|
mdnsMessage.additionals?.push(rrResult.record);
|
|
@@ -203,15 +256,25 @@ export class Mdns extends Multicast {
|
|
|
203
256
|
}
|
|
204
257
|
return mdnsMessage;
|
|
205
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Decodes a DNS name from a buffer, handling compression.
|
|
261
|
+
*
|
|
262
|
+
* @param {Buffer} msg - The full mDNS message buffer.
|
|
263
|
+
* @param {number} offset - The offset at which the DNS name starts.
|
|
264
|
+
* @returns {{ name: string; newOffset: number }} An object with the decoded name and the new offset.
|
|
265
|
+
* @throws Error if the offset exceeds the buffer length or too many iterations are performed.
|
|
266
|
+
*/
|
|
206
267
|
decodeDnsName(msg, offset) {
|
|
207
268
|
const labels = [];
|
|
208
269
|
let jumped = false;
|
|
209
270
|
let originalOffset = offset;
|
|
210
|
-
let iterations = 0;
|
|
271
|
+
let iterations = 0; // Prevent infinite loops
|
|
211
272
|
while (true) {
|
|
273
|
+
// Safety guard: prevent infinite loops in malformed messages.
|
|
212
274
|
if (iterations++ > 1000) {
|
|
213
275
|
throw new Error('Too many iterations while decoding DNS name. Possible malformed message.');
|
|
214
276
|
}
|
|
277
|
+
// Check that offset is within buffer bounds.
|
|
215
278
|
if (offset >= msg.length) {
|
|
216
279
|
throw new Error('Offset exceeds buffer length while decoding DNS name.');
|
|
217
280
|
}
|
|
@@ -220,7 +283,9 @@ export class Mdns extends Multicast {
|
|
|
220
283
|
offset++;
|
|
221
284
|
break;
|
|
222
285
|
}
|
|
286
|
+
// Check for pointer (first two bits are 11)
|
|
223
287
|
if ((len & 0xc0) === 0xc0) {
|
|
288
|
+
// Ensure the pointer has two bytes available.
|
|
224
289
|
if (offset + 1 >= msg.length) {
|
|
225
290
|
throw new Error('Incomplete pointer encountered while decoding DNS name.');
|
|
226
291
|
}
|
|
@@ -233,6 +298,7 @@ export class Mdns extends Multicast {
|
|
|
233
298
|
continue;
|
|
234
299
|
}
|
|
235
300
|
offset++;
|
|
301
|
+
// Check that the label length doesn't go beyond the buffer.
|
|
236
302
|
if (offset + len > msg.length) {
|
|
237
303
|
throw new Error('Label length exceeds buffer bounds while decoding DNS name.');
|
|
238
304
|
}
|
|
@@ -241,6 +307,15 @@ export class Mdns extends Multicast {
|
|
|
241
307
|
}
|
|
242
308
|
return { name: labels.join('.'), newOffset: jumped ? originalOffset : offset };
|
|
243
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Encodes a domain name into the DNS label format.
|
|
312
|
+
*
|
|
313
|
+
* For example, "example.local" becomes:
|
|
314
|
+
* [7] "example" [5] "local" [0]
|
|
315
|
+
*
|
|
316
|
+
* @param {string} name - The domain name to encode.
|
|
317
|
+
* @returns {Buffer} The encoded domain name as a Buffer.
|
|
318
|
+
*/
|
|
244
319
|
encodeDnsName(name) {
|
|
245
320
|
const labels = name.split('.');
|
|
246
321
|
const buffers = labels.map((label) => {
|
|
@@ -248,12 +323,22 @@ export class Mdns extends Multicast {
|
|
|
248
323
|
lenBuf.writeUInt8(label.length, 0);
|
|
249
324
|
return Buffer.concat([lenBuf, Buffer.from(label)]);
|
|
250
325
|
});
|
|
326
|
+
// Append the null byte to terminate the name.
|
|
251
327
|
return Buffer.concat([...buffers, Buffer.from([0])]);
|
|
252
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Decodes a DNS resource record.
|
|
331
|
+
*
|
|
332
|
+
* @param {Buffer} msg - The full mDNS message buffer.
|
|
333
|
+
* @param {number} offset - The offset at which the resource record starts.
|
|
334
|
+
* @returns {{ record: MdnsRecord; newOffset: number }} An object containing the decoded record and the new offset.
|
|
335
|
+
*/
|
|
253
336
|
decodeResourceRecord(msg, offset) {
|
|
337
|
+
// Decode the NAME field (which may be compressed)
|
|
254
338
|
const nameResult = this.decodeDnsName(msg, offset);
|
|
255
339
|
const name = nameResult.name;
|
|
256
340
|
offset = nameResult.newOffset;
|
|
341
|
+
// Read TYPE (16 bits), CLASS (16 bits), TTL (32 bits), and RDLENGTH (16 bits)
|
|
257
342
|
const type = msg.readUInt16BE(offset);
|
|
258
343
|
offset += 2;
|
|
259
344
|
const rrclass = msg.readUInt16BE(offset);
|
|
@@ -263,12 +348,14 @@ export class Mdns extends Multicast {
|
|
|
263
348
|
const rdlength = msg.readUInt16BE(offset);
|
|
264
349
|
offset += 2;
|
|
265
350
|
let data = '';
|
|
266
|
-
if (type === 12) {
|
|
351
|
+
if (type === 12 /* DnsRecordType.PTR */) {
|
|
352
|
+
// PTR record (type 12): decode its RDATA as a domain name.
|
|
267
353
|
const ptrResult = this.decodeDnsName(msg, offset);
|
|
268
354
|
data = ptrResult.name;
|
|
269
355
|
offset += rdlength;
|
|
270
356
|
}
|
|
271
|
-
else if (type === 16) {
|
|
357
|
+
else if (type === 16 /* DnsRecordType.TXT */) {
|
|
358
|
+
// TXT record: may consist of one or more length-prefixed strings.
|
|
272
359
|
const txtStrings = [];
|
|
273
360
|
const end = offset + rdlength;
|
|
274
361
|
while (offset < end) {
|
|
@@ -280,7 +367,8 @@ export class Mdns extends Multicast {
|
|
|
280
367
|
}
|
|
281
368
|
data = txtStrings.join(', ');
|
|
282
369
|
}
|
|
283
|
-
else if (type === 33) {
|
|
370
|
+
else if (type === 33 /* DnsRecordType.SRV */) {
|
|
371
|
+
// SRV record (type === 33): consists of 2 bytes for priority, 2 for weight, 2 for port, followed by the target domain name.
|
|
284
372
|
const priority = msg.readUInt16BE(offset);
|
|
285
373
|
const weight = msg.readUInt16BE(offset + 2);
|
|
286
374
|
const port = msg.readUInt16BE(offset + 4);
|
|
@@ -294,13 +382,16 @@ export class Mdns extends Multicast {
|
|
|
294
382
|
});
|
|
295
383
|
offset = srvTargetResult.newOffset;
|
|
296
384
|
}
|
|
297
|
-
else if (type === 1) {
|
|
385
|
+
else if (type === 1 /* DnsRecordType.A */) {
|
|
386
|
+
// A record (type 1): an IPv4 address stored in 4 bytes.
|
|
298
387
|
const ipBytes = msg.slice(offset, offset + 4);
|
|
299
388
|
data = Array.from(ipBytes).join('.');
|
|
300
389
|
offset += 4;
|
|
301
390
|
}
|
|
302
|
-
else if (type === 28) {
|
|
391
|
+
else if (type === 28 /* DnsRecordType.AAAA */) {
|
|
392
|
+
// AAAA record (type 28): IPv6 address stored in 16 bytes.
|
|
303
393
|
const ipBytes = msg.slice(offset, offset + 16);
|
|
394
|
+
// Convert the 16 bytes into an IPv6 address string (colon-separated)
|
|
304
395
|
const ipv6Parts = [];
|
|
305
396
|
for (let i = 0; i < 16; i += 2) {
|
|
306
397
|
ipv6Parts.push(ipBytes.readUInt16BE(i).toString(16));
|
|
@@ -308,10 +399,14 @@ export class Mdns extends Multicast {
|
|
|
308
399
|
data = ipv6Parts.join(':');
|
|
309
400
|
offset += 16;
|
|
310
401
|
}
|
|
311
|
-
else if (type === 47) {
|
|
402
|
+
else if (type === 47 /* DnsRecordType.NSEC */) {
|
|
403
|
+
// NSEC record: RDATA consists of:
|
|
404
|
+
// - Next Domain Name (in DNS label format)
|
|
405
|
+
// - Type Bit Maps (variable length)
|
|
312
406
|
const { name: nextDomain, newOffset } = this.decodeDnsName(msg, offset);
|
|
313
407
|
const nextDomainLength = newOffset - offset;
|
|
314
408
|
offset = newOffset;
|
|
409
|
+
// Calculate the remaining length for the type bit maps.
|
|
315
410
|
const bitmapLength = rdlength - nextDomainLength;
|
|
316
411
|
const bitmapData = msg.slice(offset, offset + bitmapLength);
|
|
317
412
|
const types = [];
|
|
@@ -338,6 +433,7 @@ export class Mdns extends Multicast {
|
|
|
338
433
|
offset += bitmapLength;
|
|
339
434
|
}
|
|
340
435
|
else {
|
|
436
|
+
// Fall back
|
|
341
437
|
data = msg.slice(offset, offset + rdlength).toString('hex');
|
|
342
438
|
offset += rdlength;
|
|
343
439
|
}
|
|
@@ -346,19 +442,28 @@ export class Mdns extends Multicast {
|
|
|
346
442
|
newOffset: offset,
|
|
347
443
|
};
|
|
348
444
|
}
|
|
445
|
+
/**
|
|
446
|
+
* Sends a DNS query with multiple questions.
|
|
447
|
+
*
|
|
448
|
+
* @param {Array<{ name: string; type: number; class: number; unicastResponse?: boolean }>} questions - Array of questions
|
|
449
|
+
*
|
|
450
|
+
* @remarks
|
|
451
|
+
* Each question should have a name (e.g., "_http._tcp.local"), type (e.g., DnsRecordType.PTR), class (e.g., DnsClass.IN),
|
|
452
|
+
* and an optional unicastResponse flag (this will add the DnsClassFlag.QU flag to the query).
|
|
453
|
+
*/
|
|
349
454
|
sendQuery(questions) {
|
|
350
455
|
const header = Buffer.alloc(12);
|
|
351
|
-
header.writeUInt16BE(0, 0);
|
|
352
|
-
header.writeUInt16BE(0, 2);
|
|
353
|
-
header.writeUInt16BE(questions.length, 4);
|
|
354
|
-
header.writeUInt16BE(0, 6);
|
|
355
|
-
header.writeUInt16BE(0, 8);
|
|
356
|
-
header.writeUInt16BE(0, 10);
|
|
456
|
+
header.writeUInt16BE(0, 0); // ID
|
|
457
|
+
header.writeUInt16BE(0, 2); // Flags
|
|
458
|
+
header.writeUInt16BE(questions.length, 4); // QDCOUNT
|
|
459
|
+
header.writeUInt16BE(0, 6); // ANCOUNT
|
|
460
|
+
header.writeUInt16BE(0, 8); // NSCOUNT
|
|
461
|
+
header.writeUInt16BE(0, 10); // ARCOUNT
|
|
357
462
|
const questionBuffers = questions.map(({ name, type: qtype, class: qclass, unicastResponse = false }) => {
|
|
358
463
|
const qname = this.encodeDnsName(name);
|
|
359
464
|
const qfields = Buffer.alloc(4);
|
|
360
465
|
qfields.writeUInt16BE(qtype, 0);
|
|
361
|
-
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 : qclass, 2);
|
|
466
|
+
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 /* DnsClassFlag.QU */ : qclass, 2);
|
|
362
467
|
return Buffer.concat([qname, qfields]);
|
|
363
468
|
});
|
|
364
469
|
const query = Buffer.concat([header, ...questionBuffers]);
|
|
@@ -378,22 +483,46 @@ export class Mdns extends Multicast {
|
|
|
378
483
|
}
|
|
379
484
|
});
|
|
380
485
|
}
|
|
486
|
+
/**
|
|
487
|
+
* Constructs an mDNS response packet and sends it to the multicast address and port.
|
|
488
|
+
*
|
|
489
|
+
* @param {string} name - The domain name being responded to (e.g., "example.local").
|
|
490
|
+
* @param {number} rtype - The response type (e.g., 1 for A, 28 for AAAA, etc.).
|
|
491
|
+
* @param {number} rclass - The response class (typically 1 for IN).
|
|
492
|
+
* @param {number} ttl - The time-to-live for the answer record.
|
|
493
|
+
* @param {Buffer} rdata - The resource data for the response (e.g., 4 bytes for an A record IPv4 address).
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* const ptrRdata = mdnsIpv4.encodeDnsName('matterbridge._http._tcp.local');
|
|
497
|
+
* mdnsIpv4.sendResponse('_http._tcp.local', DnsRecordType.PTR, DnsClass.IN, 120, ptrRdata);
|
|
498
|
+
*/
|
|
381
499
|
sendResponse(name, rtype, rclass, ttl, rdata) {
|
|
500
|
+
// Create a 12-byte DNS header.
|
|
382
501
|
const header = Buffer.alloc(12);
|
|
383
|
-
header.writeUInt16BE(0, 0);
|
|
502
|
+
header.writeUInt16BE(0, 0); // ID is set to 0 in mDNS.
|
|
503
|
+
// Set flags: QR (response) bit and AA (authoritative answer) bit.
|
|
384
504
|
header.writeUInt16BE(0x8400, 2);
|
|
385
|
-
header.writeUInt16BE(0, 4);
|
|
386
|
-
header.writeUInt16BE(1, 6);
|
|
387
|
-
header.writeUInt16BE(0, 8);
|
|
388
|
-
header.writeUInt16BE(0, 10);
|
|
505
|
+
header.writeUInt16BE(0, 4); // QDCOUNT: 0 questions in response.
|
|
506
|
+
header.writeUInt16BE(1, 6); // ANCOUNT: 1 answer record.
|
|
507
|
+
header.writeUInt16BE(0, 8); // NSCOUNT: 0 authority records.
|
|
508
|
+
header.writeUInt16BE(0, 10); // ARCOUNT: 0 additional records.
|
|
509
|
+
// Encode the domain name in DNS label format.
|
|
389
510
|
const aname = this.encodeDnsName(name);
|
|
511
|
+
// Prepare the fixed part of the answer record:
|
|
512
|
+
// - 2 bytes for qtype,
|
|
513
|
+
// - 2 bytes for qclass,
|
|
514
|
+
// - 4 bytes for TTL,
|
|
515
|
+
// - 2 bytes for RDLENGTH (length of the rdata).
|
|
390
516
|
const answerFixed = Buffer.alloc(10);
|
|
391
|
-
answerFixed.writeUInt16BE(rtype, 0);
|
|
392
|
-
answerFixed.writeUInt16BE(rclass, 2);
|
|
393
|
-
answerFixed.writeUInt32BE(ttl, 4);
|
|
394
|
-
answerFixed.writeUInt16BE(rdata.length, 8);
|
|
517
|
+
answerFixed.writeUInt16BE(rtype, 0); // Record type.
|
|
518
|
+
answerFixed.writeUInt16BE(rclass, 2); // Record class.
|
|
519
|
+
answerFixed.writeUInt32BE(ttl, 4); // Time-to-live.
|
|
520
|
+
answerFixed.writeUInt16BE(rdata.length, 8); // RDLENGTH.
|
|
521
|
+
// Concatenate the answer: encoded name, fixed fields, and resource data.
|
|
395
522
|
const answer = Buffer.concat([aname, answerFixed, rdata]);
|
|
523
|
+
// Concatenate header and answer to form the complete mDNS response packet.
|
|
396
524
|
const response = Buffer.concat([header, answer]);
|
|
525
|
+
// Send the response packet via the socket.
|
|
397
526
|
this.socket.send(response, 0, response.length, this.multicastPort, this.multicastAddress, (error) => {
|
|
398
527
|
if (error) {
|
|
399
528
|
this.log.error(`Dgram mDNS server failed to send response message for ${MAGENTA}${name}${er} type ${MAGENTA}${this.dnsTypeToString(rtype)}${er} class ${MAGENTA}${this.dnsResponseClassToString(rclass)}${er} ttl ${MAGENTA}${ttl}${er}: ${error instanceof Error ? error.message : error}`);
|
|
@@ -405,116 +534,128 @@ export class Mdns extends Multicast {
|
|
|
405
534
|
}
|
|
406
535
|
});
|
|
407
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Converts a DNS record type numeric value to its string representation.
|
|
539
|
+
*
|
|
540
|
+
* @param {number} type - The numeric DNS record type.
|
|
541
|
+
* @returns {string} The string representation of the record type.
|
|
542
|
+
*/
|
|
408
543
|
dnsTypeToString(type) {
|
|
409
544
|
const typeMap = {
|
|
410
|
-
[1]: 'A',
|
|
411
|
-
[2]: 'NS',
|
|
412
|
-
[3]: 'MD',
|
|
413
|
-
[4]: 'MF',
|
|
414
|
-
[5]: 'CNAME',
|
|
415
|
-
[6]: 'SOA',
|
|
416
|
-
[7]: 'MB',
|
|
417
|
-
[8]: 'MG',
|
|
418
|
-
[9]: 'MR',
|
|
419
|
-
[10]: 'NULL',
|
|
420
|
-
[11]: 'WKS',
|
|
421
|
-
[12]: 'PTR',
|
|
422
|
-
[13]: 'HINFO',
|
|
423
|
-
[14]: 'MINFO',
|
|
424
|
-
[15]: 'MX',
|
|
425
|
-
[16]: 'TXT',
|
|
426
|
-
[17]: 'RP',
|
|
427
|
-
[18]: 'AFSDB',
|
|
428
|
-
[19]: 'X25',
|
|
429
|
-
[20]: 'ISDN',
|
|
430
|
-
[21]: 'RT',
|
|
431
|
-
[22]: 'NSAP',
|
|
432
|
-
[23]: 'NSAP_PTR',
|
|
433
|
-
[24]: 'SIG',
|
|
434
|
-
[25]: 'KEY',
|
|
435
|
-
[26]: 'PX',
|
|
436
|
-
[27]: 'GPOS',
|
|
437
|
-
[28]: 'AAAA',
|
|
438
|
-
[29]: 'LOC',
|
|
439
|
-
[30]: 'NXT',
|
|
440
|
-
[31]: 'EID',
|
|
441
|
-
[32]: 'NIMLOC',
|
|
442
|
-
[33]: 'SRV',
|
|
443
|
-
[34]: 'ATMA',
|
|
444
|
-
[35]: 'NAPTR',
|
|
445
|
-
[36]: 'KX',
|
|
446
|
-
[37]: 'CERT',
|
|
447
|
-
[38]: 'A6',
|
|
448
|
-
[39]: 'DNAME',
|
|
449
|
-
[40]: 'SINK',
|
|
450
|
-
[41]: 'OPT',
|
|
451
|
-
[42]: 'APL',
|
|
452
|
-
[43]: 'DS',
|
|
453
|
-
[44]: 'SSHFP',
|
|
454
|
-
[45]: 'IPSECKEY',
|
|
455
|
-
[46]: 'RRSIG',
|
|
456
|
-
[47]: 'NSEC',
|
|
457
|
-
[48]: 'DNSKEY',
|
|
458
|
-
[49]: 'DHCID',
|
|
459
|
-
[50]: 'NSEC3',
|
|
460
|
-
[51]: 'NSEC3PARAM',
|
|
461
|
-
[52]: 'TLSA',
|
|
462
|
-
[53]: 'SMIMEA',
|
|
463
|
-
[55]: 'HIP',
|
|
464
|
-
[56]: 'NINFO',
|
|
465
|
-
[57]: 'RKEY',
|
|
466
|
-
[58]: 'TALINK',
|
|
467
|
-
[59]: 'CDS',
|
|
468
|
-
[60]: 'CDNSKEY',
|
|
469
|
-
[61]: 'OPENPGPKEY',
|
|
470
|
-
[62]: 'CSYNC',
|
|
471
|
-
[63]: 'ZONEMD',
|
|
472
|
-
[64]: 'SVCB',
|
|
473
|
-
[65]: 'HTTPS',
|
|
474
|
-
[99]: 'SPF',
|
|
475
|
-
[100]: 'UINFO',
|
|
476
|
-
[101]: 'UID',
|
|
477
|
-
[102]: 'GID',
|
|
478
|
-
[103]: 'UNSPEC',
|
|
479
|
-
[104]: 'NID',
|
|
480
|
-
[105]: 'L32',
|
|
481
|
-
[106]: 'L64',
|
|
482
|
-
[107]: 'LP',
|
|
483
|
-
[108]: 'EUI48',
|
|
484
|
-
[109]: 'EUI64',
|
|
485
|
-
[249]: 'TKEY',
|
|
486
|
-
[250]: 'TSIG',
|
|
487
|
-
[251]: 'IXFR',
|
|
488
|
-
[252]: 'AXFR',
|
|
489
|
-
[253]: 'MAILB',
|
|
490
|
-
[254]: 'MAILA',
|
|
491
|
-
[255]: 'ANY',
|
|
492
|
-
[256]: 'URI',
|
|
493
|
-
[257]: 'CAA',
|
|
494
|
-
[258]: 'AVC',
|
|
495
|
-
[259]: 'DOA',
|
|
496
|
-
[260]: 'AMTRELAY',
|
|
497
|
-
[261]: 'ZONEVERSION',
|
|
498
|
-
[32768]: 'TA',
|
|
499
|
-
[32769]: 'DLV',
|
|
545
|
+
[1 /* DnsRecordType.A */]: 'A',
|
|
546
|
+
[2 /* DnsRecordType.NS */]: 'NS',
|
|
547
|
+
[3 /* DnsRecordType.MD */]: 'MD',
|
|
548
|
+
[4 /* DnsRecordType.MF */]: 'MF',
|
|
549
|
+
[5 /* DnsRecordType.CNAME */]: 'CNAME',
|
|
550
|
+
[6 /* DnsRecordType.SOA */]: 'SOA',
|
|
551
|
+
[7 /* DnsRecordType.MB */]: 'MB',
|
|
552
|
+
[8 /* DnsRecordType.MG */]: 'MG',
|
|
553
|
+
[9 /* DnsRecordType.MR */]: 'MR',
|
|
554
|
+
[10 /* DnsRecordType.NULL */]: 'NULL',
|
|
555
|
+
[11 /* DnsRecordType.WKS */]: 'WKS',
|
|
556
|
+
[12 /* DnsRecordType.PTR */]: 'PTR',
|
|
557
|
+
[13 /* DnsRecordType.HINFO */]: 'HINFO',
|
|
558
|
+
[14 /* DnsRecordType.MINFO */]: 'MINFO',
|
|
559
|
+
[15 /* DnsRecordType.MX */]: 'MX',
|
|
560
|
+
[16 /* DnsRecordType.TXT */]: 'TXT',
|
|
561
|
+
[17 /* DnsRecordType.RP */]: 'RP',
|
|
562
|
+
[18 /* DnsRecordType.AFSDB */]: 'AFSDB',
|
|
563
|
+
[19 /* DnsRecordType.X25 */]: 'X25',
|
|
564
|
+
[20 /* DnsRecordType.ISDN */]: 'ISDN',
|
|
565
|
+
[21 /* DnsRecordType.RT */]: 'RT',
|
|
566
|
+
[22 /* DnsRecordType.NSAP */]: 'NSAP',
|
|
567
|
+
[23 /* DnsRecordType.NSAP_PTR */]: 'NSAP_PTR',
|
|
568
|
+
[24 /* DnsRecordType.SIG */]: 'SIG',
|
|
569
|
+
[25 /* DnsRecordType.KEY */]: 'KEY',
|
|
570
|
+
[26 /* DnsRecordType.PX */]: 'PX',
|
|
571
|
+
[27 /* DnsRecordType.GPOS */]: 'GPOS',
|
|
572
|
+
[28 /* DnsRecordType.AAAA */]: 'AAAA',
|
|
573
|
+
[29 /* DnsRecordType.LOC */]: 'LOC',
|
|
574
|
+
[30 /* DnsRecordType.NXT */]: 'NXT',
|
|
575
|
+
[31 /* DnsRecordType.EID */]: 'EID',
|
|
576
|
+
[32 /* DnsRecordType.NIMLOC */]: 'NIMLOC',
|
|
577
|
+
[33 /* DnsRecordType.SRV */]: 'SRV',
|
|
578
|
+
[34 /* DnsRecordType.ATMA */]: 'ATMA',
|
|
579
|
+
[35 /* DnsRecordType.NAPTR */]: 'NAPTR',
|
|
580
|
+
[36 /* DnsRecordType.KX */]: 'KX',
|
|
581
|
+
[37 /* DnsRecordType.CERT */]: 'CERT',
|
|
582
|
+
[38 /* DnsRecordType.A6 */]: 'A6',
|
|
583
|
+
[39 /* DnsRecordType.DNAME */]: 'DNAME',
|
|
584
|
+
[40 /* DnsRecordType.SINK */]: 'SINK',
|
|
585
|
+
[41 /* DnsRecordType.OPT */]: 'OPT',
|
|
586
|
+
[42 /* DnsRecordType.APL */]: 'APL',
|
|
587
|
+
[43 /* DnsRecordType.DS */]: 'DS',
|
|
588
|
+
[44 /* DnsRecordType.SSHFP */]: 'SSHFP',
|
|
589
|
+
[45 /* DnsRecordType.IPSECKEY */]: 'IPSECKEY',
|
|
590
|
+
[46 /* DnsRecordType.RRSIG */]: 'RRSIG',
|
|
591
|
+
[47 /* DnsRecordType.NSEC */]: 'NSEC',
|
|
592
|
+
[48 /* DnsRecordType.DNSKEY */]: 'DNSKEY',
|
|
593
|
+
[49 /* DnsRecordType.DHCID */]: 'DHCID',
|
|
594
|
+
[50 /* DnsRecordType.NSEC3 */]: 'NSEC3',
|
|
595
|
+
[51 /* DnsRecordType.NSEC3PARAM */]: 'NSEC3PARAM',
|
|
596
|
+
[52 /* DnsRecordType.TLSA */]: 'TLSA',
|
|
597
|
+
[53 /* DnsRecordType.SMIMEA */]: 'SMIMEA',
|
|
598
|
+
[55 /* DnsRecordType.HIP */]: 'HIP',
|
|
599
|
+
[56 /* DnsRecordType.NINFO */]: 'NINFO',
|
|
600
|
+
[57 /* DnsRecordType.RKEY */]: 'RKEY',
|
|
601
|
+
[58 /* DnsRecordType.TALINK */]: 'TALINK',
|
|
602
|
+
[59 /* DnsRecordType.CDS */]: 'CDS',
|
|
603
|
+
[60 /* DnsRecordType.CDNSKEY */]: 'CDNSKEY',
|
|
604
|
+
[61 /* DnsRecordType.OPENPGPKEY */]: 'OPENPGPKEY',
|
|
605
|
+
[62 /* DnsRecordType.CSYNC */]: 'CSYNC',
|
|
606
|
+
[63 /* DnsRecordType.ZONEMD */]: 'ZONEMD',
|
|
607
|
+
[64 /* DnsRecordType.SVCB */]: 'SVCB',
|
|
608
|
+
[65 /* DnsRecordType.HTTPS */]: 'HTTPS',
|
|
609
|
+
[99 /* DnsRecordType.SPF */]: 'SPF',
|
|
610
|
+
[100 /* DnsRecordType.UINFO */]: 'UINFO',
|
|
611
|
+
[101 /* DnsRecordType.UID */]: 'UID',
|
|
612
|
+
[102 /* DnsRecordType.GID */]: 'GID',
|
|
613
|
+
[103 /* DnsRecordType.UNSPEC */]: 'UNSPEC',
|
|
614
|
+
[104 /* DnsRecordType.NID */]: 'NID',
|
|
615
|
+
[105 /* DnsRecordType.L32 */]: 'L32',
|
|
616
|
+
[106 /* DnsRecordType.L64 */]: 'L64',
|
|
617
|
+
[107 /* DnsRecordType.LP */]: 'LP',
|
|
618
|
+
[108 /* DnsRecordType.EUI48 */]: 'EUI48',
|
|
619
|
+
[109 /* DnsRecordType.EUI64 */]: 'EUI64',
|
|
620
|
+
[249 /* DnsRecordType.TKEY */]: 'TKEY',
|
|
621
|
+
[250 /* DnsRecordType.TSIG */]: 'TSIG',
|
|
622
|
+
[251 /* DnsRecordType.IXFR */]: 'IXFR',
|
|
623
|
+
[252 /* DnsRecordType.AXFR */]: 'AXFR',
|
|
624
|
+
[253 /* DnsRecordType.MAILB */]: 'MAILB',
|
|
625
|
+
[254 /* DnsRecordType.MAILA */]: 'MAILA',
|
|
626
|
+
[255 /* DnsRecordType.ANY */]: 'ANY',
|
|
627
|
+
[256 /* DnsRecordType.URI */]: 'URI',
|
|
628
|
+
[257 /* DnsRecordType.CAA */]: 'CAA',
|
|
629
|
+
[258 /* DnsRecordType.AVC */]: 'AVC',
|
|
630
|
+
[259 /* DnsRecordType.DOA */]: 'DOA',
|
|
631
|
+
[260 /* DnsRecordType.AMTRELAY */]: 'AMTRELAY',
|
|
632
|
+
[261 /* DnsRecordType.ZONEVERSION */]: 'ZONEVERSION',
|
|
633
|
+
[32768 /* DnsRecordType.TA */]: 'TA',
|
|
634
|
+
[32769 /* DnsRecordType.DLV */]: 'DLV',
|
|
500
635
|
};
|
|
501
636
|
return typeMap[type] ?? `TYPE${type}`;
|
|
502
637
|
}
|
|
638
|
+
/**
|
|
639
|
+
* Converts a DNS response class numeric value to its string representation.
|
|
640
|
+
*
|
|
641
|
+
* @param {number} cls - The numeric DNS class.
|
|
642
|
+
* @returns {string} The string representation of the DNS class.
|
|
643
|
+
*/
|
|
503
644
|
dnsResponseClassToString(cls) {
|
|
504
|
-
const isFlush = !!(cls & 32768);
|
|
645
|
+
const isFlush = !!(cls & 32768 /* DnsClassFlag.FLUSH */);
|
|
505
646
|
const baseClass = cls & 0x7fff;
|
|
506
647
|
let classStr;
|
|
507
648
|
switch (baseClass) {
|
|
508
|
-
case 1
|
|
649
|
+
case 1 /* DnsClass.IN */:
|
|
509
650
|
classStr = 'IN';
|
|
510
651
|
break;
|
|
511
|
-
case 3
|
|
652
|
+
case 3 /* DnsClass.CH */:
|
|
512
653
|
classStr = 'CH';
|
|
513
654
|
break;
|
|
514
|
-
case 4
|
|
655
|
+
case 4 /* DnsClass.HS */:
|
|
515
656
|
classStr = 'HS';
|
|
516
657
|
break;
|
|
517
|
-
case 255
|
|
658
|
+
case 255 /* DnsClass.ANY */:
|
|
518
659
|
classStr = 'ANY';
|
|
519
660
|
break;
|
|
520
661
|
default:
|
|
@@ -522,21 +663,28 @@ export class Mdns extends Multicast {
|
|
|
522
663
|
}
|
|
523
664
|
return isFlush ? `${classStr}|FLUSH` : classStr;
|
|
524
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Converts a DNS question class to a human-readable string.
|
|
668
|
+
* Adds support for mDNS QU (unicast-response) bit.
|
|
669
|
+
*
|
|
670
|
+
* @param {number} cls - The numeric question class.
|
|
671
|
+
* @returns {string} The string representation, e.g. "IN|QU"
|
|
672
|
+
*/
|
|
525
673
|
dnsQuestionClassToString(cls) {
|
|
526
|
-
const isQU = !!(cls & 32768);
|
|
674
|
+
const isQU = !!(cls & 32768 /* DnsClassFlag.QU */);
|
|
527
675
|
const baseClass = cls & 0x7fff;
|
|
528
676
|
let classStr;
|
|
529
677
|
switch (baseClass) {
|
|
530
|
-
case 1
|
|
678
|
+
case 1 /* DnsClass.IN */:
|
|
531
679
|
classStr = 'IN';
|
|
532
680
|
break;
|
|
533
|
-
case 3
|
|
681
|
+
case 3 /* DnsClass.CH */:
|
|
534
682
|
classStr = 'CH';
|
|
535
683
|
break;
|
|
536
|
-
case 4
|
|
684
|
+
case 4 /* DnsClass.HS */:
|
|
537
685
|
classStr = 'HS';
|
|
538
686
|
break;
|
|
539
|
-
case 255
|
|
687
|
+
case 255 /* DnsClass.ANY */:
|
|
540
688
|
classStr = 'ANY';
|
|
541
689
|
break;
|
|
542
690
|
default:
|
|
@@ -544,6 +692,11 @@ export class Mdns extends Multicast {
|
|
|
544
692
|
}
|
|
545
693
|
return isQU ? `${classStr}|QU` : classStr;
|
|
546
694
|
}
|
|
695
|
+
/**
|
|
696
|
+
* Logs the decoded mDNS message header.
|
|
697
|
+
*
|
|
698
|
+
* @param {MdnsMessage} msg - The mDNS message header object.
|
|
699
|
+
*/
|
|
547
700
|
logMdnsMessage(msg) {
|
|
548
701
|
this.log.info(`Decoded mDNS message: 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}`);
|
|
549
702
|
msg.questions?.forEach((question) => {
|
|
@@ -560,9 +713,14 @@ export class Mdns extends Multicast {
|
|
|
560
713
|
});
|
|
561
714
|
this.log.info(`---\n`);
|
|
562
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Logs the discovered devices from the mDNS queries and responses.
|
|
718
|
+
*/
|
|
563
719
|
logDevices() {
|
|
564
720
|
this.log.info(`Discovered query devices: ${MAGENTA}${this.deviceQueries.size}${nf}`);
|
|
721
|
+
// Collect devices into an array
|
|
565
722
|
const deviceQueryArray = Array.from(this.deviceQueries.entries());
|
|
723
|
+
// Sort the array by numeric value of the IP address
|
|
566
724
|
deviceQueryArray.sort(([addressA], [addressB]) => {
|
|
567
725
|
const partsA = addressA.split('.').map(Number);
|
|
568
726
|
const partsB = addressB.split('.').map(Number);
|
|
@@ -571,13 +729,17 @@ export class Mdns extends Multicast {
|
|
|
571
729
|
if (diff !== 0)
|
|
572
730
|
return diff;
|
|
573
731
|
}
|
|
732
|
+
// istanbul ignore next
|
|
574
733
|
return 0;
|
|
575
734
|
});
|
|
735
|
+
// Log the sorted devices
|
|
576
736
|
deviceQueryArray.forEach(([rinfo, response]) => {
|
|
577
737
|
this.log.info(`- ${MAGENTA}${rinfo}${nf} family ${BLUE}${response.rinfo.family}${nf} address ${BLUE}${response.rinfo.address}${nf} port ${BLUE}${response.rinfo.port}${nf}`);
|
|
578
738
|
});
|
|
579
739
|
this.log.info(`Discovered response devices: ${MAGENTA}${this.deviceResponses.size}${nf}`);
|
|
740
|
+
// Collect devices into an array
|
|
580
741
|
const deviceResponseArray = Array.from(this.deviceResponses.entries());
|
|
742
|
+
// Sort the array by numeric value of the IP address
|
|
581
743
|
deviceResponseArray.sort(([addressA], [addressB]) => {
|
|
582
744
|
const partsA = addressA.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
583
745
|
const partsB = addressB.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
@@ -586,10 +748,13 @@ export class Mdns extends Multicast {
|
|
|
586
748
|
if (diff !== 0)
|
|
587
749
|
return diff;
|
|
588
750
|
}
|
|
751
|
+
// istanbul ignore next
|
|
589
752
|
return 0;
|
|
590
753
|
});
|
|
754
|
+
// Log the sorted devices
|
|
591
755
|
deviceResponseArray.forEach(([rinfo, response]) => {
|
|
592
756
|
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}`);
|
|
593
757
|
});
|
|
594
758
|
}
|
|
595
759
|
}
|
|
760
|
+
//# sourceMappingURL=mdns.js.map
|