matterbridge 3.2.4-dev-20250830-5c48452 → 3.2.4
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/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/cooktop.d.ts +60 -0
- package/dist/devices/cooktop.d.ts.map +1 -0
- package/dist/devices/cooktop.js +55 -0
- package/dist/devices/cooktop.js.map +1 -0
- package/dist/devices/dishwasher.d.ts +71 -0
- package/dist/devices/dishwasher.d.ts.map +1 -0
- package/dist/devices/dishwasher.js +57 -0
- 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 +15 -0
- package/dist/devices/export.d.ts.map +1 -0
- package/dist/devices/export.js +4 -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 +67 -0
- package/dist/devices/laundryDryer.d.ts.map +1 -0
- package/dist/devices/laundryDryer.js +62 -3
- package/dist/devices/laundryDryer.js.map +1 -0
- package/dist/devices/laundryWasher.d.ts +81 -0
- package/dist/devices/laundryWasher.d.ts.map +1 -0
- package/dist/devices/laundryWasher.js +70 -4
- package/dist/devices/laundryWasher.js.map +1 -0
- package/dist/devices/microwaveOven.d.ts +168 -0
- package/dist/devices/microwaveOven.d.ts.map +1 -0
- package/dist/devices/microwaveOven.js +88 -5
- package/dist/devices/microwaveOven.js.map +1 -0
- package/dist/devices/oven.d.ts +105 -0
- package/dist/devices/oven.d.ts.map +1 -0
- package/dist/devices/oven.js +85 -0
- package/dist/devices/oven.js.map +1 -0
- package/dist/devices/refrigerator.d.ts +93 -0
- package/dist/devices/refrigerator.d.ts.map +1 -0
- package/dist/devices/refrigerator.js +80 -0
- package/dist/devices/refrigerator.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/temperatureControl.d.ts +166 -0
- package/dist/devices/temperatureControl.d.ts.map +1 -0
- package/dist/devices/temperatureControl.js +25 -3
- package/dist/devices/temperatureControl.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 +298 -137
- 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 +313 -0
- package/dist/frontend.d.ts.map +1 -0
- package/dist/frontend.js +451 -24
- 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 +462 -0
- package/dist/matterbridge.d.ts.map +1 -0
- package/dist/matterbridge.js +789 -50
- 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 +1356 -0
- package/dist/matterbridgeEndpoint.d.ts.map +1 -0
- package/dist/matterbridgeEndpoint.js +1220 -54
- package/dist/matterbridgeEndpoint.js.map +1 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +407 -0
- package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
- package/dist/matterbridgeEndpointHelpers.js +345 -12
- package/dist/matterbridgeEndpointHelpers.js.map +1 -0
- package/dist/matterbridgePlatform.d.ts +331 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +256 -0
- package/dist/matterbridgePlatform.js.map +1 -0
- package/dist/matterbridgeTypes.d.ts +198 -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 +75 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +69 -0
- package/dist/update.js.map +1 -0
- package/dist/utils/colorUtils.d.ts +99 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/colorUtils.js +97 -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 +89 -0
- package/dist/utils/hex.d.ts.map +1 -0
- package/dist/utils/hex.js +124 -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 +84 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +91 -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 +54 -0
- package/dist/utils/wait.d.ts.map +1 -0
- package/dist/utils/wait.js +60 -8
- 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,14 +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
|
-
result.answers?.find((record) => record.type === 16) ||
|
|
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 */) ||
|
|
133
170
|
result.answers
|
|
134
171
|
? result.answers[0]
|
|
135
|
-
: undefined;
|
|
136
|
-
this.deviceResponses.set(rinfo.address, { rinfo, response: result, dataPTR: ptr?.type === 12 ? ptr?.data : ptr?.name });
|
|
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 });
|
|
137
174
|
this.onResponse(rinfo, result);
|
|
138
175
|
}
|
|
139
176
|
this.logMdnsMessage(result);
|
|
@@ -142,20 +179,28 @@ export class Mdns extends Multicast {
|
|
|
142
179
|
this.log.error(`Error decoding mDNS message: ${error instanceof Error ? error.message : error}`);
|
|
143
180
|
}
|
|
144
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
|
+
*/
|
|
145
190
|
decodeMdnsMessage(msg) {
|
|
146
191
|
if (msg.length < 12) {
|
|
147
192
|
throw new Error('mDNS message too short');
|
|
148
193
|
}
|
|
149
194
|
const id = msg.readUInt16BE(0);
|
|
150
195
|
const flags = msg.readUInt16BE(2);
|
|
151
|
-
const qr = (flags & 0x8000) >> 15;
|
|
152
|
-
const opcode = (flags & 0x7800) >> 11;
|
|
153
|
-
const aa = Boolean(flags & 0x0400);
|
|
154
|
-
const tc = Boolean(flags & 0x0200);
|
|
155
|
-
const rd = Boolean(flags & 0x0100);
|
|
156
|
-
const ra = Boolean(flags & 0x0080);
|
|
157
|
-
const z = (flags & 0x0070) >> 4;
|
|
158
|
-
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.
|
|
159
204
|
const qdCount = msg.readUInt16BE(4);
|
|
160
205
|
const anCount = msg.readUInt16BE(6);
|
|
161
206
|
const nsCount = msg.readUInt16BE(8);
|
|
@@ -180,6 +225,7 @@ export class Mdns extends Multicast {
|
|
|
180
225
|
additionals: [],
|
|
181
226
|
};
|
|
182
227
|
let offset = 12;
|
|
228
|
+
// Decode the question section.
|
|
183
229
|
for (let i = 0; i < qdCount; i++) {
|
|
184
230
|
const qnameResult = this.decodeDnsName(msg, offset);
|
|
185
231
|
const qname = qnameResult.name;
|
|
@@ -190,16 +236,19 @@ export class Mdns extends Multicast {
|
|
|
190
236
|
offset += 2;
|
|
191
237
|
mdnsMessage.questions?.push({ name: qname, type: qtype, class: qclass });
|
|
192
238
|
}
|
|
239
|
+
// Decode the answer section.
|
|
193
240
|
for (let i = 0; i < anCount; i++) {
|
|
194
241
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
195
242
|
mdnsMessage.answers?.push(rrResult.record);
|
|
196
243
|
offset = rrResult.newOffset;
|
|
197
244
|
}
|
|
245
|
+
// Decode the authority (NS) section.
|
|
198
246
|
for (let i = 0; i < nsCount; i++) {
|
|
199
247
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
200
248
|
mdnsMessage.authorities?.push(rrResult.record);
|
|
201
249
|
offset = rrResult.newOffset;
|
|
202
250
|
}
|
|
251
|
+
// Decode the additional records section.
|
|
203
252
|
for (let i = 0; i < arCount; i++) {
|
|
204
253
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
205
254
|
mdnsMessage.additionals?.push(rrResult.record);
|
|
@@ -207,15 +256,25 @@ export class Mdns extends Multicast {
|
|
|
207
256
|
}
|
|
208
257
|
return mdnsMessage;
|
|
209
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
|
+
*/
|
|
210
267
|
decodeDnsName(msg, offset) {
|
|
211
268
|
const labels = [];
|
|
212
269
|
let jumped = false;
|
|
213
270
|
let originalOffset = offset;
|
|
214
|
-
let iterations = 0;
|
|
271
|
+
let iterations = 0; // Prevent infinite loops
|
|
215
272
|
while (true) {
|
|
273
|
+
// Safety guard: prevent infinite loops in malformed messages.
|
|
216
274
|
if (iterations++ > 1000) {
|
|
217
275
|
throw new Error('Too many iterations while decoding DNS name. Possible malformed message.');
|
|
218
276
|
}
|
|
277
|
+
// Check that offset is within buffer bounds.
|
|
219
278
|
if (offset >= msg.length) {
|
|
220
279
|
throw new Error('Offset exceeds buffer length while decoding DNS name.');
|
|
221
280
|
}
|
|
@@ -224,7 +283,9 @@ export class Mdns extends Multicast {
|
|
|
224
283
|
offset++;
|
|
225
284
|
break;
|
|
226
285
|
}
|
|
286
|
+
// Check for pointer (first two bits are 11)
|
|
227
287
|
if ((len & 0xc0) === 0xc0) {
|
|
288
|
+
// Ensure the pointer has two bytes available.
|
|
228
289
|
if (offset + 1 >= msg.length) {
|
|
229
290
|
throw new Error('Incomplete pointer encountered while decoding DNS name.');
|
|
230
291
|
}
|
|
@@ -237,6 +298,7 @@ export class Mdns extends Multicast {
|
|
|
237
298
|
continue;
|
|
238
299
|
}
|
|
239
300
|
offset++;
|
|
301
|
+
// Check that the label length doesn't go beyond the buffer.
|
|
240
302
|
if (offset + len > msg.length) {
|
|
241
303
|
throw new Error('Label length exceeds buffer bounds while decoding DNS name.');
|
|
242
304
|
}
|
|
@@ -245,6 +307,15 @@ export class Mdns extends Multicast {
|
|
|
245
307
|
}
|
|
246
308
|
return { name: labels.join('.'), newOffset: jumped ? originalOffset : offset };
|
|
247
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
|
+
*/
|
|
248
319
|
encodeDnsName(name) {
|
|
249
320
|
const labels = name.split('.');
|
|
250
321
|
const buffers = labels.map((label) => {
|
|
@@ -252,12 +323,22 @@ export class Mdns extends Multicast {
|
|
|
252
323
|
lenBuf.writeUInt8(label.length, 0);
|
|
253
324
|
return Buffer.concat([lenBuf, Buffer.from(label)]);
|
|
254
325
|
});
|
|
326
|
+
// Append the null byte to terminate the name.
|
|
255
327
|
return Buffer.concat([...buffers, Buffer.from([0])]);
|
|
256
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
|
+
*/
|
|
257
336
|
decodeResourceRecord(msg, offset) {
|
|
337
|
+
// Decode the NAME field (which may be compressed)
|
|
258
338
|
const nameResult = this.decodeDnsName(msg, offset);
|
|
259
339
|
const name = nameResult.name;
|
|
260
340
|
offset = nameResult.newOffset;
|
|
341
|
+
// Read TYPE (16 bits), CLASS (16 bits), TTL (32 bits), and RDLENGTH (16 bits)
|
|
261
342
|
const type = msg.readUInt16BE(offset);
|
|
262
343
|
offset += 2;
|
|
263
344
|
const rrclass = msg.readUInt16BE(offset);
|
|
@@ -267,12 +348,14 @@ export class Mdns extends Multicast {
|
|
|
267
348
|
const rdlength = msg.readUInt16BE(offset);
|
|
268
349
|
offset += 2;
|
|
269
350
|
let data = '';
|
|
270
|
-
if (type === 12) {
|
|
351
|
+
if (type === 12 /* DnsRecordType.PTR */) {
|
|
352
|
+
// PTR record (type 12): decode its RDATA as a domain name.
|
|
271
353
|
const ptrResult = this.decodeDnsName(msg, offset);
|
|
272
354
|
data = ptrResult.name;
|
|
273
355
|
offset += rdlength;
|
|
274
356
|
}
|
|
275
|
-
else if (type === 16) {
|
|
357
|
+
else if (type === 16 /* DnsRecordType.TXT */) {
|
|
358
|
+
// TXT record: may consist of one or more length-prefixed strings.
|
|
276
359
|
const txtStrings = [];
|
|
277
360
|
const end = offset + rdlength;
|
|
278
361
|
while (offset < end) {
|
|
@@ -284,7 +367,8 @@ export class Mdns extends Multicast {
|
|
|
284
367
|
}
|
|
285
368
|
data = txtStrings.join(', ');
|
|
286
369
|
}
|
|
287
|
-
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.
|
|
288
372
|
const priority = msg.readUInt16BE(offset);
|
|
289
373
|
const weight = msg.readUInt16BE(offset + 2);
|
|
290
374
|
const port = msg.readUInt16BE(offset + 4);
|
|
@@ -298,13 +382,16 @@ export class Mdns extends Multicast {
|
|
|
298
382
|
});
|
|
299
383
|
offset = srvTargetResult.newOffset;
|
|
300
384
|
}
|
|
301
|
-
else if (type === 1) {
|
|
385
|
+
else if (type === 1 /* DnsRecordType.A */) {
|
|
386
|
+
// A record (type 1): an IPv4 address stored in 4 bytes.
|
|
302
387
|
const ipBytes = msg.slice(offset, offset + 4);
|
|
303
388
|
data = Array.from(ipBytes).join('.');
|
|
304
389
|
offset += 4;
|
|
305
390
|
}
|
|
306
|
-
else if (type === 28) {
|
|
391
|
+
else if (type === 28 /* DnsRecordType.AAAA */) {
|
|
392
|
+
// AAAA record (type 28): IPv6 address stored in 16 bytes.
|
|
307
393
|
const ipBytes = msg.slice(offset, offset + 16);
|
|
394
|
+
// Convert the 16 bytes into an IPv6 address string (colon-separated)
|
|
308
395
|
const ipv6Parts = [];
|
|
309
396
|
for (let i = 0; i < 16; i += 2) {
|
|
310
397
|
ipv6Parts.push(ipBytes.readUInt16BE(i).toString(16));
|
|
@@ -312,10 +399,14 @@ export class Mdns extends Multicast {
|
|
|
312
399
|
data = ipv6Parts.join(':');
|
|
313
400
|
offset += 16;
|
|
314
401
|
}
|
|
315
|
-
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)
|
|
316
406
|
const { name: nextDomain, newOffset } = this.decodeDnsName(msg, offset);
|
|
317
407
|
const nextDomainLength = newOffset - offset;
|
|
318
408
|
offset = newOffset;
|
|
409
|
+
// Calculate the remaining length for the type bit maps.
|
|
319
410
|
const bitmapLength = rdlength - nextDomainLength;
|
|
320
411
|
const bitmapData = msg.slice(offset, offset + bitmapLength);
|
|
321
412
|
const types = [];
|
|
@@ -342,6 +433,7 @@ export class Mdns extends Multicast {
|
|
|
342
433
|
offset += bitmapLength;
|
|
343
434
|
}
|
|
344
435
|
else {
|
|
436
|
+
// Fall back
|
|
345
437
|
data = msg.slice(offset, offset + rdlength).toString('hex');
|
|
346
438
|
offset += rdlength;
|
|
347
439
|
}
|
|
@@ -350,19 +442,28 @@ export class Mdns extends Multicast {
|
|
|
350
442
|
newOffset: offset,
|
|
351
443
|
};
|
|
352
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
|
+
*/
|
|
353
454
|
sendQuery(questions) {
|
|
354
455
|
const header = Buffer.alloc(12);
|
|
355
|
-
header.writeUInt16BE(0, 0);
|
|
356
|
-
header.writeUInt16BE(0, 2);
|
|
357
|
-
header.writeUInt16BE(questions.length, 4);
|
|
358
|
-
header.writeUInt16BE(0, 6);
|
|
359
|
-
header.writeUInt16BE(0, 8);
|
|
360
|
-
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
|
|
361
462
|
const questionBuffers = questions.map(({ name, type: qtype, class: qclass, unicastResponse = false }) => {
|
|
362
463
|
const qname = this.encodeDnsName(name);
|
|
363
464
|
const qfields = Buffer.alloc(4);
|
|
364
465
|
qfields.writeUInt16BE(qtype, 0);
|
|
365
|
-
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 : qclass, 2);
|
|
466
|
+
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 /* DnsClassFlag.QU */ : qclass, 2);
|
|
366
467
|
return Buffer.concat([qname, qfields]);
|
|
367
468
|
});
|
|
368
469
|
const query = Buffer.concat([header, ...questionBuffers]);
|
|
@@ -382,22 +483,46 @@ export class Mdns extends Multicast {
|
|
|
382
483
|
}
|
|
383
484
|
});
|
|
384
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
|
+
*/
|
|
385
499
|
sendResponse(name, rtype, rclass, ttl, rdata) {
|
|
500
|
+
// Create a 12-byte DNS header.
|
|
386
501
|
const header = Buffer.alloc(12);
|
|
387
|
-
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.
|
|
388
504
|
header.writeUInt16BE(0x8400, 2);
|
|
389
|
-
header.writeUInt16BE(0, 4);
|
|
390
|
-
header.writeUInt16BE(1, 6);
|
|
391
|
-
header.writeUInt16BE(0, 8);
|
|
392
|
-
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.
|
|
393
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).
|
|
394
516
|
const answerFixed = Buffer.alloc(10);
|
|
395
|
-
answerFixed.writeUInt16BE(rtype, 0);
|
|
396
|
-
answerFixed.writeUInt16BE(rclass, 2);
|
|
397
|
-
answerFixed.writeUInt32BE(ttl, 4);
|
|
398
|
-
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.
|
|
399
522
|
const answer = Buffer.concat([aname, answerFixed, rdata]);
|
|
523
|
+
// Concatenate header and answer to form the complete mDNS response packet.
|
|
400
524
|
const response = Buffer.concat([header, answer]);
|
|
525
|
+
// Send the response packet via the socket.
|
|
401
526
|
this.socket.send(response, 0, response.length, this.multicastPort, this.multicastAddress, (error) => {
|
|
402
527
|
if (error) {
|
|
403
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}`);
|
|
@@ -409,116 +534,128 @@ export class Mdns extends Multicast {
|
|
|
409
534
|
}
|
|
410
535
|
});
|
|
411
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
|
+
*/
|
|
412
543
|
dnsTypeToString(type) {
|
|
413
544
|
const typeMap = {
|
|
414
|
-
[1]: 'A',
|
|
415
|
-
[2]: 'NS',
|
|
416
|
-
[3]: 'MD',
|
|
417
|
-
[4]: 'MF',
|
|
418
|
-
[5]: 'CNAME',
|
|
419
|
-
[6]: 'SOA',
|
|
420
|
-
[7]: 'MB',
|
|
421
|
-
[8]: 'MG',
|
|
422
|
-
[9]: 'MR',
|
|
423
|
-
[10]: 'NULL',
|
|
424
|
-
[11]: 'WKS',
|
|
425
|
-
[12]: 'PTR',
|
|
426
|
-
[13]: 'HINFO',
|
|
427
|
-
[14]: 'MINFO',
|
|
428
|
-
[15]: 'MX',
|
|
429
|
-
[16]: 'TXT',
|
|
430
|
-
[17]: 'RP',
|
|
431
|
-
[18]: 'AFSDB',
|
|
432
|
-
[19]: 'X25',
|
|
433
|
-
[20]: 'ISDN',
|
|
434
|
-
[21]: 'RT',
|
|
435
|
-
[22]: 'NSAP',
|
|
436
|
-
[23]: 'NSAP_PTR',
|
|
437
|
-
[24]: 'SIG',
|
|
438
|
-
[25]: 'KEY',
|
|
439
|
-
[26]: 'PX',
|
|
440
|
-
[27]: 'GPOS',
|
|
441
|
-
[28]: 'AAAA',
|
|
442
|
-
[29]: 'LOC',
|
|
443
|
-
[30]: 'NXT',
|
|
444
|
-
[31]: 'EID',
|
|
445
|
-
[32]: 'NIMLOC',
|
|
446
|
-
[33]: 'SRV',
|
|
447
|
-
[34]: 'ATMA',
|
|
448
|
-
[35]: 'NAPTR',
|
|
449
|
-
[36]: 'KX',
|
|
450
|
-
[37]: 'CERT',
|
|
451
|
-
[38]: 'A6',
|
|
452
|
-
[39]: 'DNAME',
|
|
453
|
-
[40]: 'SINK',
|
|
454
|
-
[41]: 'OPT',
|
|
455
|
-
[42]: 'APL',
|
|
456
|
-
[43]: 'DS',
|
|
457
|
-
[44]: 'SSHFP',
|
|
458
|
-
[45]: 'IPSECKEY',
|
|
459
|
-
[46]: 'RRSIG',
|
|
460
|
-
[47]: 'NSEC',
|
|
461
|
-
[48]: 'DNSKEY',
|
|
462
|
-
[49]: 'DHCID',
|
|
463
|
-
[50]: 'NSEC3',
|
|
464
|
-
[51]: 'NSEC3PARAM',
|
|
465
|
-
[52]: 'TLSA',
|
|
466
|
-
[53]: 'SMIMEA',
|
|
467
|
-
[55]: 'HIP',
|
|
468
|
-
[56]: 'NINFO',
|
|
469
|
-
[57]: 'RKEY',
|
|
470
|
-
[58]: 'TALINK',
|
|
471
|
-
[59]: 'CDS',
|
|
472
|
-
[60]: 'CDNSKEY',
|
|
473
|
-
[61]: 'OPENPGPKEY',
|
|
474
|
-
[62]: 'CSYNC',
|
|
475
|
-
[63]: 'ZONEMD',
|
|
476
|
-
[64]: 'SVCB',
|
|
477
|
-
[65]: 'HTTPS',
|
|
478
|
-
[99]: 'SPF',
|
|
479
|
-
[100]: 'UINFO',
|
|
480
|
-
[101]: 'UID',
|
|
481
|
-
[102]: 'GID',
|
|
482
|
-
[103]: 'UNSPEC',
|
|
483
|
-
[104]: 'NID',
|
|
484
|
-
[105]: 'L32',
|
|
485
|
-
[106]: 'L64',
|
|
486
|
-
[107]: 'LP',
|
|
487
|
-
[108]: 'EUI48',
|
|
488
|
-
[109]: 'EUI64',
|
|
489
|
-
[249]: 'TKEY',
|
|
490
|
-
[250]: 'TSIG',
|
|
491
|
-
[251]: 'IXFR',
|
|
492
|
-
[252]: 'AXFR',
|
|
493
|
-
[253]: 'MAILB',
|
|
494
|
-
[254]: 'MAILA',
|
|
495
|
-
[255]: 'ANY',
|
|
496
|
-
[256]: 'URI',
|
|
497
|
-
[257]: 'CAA',
|
|
498
|
-
[258]: 'AVC',
|
|
499
|
-
[259]: 'DOA',
|
|
500
|
-
[260]: 'AMTRELAY',
|
|
501
|
-
[261]: 'ZONEVERSION',
|
|
502
|
-
[32768]: 'TA',
|
|
503
|
-
[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',
|
|
504
635
|
};
|
|
505
636
|
return typeMap[type] ?? `TYPE${type}`;
|
|
506
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
|
+
*/
|
|
507
644
|
dnsResponseClassToString(cls) {
|
|
508
|
-
const isFlush = !!(cls & 32768);
|
|
645
|
+
const isFlush = !!(cls & 32768 /* DnsClassFlag.FLUSH */);
|
|
509
646
|
const baseClass = cls & 0x7fff;
|
|
510
647
|
let classStr;
|
|
511
648
|
switch (baseClass) {
|
|
512
|
-
case 1
|
|
649
|
+
case 1 /* DnsClass.IN */:
|
|
513
650
|
classStr = 'IN';
|
|
514
651
|
break;
|
|
515
|
-
case 3
|
|
652
|
+
case 3 /* DnsClass.CH */:
|
|
516
653
|
classStr = 'CH';
|
|
517
654
|
break;
|
|
518
|
-
case 4
|
|
655
|
+
case 4 /* DnsClass.HS */:
|
|
519
656
|
classStr = 'HS';
|
|
520
657
|
break;
|
|
521
|
-
case 255
|
|
658
|
+
case 255 /* DnsClass.ANY */:
|
|
522
659
|
classStr = 'ANY';
|
|
523
660
|
break;
|
|
524
661
|
default:
|
|
@@ -526,21 +663,28 @@ export class Mdns extends Multicast {
|
|
|
526
663
|
}
|
|
527
664
|
return isFlush ? `${classStr}|FLUSH` : classStr;
|
|
528
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
|
+
*/
|
|
529
673
|
dnsQuestionClassToString(cls) {
|
|
530
|
-
const isQU = !!(cls & 32768);
|
|
674
|
+
const isQU = !!(cls & 32768 /* DnsClassFlag.QU */);
|
|
531
675
|
const baseClass = cls & 0x7fff;
|
|
532
676
|
let classStr;
|
|
533
677
|
switch (baseClass) {
|
|
534
|
-
case 1
|
|
678
|
+
case 1 /* DnsClass.IN */:
|
|
535
679
|
classStr = 'IN';
|
|
536
680
|
break;
|
|
537
|
-
case 3
|
|
681
|
+
case 3 /* DnsClass.CH */:
|
|
538
682
|
classStr = 'CH';
|
|
539
683
|
break;
|
|
540
|
-
case 4
|
|
684
|
+
case 4 /* DnsClass.HS */:
|
|
541
685
|
classStr = 'HS';
|
|
542
686
|
break;
|
|
543
|
-
case 255
|
|
687
|
+
case 255 /* DnsClass.ANY */:
|
|
544
688
|
classStr = 'ANY';
|
|
545
689
|
break;
|
|
546
690
|
default:
|
|
@@ -548,6 +692,11 @@ export class Mdns extends Multicast {
|
|
|
548
692
|
}
|
|
549
693
|
return isQU ? `${classStr}|QU` : classStr;
|
|
550
694
|
}
|
|
695
|
+
/**
|
|
696
|
+
* Logs the decoded mDNS message header.
|
|
697
|
+
*
|
|
698
|
+
* @param {MdnsMessage} msg - The mDNS message header object.
|
|
699
|
+
*/
|
|
551
700
|
logMdnsMessage(msg) {
|
|
552
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}`);
|
|
553
702
|
msg.questions?.forEach((question) => {
|
|
@@ -564,9 +713,14 @@ export class Mdns extends Multicast {
|
|
|
564
713
|
});
|
|
565
714
|
this.log.info(`---\n`);
|
|
566
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Logs the discovered devices from the mDNS queries and responses.
|
|
718
|
+
*/
|
|
567
719
|
logDevices() {
|
|
568
720
|
this.log.info(`Discovered query devices: ${MAGENTA}${this.deviceQueries.size}${nf}`);
|
|
721
|
+
// Collect devices into an array
|
|
569
722
|
const deviceQueryArray = Array.from(this.deviceQueries.entries());
|
|
723
|
+
// Sort the array by numeric value of the IP address
|
|
570
724
|
deviceQueryArray.sort(([addressA], [addressB]) => {
|
|
571
725
|
const partsA = addressA.split('.').map(Number);
|
|
572
726
|
const partsB = addressB.split('.').map(Number);
|
|
@@ -575,13 +729,17 @@ export class Mdns extends Multicast {
|
|
|
575
729
|
if (diff !== 0)
|
|
576
730
|
return diff;
|
|
577
731
|
}
|
|
732
|
+
// istanbul ignore next
|
|
578
733
|
return 0;
|
|
579
734
|
});
|
|
735
|
+
// Log the sorted devices
|
|
580
736
|
deviceQueryArray.forEach(([rinfo, response]) => {
|
|
581
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}`);
|
|
582
738
|
});
|
|
583
739
|
this.log.info(`Discovered response devices: ${MAGENTA}${this.deviceResponses.size}${nf}`);
|
|
740
|
+
// Collect devices into an array
|
|
584
741
|
const deviceResponseArray = Array.from(this.deviceResponses.entries());
|
|
742
|
+
// Sort the array by numeric value of the IP address
|
|
585
743
|
deviceResponseArray.sort(([addressA], [addressB]) => {
|
|
586
744
|
const partsA = addressA.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
587
745
|
const partsB = addressB.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
@@ -590,10 +748,13 @@ export class Mdns extends Multicast {
|
|
|
590
748
|
if (diff !== 0)
|
|
591
749
|
return diff;
|
|
592
750
|
}
|
|
751
|
+
// istanbul ignore next
|
|
593
752
|
return 0;
|
|
594
753
|
});
|
|
754
|
+
// Log the sorted devices
|
|
595
755
|
deviceResponseArray.forEach(([rinfo, response]) => {
|
|
596
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}`);
|
|
597
757
|
});
|
|
598
758
|
}
|
|
599
759
|
}
|
|
760
|
+
//# sourceMappingURL=mdns.js.map
|