matterbridge 3.4.6-dev-20260101-968b4ce → 3.4.6
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 +1 -1
- package/dist/broadcastServer.d.ts +144 -0
- package/dist/broadcastServer.d.ts.map +1 -0
- package/dist/broadcastServer.js +117 -0
- package/dist/broadcastServer.js.map +1 -0
- package/dist/broadcastServerTypes.d.ts +841 -0
- package/dist/broadcastServerTypes.d.ts.map +1 -0
- package/dist/broadcastServerTypes.js +24 -0
- package/dist/broadcastServerTypes.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +97 -1
- package/dist/cli.js.map +1 -0
- package/dist/cliEmitter.d.ts +50 -0
- package/dist/cliEmitter.d.ts.map +1 -0
- package/dist/cliEmitter.js +37 -0
- package/dist/cliEmitter.js.map +1 -0
- package/dist/cliHistory.d.ts +48 -0
- package/dist/cliHistory.d.ts.map +1 -0
- package/dist/cliHistory.js +38 -0
- package/dist/cliHistory.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/deviceManager.d.ts +135 -0
- package/dist/deviceManager.d.ts.map +1 -0
- package/dist/deviceManager.js +113 -1
- package/dist/deviceManager.js.map +1 -0
- package/dist/devices/airConditioner.d.ts +98 -0
- package/dist/devices/airConditioner.d.ts.map +1 -0
- package/dist/devices/airConditioner.js +57 -0
- package/dist/devices/airConditioner.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 +61 -0
- package/dist/devices/cooktop.d.ts.map +1 -0
- package/dist/devices/cooktop.js +56 -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 +76 -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 +17 -0
- package/dist/devices/export.d.ts.map +1 -0
- package/dist/devices/export.js +5 -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 +43 -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 +118 -0
- package/dist/devices/refrigerator.d.ts.map +1 -0
- package/dist/devices/refrigerator.js +102 -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 +100 -9
- 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/speaker.d.ts +87 -0
- package/dist/devices/speaker.d.ts.map +1 -0
- package/dist/devices/speaker.js +84 -0
- package/dist/devices/speaker.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 +24 -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 +143 -0
- package/dist/dgram/dgram.d.ts.map +1 -0
- package/dist/dgram/dgram.js +114 -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 +77 -23
- package/dist/dgram/mb_mdns.js.map +1 -0
- package/dist/dgram/mdns.d.ts +371 -0
- package/dist/dgram/mdns.d.ts.map +1 -0
- package/dist/dgram/mdns.js +371 -139
- package/dist/dgram/mdns.js.map +1 -0
- package/dist/dgram/mdnsReflectorClient.d.ts +88 -0
- package/dist/dgram/mdnsReflectorClient.d.ts.map +1 -0
- package/dist/dgram/mdnsReflectorClient.js +71 -5
- package/dist/dgram/mdnsReflectorClient.js.map +1 -0
- package/dist/dgram/mdnsReflectorServer.d.ts +78 -0
- package/dist/dgram/mdnsReflectorServer.d.ts.map +1 -0
- package/dist/dgram/mdnsReflectorServer.js +73 -8
- package/dist/dgram/mdnsReflectorServer.js.map +1 -0
- package/dist/dgram/mdnsReflectorTypes.d.ts +28 -0
- package/dist/dgram/mdnsReflectorTypes.d.ts.map +1 -0
- package/dist/dgram/mdnsReflectorTypes.js +24 -1
- package/dist/dgram/mdnsReflectorTypes.js.map +1 -0
- package/dist/dgram/multicast.d.ts +67 -0
- package/dist/dgram/multicast.d.ts.map +1 -0
- package/dist/dgram/multicast.js +62 -1
- package/dist/dgram/multicast.js.map +1 -0
- package/dist/dgram/unicast.d.ts +64 -0
- package/dist/dgram/unicast.d.ts.map +1 -0
- package/dist/dgram/unicast.js +60 -0
- package/dist/dgram/unicast.js.map +1 -0
- package/dist/frontend.d.ts +245 -0
- package/dist/frontend.d.ts.map +1 -0
- package/dist/frontend.js +485 -38
- package/dist/frontend.js.map +1 -0
- package/dist/frontendTypes.d.ts +529 -0
- package/dist/frontendTypes.d.ts.map +1 -0
- package/dist/frontendTypes.js +45 -0
- package/dist/frontendTypes.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 +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/jestutils/export.d.ts +2 -0
- package/dist/jestutils/export.d.ts.map +1 -0
- package/dist/jestutils/export.js +1 -0
- package/dist/jestutils/export.js.map +1 -0
- package/dist/jestutils/jestHelpers.d.ts +345 -0
- package/dist/jestutils/jestHelpers.d.ts.map +1 -0
- package/dist/jestutils/jestHelpers.js +371 -14
- package/dist/jestutils/jestHelpers.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/matterNode.d.ts +342 -0
- package/dist/matterNode.d.ts.map +1 -0
- package/dist/matterNode.js +369 -8
- package/dist/matterNode.js.map +1 -0
- package/dist/matterbridge.d.ts +505 -0
- package/dist/matterbridge.d.ts.map +1 -0
- package/dist/matterbridge.js +824 -46
- package/dist/matterbridge.js.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts +41 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.js +38 -0
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
- package/dist/matterbridgeBehaviors.d.ts +2404 -0
- package/dist/matterbridgeBehaviors.d.ts.map +1 -0
- package/dist/matterbridgeBehaviors.js +68 -5
- package/dist/matterbridgeBehaviors.js.map +1 -0
- package/dist/matterbridgeDeviceTypes.d.ts +698 -0
- package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
- package/dist/matterbridgeDeviceTypes.js +635 -14
- package/dist/matterbridgeDeviceTypes.js.map +1 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +41 -0
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
- package/dist/matterbridgeDynamicPlatform.js +38 -0
- package/dist/matterbridgeDynamicPlatform.js.map +1 -0
- package/dist/matterbridgeEndpoint.d.ts +1507 -0
- package/dist/matterbridgeEndpoint.d.ts.map +1 -0
- package/dist/matterbridgeEndpoint.js +1457 -53
- package/dist/matterbridgeEndpoint.js.map +1 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +787 -0
- package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
- package/dist/matterbridgeEndpointHelpers.js +483 -20
- package/dist/matterbridgeEndpointHelpers.js.map +1 -0
- package/dist/matterbridgeEndpointTypes.d.ts +166 -0
- package/dist/matterbridgeEndpointTypes.d.ts.map +1 -0
- package/dist/matterbridgeEndpointTypes.js +25 -0
- package/dist/matterbridgeEndpointTypes.js.map +1 -0
- package/dist/matterbridgePlatform.d.ts +539 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +451 -1
- package/dist/matterbridgePlatform.js.map +1 -0
- package/dist/matterbridgeTypes.d.ts +252 -0
- package/dist/matterbridgeTypes.d.ts.map +1 -0
- package/dist/matterbridgeTypes.js +26 -0
- package/dist/matterbridgeTypes.js.map +1 -0
- package/dist/pluginManager.d.ts +372 -0
- package/dist/pluginManager.d.ts.map +1 -0
- package/dist/pluginManager.js +341 -5
- package/dist/pluginManager.js.map +1 -0
- package/dist/shelly.d.ts +181 -0
- package/dist/shelly.d.ts.map +1 -0
- package/dist/shelly.js +178 -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 +84 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +93 -1
- package/dist/update.js.map +1 -0
- package/dist/utils/colorUtils.d.ts +101 -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 +66 -0
- package/dist/utils/commandLine.d.ts.map +1 -0
- package/dist/utils/commandLine.js +60 -0
- package/dist/utils/commandLine.js.map +1 -0
- package/dist/utils/copyDirectory.d.ts +35 -0
- package/dist/utils/copyDirectory.d.ts.map +1 -0
- package/dist/utils/copyDirectory.js +37 -0
- 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 +45 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +42 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/export.d.ts +13 -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/format.d.ts +53 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +49 -0
- package/dist/utils/format.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/inspector.d.ts +87 -0
- package/dist/utils/inspector.d.ts.map +1 -0
- package/dist/utils/inspector.js +69 -1
- package/dist/utils/inspector.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 +93 -0
- package/dist/utils/isValid.js.map +1 -0
- package/dist/utils/network.d.ts +140 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +126 -6
- 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 +71 -1
- package/dist/utils/spawn.js.map +1 -0
- package/dist/utils/tracker.d.ts +108 -0
- package/dist/utils/tracker.d.ts.map +1 -0
- package/dist/utils/tracker.js +64 -1
- package/dist/utils/tracker.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/dist/workerGlobalPrefix.d.ts +25 -0
- package/dist/workerGlobalPrefix.d.ts.map +1 -0
- package/dist/workerGlobalPrefix.js +37 -5
- package/dist/workerGlobalPrefix.js.map +1 -0
- package/dist/workerTypes.d.ts +52 -0
- package/dist/workerTypes.d.ts.map +1 -0
- package/dist/workerTypes.js +24 -0
- package/dist/workerTypes.js.map +1 -0
- package/dist/workers.d.ts +69 -0
- package/dist/workers.d.ts.map +1 -0
- package/dist/workers.js +68 -4
- package/dist/workers.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
package/dist/dgram/mdns.js
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
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, GREEN, idn, MAGENTA, nf, rs } from 'node-ansi-logger';
|
|
25
|
+
// Utils imports
|
|
2
26
|
import { hasParameter } from '../utils/commandLine.js';
|
|
27
|
+
// Net imports
|
|
3
28
|
import { Multicast } from './multicast.js';
|
|
4
29
|
export var DnsRecordType;
|
|
5
30
|
(function (DnsRecordType) {
|
|
@@ -91,6 +116,7 @@ export var DnsRecordType;
|
|
|
91
116
|
DnsRecordType[DnsRecordType["DOA"] = 259] = "DOA";
|
|
92
117
|
DnsRecordType[DnsRecordType["AMTRELAY"] = 260] = "AMTRELAY";
|
|
93
118
|
DnsRecordType[DnsRecordType["ZONEVERSION"] = 261] = "ZONEVERSION";
|
|
119
|
+
// 262-32767 are unassigned/reserved
|
|
94
120
|
DnsRecordType[DnsRecordType["TA"] = 32768] = "TA";
|
|
95
121
|
DnsRecordType[DnsRecordType["DLV"] = 32769] = "DLV";
|
|
96
122
|
})(DnsRecordType || (DnsRecordType = {}));
|
|
@@ -104,34 +130,65 @@ export var DnsClass;
|
|
|
104
130
|
export var DnsClassFlag;
|
|
105
131
|
(function (DnsClassFlag) {
|
|
106
132
|
DnsClassFlag[DnsClassFlag["FLUSH"] = 32768] = "FLUSH";
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
107
134
|
DnsClassFlag[DnsClassFlag["QU"] = 32768] = "QU";
|
|
108
135
|
})(DnsClassFlag || (DnsClassFlag = {}));
|
|
136
|
+
/**
|
|
137
|
+
* Checks if a given message is an mDNS message.
|
|
138
|
+
*
|
|
139
|
+
* @param {Buffer} message - The message buffer to check.
|
|
140
|
+
* @returns {boolean} True if the message is an mDNS message, false otherwise.
|
|
141
|
+
*/
|
|
109
142
|
export function isMdns(message) {
|
|
110
143
|
if (!message || message.length < 12)
|
|
111
144
|
return false;
|
|
112
145
|
const id = message.readUInt16BE(0);
|
|
113
146
|
return id === 0;
|
|
114
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Checks if a given mDNS message is a query.
|
|
150
|
+
*
|
|
151
|
+
* @param {Buffer} message - The mDNS message buffer to check.
|
|
152
|
+
* @returns {boolean} True if the message is a query, false otherwise.
|
|
153
|
+
*/
|
|
115
154
|
export function isMdnsQuery(message) {
|
|
116
155
|
if (message.length < 12)
|
|
117
156
|
return false;
|
|
118
157
|
const id = message.readUInt16BE(0);
|
|
119
158
|
const flags = message.readUInt16BE(2);
|
|
120
|
-
const qr = (flags & 0x8000) >> 15;
|
|
159
|
+
const qr = (flags & 0x8000) >> 15; // Bit 15: 0=query, 1=response.
|
|
121
160
|
return id == 0 && qr === 0;
|
|
122
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Checks if a given mDNS message is a query.
|
|
164
|
+
*
|
|
165
|
+
* @param {Buffer} message - The mDNS message buffer to check.
|
|
166
|
+
* @returns {boolean} True if the message is a query, false otherwise.
|
|
167
|
+
*/
|
|
123
168
|
export function isMdnsResponse(message) {
|
|
124
169
|
if (message.length < 12)
|
|
125
170
|
return false;
|
|
126
171
|
const id = message.readUInt16BE(0);
|
|
127
172
|
const flags = message.readUInt16BE(2);
|
|
128
|
-
const qr = (flags & 0x8000) >> 15;
|
|
173
|
+
const qr = (flags & 0x8000) >> 15; // Bit 15: 0=query, 1=response.
|
|
129
174
|
return id == 0 && qr === 1;
|
|
130
175
|
}
|
|
131
176
|
export class Mdns extends Multicast {
|
|
132
177
|
deviceQueries = new Map();
|
|
133
178
|
deviceResponses = new Map();
|
|
134
179
|
filters = [];
|
|
180
|
+
/**
|
|
181
|
+
* Creates an instance of the Mdns class.
|
|
182
|
+
*
|
|
183
|
+
* @param {string} name - The internal name of the mDNS server for the logs.
|
|
184
|
+
* @param {string} multicastAddress - The multicast address for mDNS (i.e. 224.0.0.251 for udp4 or ff02::fb for udp6).
|
|
185
|
+
* @param {number} multicastPort - The port for mDNS (i.e. 5353).
|
|
186
|
+
* @param {('udp4' | 'udp6')} socketType - The type of socket to create (either 'udp4' or 'udp6').
|
|
187
|
+
* @param {boolean} [reuseAddr] - Whether to reuse the address. Defaults to true.
|
|
188
|
+
* @param {string} [interfaceName] - The optional name of the network interface to use.
|
|
189
|
+
* @param {string} [interfaceAddress] - The optional IP address of the network interface to use.
|
|
190
|
+
* @param {string} [outgoingInterfaceAddress] - The address of the outgoing network interface.
|
|
191
|
+
*/
|
|
135
192
|
constructor(name, multicastAddress, multicastPort, socketType, reuseAddr = true, interfaceName, interfaceAddress, outgoingInterfaceAddress) {
|
|
136
193
|
super(name, multicastAddress, multicastPort, socketType, reuseAddr, interfaceName, interfaceAddress, outgoingInterfaceAddress);
|
|
137
194
|
}
|
|
@@ -151,16 +208,17 @@ export class Mdns extends Multicast {
|
|
|
151
208
|
this.onQuery(rinfo, result);
|
|
152
209
|
}
|
|
153
210
|
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) ||
|
|
211
|
+
const ptr = result.answers?.find((record) => record.name === '_shelly._tcp.local' && record.type === 12 /* DnsRecordType.PTR */) ||
|
|
212
|
+
result.answers?.find((record) => record.name === '_http._tcp.local' && record.type === 12 /* DnsRecordType.PTR */) ||
|
|
213
|
+
result.answers?.find((record) => record.type === 12 /* DnsRecordType.PTR */) ||
|
|
214
|
+
result.answers?.find((record) => record.type === 16 /* DnsRecordType.TXT */) ||
|
|
158
215
|
result.answers
|
|
159
216
|
? result.answers[0]
|
|
160
|
-
: undefined;
|
|
161
|
-
this.deviceResponses.set(rinfo.address, { rinfo, response: result, dataPTR: ptr?.type === 12 ? ptr?.data : ptr?.name });
|
|
217
|
+
: undefined; // Fallback to the first answer if no PTR or TXT found
|
|
218
|
+
this.deviceResponses.set(rinfo.address, { rinfo, response: result, dataPTR: ptr?.type === 12 /* DnsRecordType.PTR */ ? ptr?.data : ptr?.name });
|
|
162
219
|
this.onResponse(rinfo, result);
|
|
163
220
|
}
|
|
221
|
+
// Apply filters if any
|
|
164
222
|
if (this.filters.length > 0) {
|
|
165
223
|
this.log.debug(`mDNS message filtered out by filters: ${this.filters.join(', ')}`);
|
|
166
224
|
for (const filter of this.filters) {
|
|
@@ -182,20 +240,28 @@ export class Mdns extends Multicast {
|
|
|
182
240
|
this.log.error(`Error decoding mDNS message: ${error instanceof Error ? error.message : error}`);
|
|
183
241
|
}
|
|
184
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Decodes an mDNS message, including the header, question section, answer section,
|
|
245
|
+
* authority section, and additional section.
|
|
246
|
+
*
|
|
247
|
+
* @param {Buffer} msg - The raw mDNS message buffer.
|
|
248
|
+
* @returns {MdnsMessage} An object representing the decoded mDNS message.
|
|
249
|
+
* @throws {Error} if the message is too short.
|
|
250
|
+
*/
|
|
185
251
|
decodeMdnsMessage(msg) {
|
|
186
252
|
if (msg.length < 12) {
|
|
187
253
|
throw new Error('mDNS message too short');
|
|
188
254
|
}
|
|
189
255
|
const id = msg.readUInt16BE(0);
|
|
190
256
|
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;
|
|
257
|
+
const qr = (flags & 0x8000) >> 15; // Bit 15: 0=query, 1=response (QR = Query/Response).
|
|
258
|
+
const opcode = (flags & 0x7800) >> 11; // Bits 14-11 (OPCODE: kind of query; in mDNS this is typically 0 = standard query).
|
|
259
|
+
const aa = Boolean(flags & 0x0400); // Bit 10 (AA: Authoritative Answer; sender claims authority for the name).
|
|
260
|
+
const tc = Boolean(flags & 0x0200); // Bit 9 (TC: TrunCation; message was truncated due to length limits).
|
|
261
|
+
const rd = Boolean(flags & 0x0100); // Bit 8 (RD: Recursion Desired; usually 0 in mDNS).
|
|
262
|
+
const ra = Boolean(flags & 0x0080); // Bit 7 (RA: Recursion Available; meaningful for recursive resolvers, usually 0 in mDNS).
|
|
263
|
+
const z = (flags & 0x0070) >> 4; // Bits 6-4 (Z: reserved in DNS; should be 0 in classic DNS/mDNS).
|
|
264
|
+
const rcode = flags & 0x000f; // Bits 3-0 (RCODE: Response Code; 0 = NoError, 3 = NXDomain, etc).
|
|
199
265
|
const qdCount = msg.readUInt16BE(4);
|
|
200
266
|
const anCount = msg.readUInt16BE(6);
|
|
201
267
|
const nsCount = msg.readUInt16BE(8);
|
|
@@ -220,6 +286,7 @@ export class Mdns extends Multicast {
|
|
|
220
286
|
additionals: [],
|
|
221
287
|
};
|
|
222
288
|
let offset = 12;
|
|
289
|
+
// Decode the question section.
|
|
223
290
|
for (let i = 0; i < qdCount; i++) {
|
|
224
291
|
const qnameResult = this.decodeDnsName(msg, offset);
|
|
225
292
|
const qname = qnameResult.name;
|
|
@@ -230,16 +297,19 @@ export class Mdns extends Multicast {
|
|
|
230
297
|
offset += 2;
|
|
231
298
|
mdnsMessage.questions?.push({ name: qname, type: qtype, class: qclass });
|
|
232
299
|
}
|
|
300
|
+
// Decode the answer section.
|
|
233
301
|
for (let i = 0; i < anCount; i++) {
|
|
234
302
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
235
303
|
mdnsMessage.answers?.push(rrResult.record);
|
|
236
304
|
offset = rrResult.newOffset;
|
|
237
305
|
}
|
|
306
|
+
// Decode the authority (NS) section.
|
|
238
307
|
for (let i = 0; i < nsCount; i++) {
|
|
239
308
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
240
309
|
mdnsMessage.authorities?.push(rrResult.record);
|
|
241
310
|
offset = rrResult.newOffset;
|
|
242
311
|
}
|
|
312
|
+
// Decode the additional records section.
|
|
243
313
|
for (let i = 0; i < arCount; i++) {
|
|
244
314
|
const rrResult = this.decodeResourceRecord(msg, offset);
|
|
245
315
|
mdnsMessage.additionals?.push(rrResult.record);
|
|
@@ -247,15 +317,25 @@ export class Mdns extends Multicast {
|
|
|
247
317
|
}
|
|
248
318
|
return mdnsMessage;
|
|
249
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Decodes a DNS name from a buffer, handling compression.
|
|
322
|
+
*
|
|
323
|
+
* @param {Buffer} msg - The full mDNS message buffer.
|
|
324
|
+
* @param {number} offset - The offset at which the DNS name starts.
|
|
325
|
+
* @returns {{ name: string; newOffset: number }} An object with the decoded name and the new offset.
|
|
326
|
+
* @throws {Error} if the offset exceeds the buffer length or too many iterations are performed.
|
|
327
|
+
*/
|
|
250
328
|
decodeDnsName(msg, offset) {
|
|
251
329
|
const labels = [];
|
|
252
330
|
let jumped = false;
|
|
253
331
|
let originalOffset = offset;
|
|
254
|
-
let iterations = 0;
|
|
332
|
+
let iterations = 0; // Prevent infinite loops
|
|
255
333
|
while (true) {
|
|
334
|
+
// Safety guard: prevent infinite loops in malformed messages.
|
|
256
335
|
if (iterations++ > 1000) {
|
|
257
336
|
throw new Error('Too many iterations while decoding DNS name. Possible malformed message.');
|
|
258
337
|
}
|
|
338
|
+
// Check that offset is within buffer bounds.
|
|
259
339
|
if (offset >= msg.length) {
|
|
260
340
|
throw new Error('Offset exceeds buffer length while decoding DNS name.');
|
|
261
341
|
}
|
|
@@ -264,7 +344,9 @@ export class Mdns extends Multicast {
|
|
|
264
344
|
offset++;
|
|
265
345
|
break;
|
|
266
346
|
}
|
|
347
|
+
// Check for pointer (first two bits are 11)
|
|
267
348
|
if ((len & 0xc0) === 0xc0) {
|
|
349
|
+
// Ensure the pointer has two bytes available.
|
|
268
350
|
if (offset + 1 >= msg.length) {
|
|
269
351
|
throw new Error('Incomplete pointer encountered while decoding DNS name.');
|
|
270
352
|
}
|
|
@@ -277,6 +359,7 @@ export class Mdns extends Multicast {
|
|
|
277
359
|
continue;
|
|
278
360
|
}
|
|
279
361
|
offset++;
|
|
362
|
+
// Check that the label length doesn't go beyond the buffer.
|
|
280
363
|
if (offset + len > msg.length) {
|
|
281
364
|
throw new Error('Label length exceeds buffer bounds while decoding DNS name.');
|
|
282
365
|
}
|
|
@@ -285,6 +368,15 @@ export class Mdns extends Multicast {
|
|
|
285
368
|
}
|
|
286
369
|
return { name: labels.join('.'), newOffset: jumped ? originalOffset : offset };
|
|
287
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Encodes a domain name into the DNS label format.
|
|
373
|
+
*
|
|
374
|
+
* For example, "example.local" becomes:
|
|
375
|
+
* [7] "example" [5] "local" [0]
|
|
376
|
+
*
|
|
377
|
+
* @param {string} name - The domain name to encode.
|
|
378
|
+
* @returns {Buffer} The encoded domain name as a Buffer.
|
|
379
|
+
*/
|
|
288
380
|
encodeDnsName(name) {
|
|
289
381
|
const labels = name.split('.');
|
|
290
382
|
const buffers = labels.map((label) => {
|
|
@@ -292,8 +384,25 @@ export class Mdns extends Multicast {
|
|
|
292
384
|
lenBuf.writeUInt8(label.length, 0);
|
|
293
385
|
return Buffer.concat([lenBuf, Buffer.from(label)]);
|
|
294
386
|
});
|
|
387
|
+
// Append the null byte to terminate the name.
|
|
295
388
|
return Buffer.concat([...buffers, Buffer.from([0])]);
|
|
296
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Encodes TXT record RDATA.
|
|
392
|
+
*
|
|
393
|
+
* In DNS/mDNS, TXT RDATA is a sequence of one or more <character-string>,
|
|
394
|
+
* each encoded as: [length byte][UTF-8 bytes].
|
|
395
|
+
*
|
|
396
|
+
* @param {string[]} txt - Array of TXT entries, e.g. ["key=value", "path=/"].
|
|
397
|
+
* @returns {Buffer} Encoded TXT RDATA.
|
|
398
|
+
* @throws {Error} If any entry exceeds 255 bytes.
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* const txtRdata = mdns.encodeTxtRdata(['txtvers=1', 'path=/']);
|
|
402
|
+
* mdns.sendResponse([
|
|
403
|
+
* { name: 'example._http._tcp.local', rtype: DnsRecordType.TXT, rclass: DnsClass.IN | DnsClassFlag.FLUSH, ttl: 120, rdata: txtRdata },
|
|
404
|
+
* ]);
|
|
405
|
+
*/
|
|
297
406
|
encodeTxtRdata(txt) {
|
|
298
407
|
const parts = txt.map((entry) => {
|
|
299
408
|
const value = Buffer.from(entry, 'utf8');
|
|
@@ -303,6 +412,21 @@ export class Mdns extends Multicast {
|
|
|
303
412
|
});
|
|
304
413
|
return Buffer.concat(parts);
|
|
305
414
|
}
|
|
415
|
+
/**
|
|
416
|
+
* Encodes SRV record RDATA.
|
|
417
|
+
*
|
|
418
|
+
* SRV RDATA layout (RFC 2782):
|
|
419
|
+
* - priority (2 bytes)
|
|
420
|
+
* - weight (2 bytes)
|
|
421
|
+
* - port (2 bytes)
|
|
422
|
+
* - target (DNS name)
|
|
423
|
+
*
|
|
424
|
+
* @param {number} priority - SRV priority.
|
|
425
|
+
* @param {number} weight - SRV weight.
|
|
426
|
+
* @param {number} port - Service port.
|
|
427
|
+
* @param {string} target - Target hostname (e.g. "matterbridge.local").
|
|
428
|
+
* @returns {Buffer} Encoded SRV RDATA.
|
|
429
|
+
*/
|
|
306
430
|
encodeSrvRdata(priority, weight, port, target) {
|
|
307
431
|
const fixed = Buffer.alloc(6);
|
|
308
432
|
fixed.writeUInt16BE(priority, 0);
|
|
@@ -310,6 +434,13 @@ export class Mdns extends Multicast {
|
|
|
310
434
|
fixed.writeUInt16BE(port, 4);
|
|
311
435
|
return Buffer.concat([fixed, this.encodeDnsName(target)]);
|
|
312
436
|
}
|
|
437
|
+
/**
|
|
438
|
+
* Encodes an IPv4 address for an A record RDATA (4 bytes).
|
|
439
|
+
*
|
|
440
|
+
* @param {string} ipv4 - IPv4 address, e.g. "192.168.1.10".
|
|
441
|
+
* @returns {Buffer} 4-byte buffer.
|
|
442
|
+
* @throws {Error} If the address is not a valid dotted-quad.
|
|
443
|
+
*/
|
|
313
444
|
encodeA(ipv4) {
|
|
314
445
|
const parts = ipv4.split('.').map((p) => Number(p));
|
|
315
446
|
if (parts.length !== 4 || parts.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {
|
|
@@ -317,8 +448,19 @@ export class Mdns extends Multicast {
|
|
|
317
448
|
}
|
|
318
449
|
return Buffer.from(parts);
|
|
319
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* Encodes an IPv6 address for an AAAA record RDATA (16 bytes).
|
|
453
|
+
*
|
|
454
|
+
* Supports the "::" zero-compression form and ignores an optional scope id
|
|
455
|
+
* suffix (e.g. "fe80::1%12" or "fe80::1%eth0").
|
|
456
|
+
*
|
|
457
|
+
* @param {string} ipv6WithOptionalScope - IPv6 address (optionally with scope id).
|
|
458
|
+
* @returns {Buffer} 16-byte buffer.
|
|
459
|
+
* @throws {Error} If the address is not a valid IPv6 literal.
|
|
460
|
+
*/
|
|
320
461
|
encodeAAAA(ipv6WithOptionalScope) {
|
|
321
462
|
const ipv6 = ipv6WithOptionalScope.split('%')[0];
|
|
463
|
+
// Expand IPv6 to 8 groups of 16-bit words.
|
|
322
464
|
const [left, right] = ipv6.split('::');
|
|
323
465
|
const leftParts = left ? left.split(':').filter(Boolean) : [];
|
|
324
466
|
const rightParts = right ? right.split(':').filter(Boolean) : [];
|
|
@@ -347,10 +489,19 @@ export class Mdns extends Multicast {
|
|
|
347
489
|
return [(word >> 8) & 0xff, word & 0xff];
|
|
348
490
|
}));
|
|
349
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Decodes a DNS resource record.
|
|
494
|
+
*
|
|
495
|
+
* @param {Buffer} msg - The full mDNS message buffer.
|
|
496
|
+
* @param {number} offset - The offset at which the resource record starts.
|
|
497
|
+
* @returns {{ record: MdnsRecord; newOffset: number }} An object containing the decoded record and the new offset.
|
|
498
|
+
*/
|
|
350
499
|
decodeResourceRecord(msg, offset) {
|
|
500
|
+
// Decode the NAME field (which may be compressed)
|
|
351
501
|
const nameResult = this.decodeDnsName(msg, offset);
|
|
352
502
|
const name = nameResult.name;
|
|
353
503
|
offset = nameResult.newOffset;
|
|
504
|
+
// Read TYPE (16 bits), CLASS (16 bits), TTL (32 bits), and RDLENGTH (16 bits)
|
|
354
505
|
const type = msg.readUInt16BE(offset);
|
|
355
506
|
offset += 2;
|
|
356
507
|
const rrclass = msg.readUInt16BE(offset);
|
|
@@ -360,12 +511,14 @@ export class Mdns extends Multicast {
|
|
|
360
511
|
const rdlength = msg.readUInt16BE(offset);
|
|
361
512
|
offset += 2;
|
|
362
513
|
let data = '';
|
|
363
|
-
if (type === 12) {
|
|
514
|
+
if (type === 12 /* DnsRecordType.PTR */) {
|
|
515
|
+
// PTR record (type 12): decode its RDATA as a domain name.
|
|
364
516
|
const ptrResult = this.decodeDnsName(msg, offset);
|
|
365
517
|
data = ptrResult.name;
|
|
366
518
|
offset += rdlength;
|
|
367
519
|
}
|
|
368
|
-
else if (type === 16) {
|
|
520
|
+
else if (type === 16 /* DnsRecordType.TXT */) {
|
|
521
|
+
// TXT record: may consist of one or more length-prefixed strings.
|
|
369
522
|
const txtStrings = [];
|
|
370
523
|
const end = offset + rdlength;
|
|
371
524
|
while (offset < end) {
|
|
@@ -377,7 +530,8 @@ export class Mdns extends Multicast {
|
|
|
377
530
|
}
|
|
378
531
|
data = txtStrings.join(', ');
|
|
379
532
|
}
|
|
380
|
-
else if (type === 33) {
|
|
533
|
+
else if (type === 33 /* DnsRecordType.SRV */) {
|
|
534
|
+
// SRV record (type === 33): consists of 2 bytes for priority, 2 for weight, 2 for port, followed by the target domain name.
|
|
381
535
|
const priority = msg.readUInt16BE(offset);
|
|
382
536
|
const weight = msg.readUInt16BE(offset + 2);
|
|
383
537
|
const port = msg.readUInt16BE(offset + 4);
|
|
@@ -391,13 +545,16 @@ export class Mdns extends Multicast {
|
|
|
391
545
|
});
|
|
392
546
|
offset = srvTargetResult.newOffset;
|
|
393
547
|
}
|
|
394
|
-
else if (type === 1) {
|
|
548
|
+
else if (type === 1 /* DnsRecordType.A */) {
|
|
549
|
+
// A record (type 1): an IPv4 address stored in 4 bytes.
|
|
395
550
|
const ipBytes = msg.slice(offset, offset + 4);
|
|
396
551
|
data = Array.from(ipBytes).join('.');
|
|
397
552
|
offset += 4;
|
|
398
553
|
}
|
|
399
|
-
else if (type === 28) {
|
|
554
|
+
else if (type === 28 /* DnsRecordType.AAAA */) {
|
|
555
|
+
// AAAA record (type 28): IPv6 address stored in 16 bytes.
|
|
400
556
|
const ipBytes = msg.slice(offset, offset + 16);
|
|
557
|
+
// Convert the 16 bytes into an IPv6 address string (colon-separated)
|
|
401
558
|
const ipv6Parts = [];
|
|
402
559
|
for (let i = 0; i < 16; i += 2) {
|
|
403
560
|
ipv6Parts.push(ipBytes.readUInt16BE(i).toString(16));
|
|
@@ -405,10 +562,14 @@ export class Mdns extends Multicast {
|
|
|
405
562
|
data = ipv6Parts.join(':');
|
|
406
563
|
offset += 16;
|
|
407
564
|
}
|
|
408
|
-
else if (type === 47) {
|
|
565
|
+
else if (type === 47 /* DnsRecordType.NSEC */) {
|
|
566
|
+
// NSEC record: RDATA consists of:
|
|
567
|
+
// - Next Domain Name (in DNS label format)
|
|
568
|
+
// - Type Bit Maps (variable length)
|
|
409
569
|
const { name: nextDomain, newOffset } = this.decodeDnsName(msg, offset);
|
|
410
570
|
const nextDomainLength = newOffset - offset;
|
|
411
571
|
offset = newOffset;
|
|
572
|
+
// Calculate the remaining length for the type bit maps.
|
|
412
573
|
const bitmapLength = rdlength - nextDomainLength;
|
|
413
574
|
const bitmapData = msg.slice(offset, offset + bitmapLength);
|
|
414
575
|
const types = [];
|
|
@@ -435,6 +596,7 @@ export class Mdns extends Multicast {
|
|
|
435
596
|
offset += bitmapLength;
|
|
436
597
|
}
|
|
437
598
|
else {
|
|
599
|
+
// Fall back
|
|
438
600
|
data = msg.slice(offset, offset + rdlength).toString('hex');
|
|
439
601
|
offset += rdlength;
|
|
440
602
|
}
|
|
@@ -443,19 +605,30 @@ export class Mdns extends Multicast {
|
|
|
443
605
|
newOffset: offset,
|
|
444
606
|
};
|
|
445
607
|
}
|
|
608
|
+
/**
|
|
609
|
+
* Sends a DNS query with multiple questions.
|
|
610
|
+
*
|
|
611
|
+
* @param {Array<{ name: string; type: number; class: number; unicastResponse?: boolean }>} questions - Array of questions
|
|
612
|
+
* to include in the query.
|
|
613
|
+
* @returns {Buffer<ArrayBuffer>} The constructed query buffer.
|
|
614
|
+
*
|
|
615
|
+
* @remarks
|
|
616
|
+
* Each question should have a name (e.g., "_http._tcp.local"), type (e.g., DnsRecordType.PTR), class (e.g., DnsClass.IN),
|
|
617
|
+
* and an optional unicastResponse flag (this will add the DnsClassFlag.QU flag to the query).
|
|
618
|
+
*/
|
|
446
619
|
sendQuery(questions) {
|
|
447
620
|
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);
|
|
621
|
+
header.writeUInt16BE(0, 0); // ID
|
|
622
|
+
header.writeUInt16BE(0, 2); // Flags
|
|
623
|
+
header.writeUInt16BE(questions.length, 4); // QDCOUNT
|
|
624
|
+
header.writeUInt16BE(0, 6); // ANCOUNT
|
|
625
|
+
header.writeUInt16BE(0, 8); // NSCOUNT
|
|
626
|
+
header.writeUInt16BE(0, 10); // ARCOUNT
|
|
454
627
|
const questionBuffers = questions.map(({ name, type: qtype, class: qclass, unicastResponse = false }) => {
|
|
455
628
|
const qname = this.encodeDnsName(name);
|
|
456
629
|
const qfields = Buffer.alloc(4);
|
|
457
630
|
qfields.writeUInt16BE(qtype, 0);
|
|
458
|
-
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 : qclass, 2);
|
|
631
|
+
qfields.writeUInt16BE(unicastResponse ? qclass | 32768 /* DnsClassFlag.QU */ : qclass, 2);
|
|
459
632
|
return Buffer.concat([qname, qfields]);
|
|
460
633
|
});
|
|
461
634
|
const query = Buffer.concat([header, ...questionBuffers]);
|
|
@@ -475,31 +648,52 @@ export class Mdns extends Multicast {
|
|
|
475
648
|
});
|
|
476
649
|
return query;
|
|
477
650
|
}
|
|
651
|
+
/**
|
|
652
|
+
* Constructs an mDNS response packet and sends it to the multicast address and port.
|
|
653
|
+
*
|
|
654
|
+
* @param {Array<{ name: string; rtype: number; rclass: number; ttl: number; rdata: Buffer }>} answers - Array of answer records.
|
|
655
|
+
* @returns {Buffer<ArrayBuffer>} The constructed response buffer.
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* const ptrRdata = mdnsIpv4.encodeDnsName('matterbridge._http._tcp.local');
|
|
659
|
+
* mdnsIpv4.sendResponse([{ name: '_http._tcp.local', rtype: DnsRecordType.PTR, rclass: DnsClass.IN, ttl: 120, rdata: ptrRdata }]);
|
|
660
|
+
*/
|
|
478
661
|
sendResponse(answers) {
|
|
479
662
|
if (!Array.isArray(answers) || answers.length === 0) {
|
|
480
663
|
throw new Error('sendResponse requires a non-empty answers array');
|
|
481
664
|
}
|
|
665
|
+
// Create a 12-byte DNS header.
|
|
482
666
|
const header = Buffer.alloc(12);
|
|
483
|
-
header.writeUInt16BE(0, 0);
|
|
667
|
+
header.writeUInt16BE(0, 0); // ID is set to 0 in mDNS.
|
|
668
|
+
// Set flags: QR (response) bit and AA (authoritative answer) bit.
|
|
484
669
|
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);
|
|
670
|
+
header.writeUInt16BE(0, 4); // QDCOUNT: 0 questions in response.
|
|
671
|
+
header.writeUInt16BE(answers.length, 6); // ANCOUNT: number of answer records.
|
|
672
|
+
header.writeUInt16BE(0, 8); // NSCOUNT: 0 authority records.
|
|
673
|
+
header.writeUInt16BE(0, 10); // ARCOUNT: 0 additional records.
|
|
489
674
|
const answerBuffers = answers.map(({ name, rtype, rclass, ttl, rdata }) => {
|
|
675
|
+
// Encode the domain name in DNS label format.
|
|
490
676
|
const aname = this.encodeDnsName(name);
|
|
677
|
+
// Prepare the fixed part of the answer record:
|
|
678
|
+
// - 2 bytes for qtype,
|
|
679
|
+
// - 2 bytes for qclass,
|
|
680
|
+
// - 4 bytes for TTL,
|
|
681
|
+
// - 2 bytes for RDLENGTH (length of the rdata).
|
|
491
682
|
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);
|
|
683
|
+
answerFixed.writeUInt16BE(rtype, 0); // Record type.
|
|
684
|
+
answerFixed.writeUInt16BE(rclass, 2); // Record class.
|
|
685
|
+
answerFixed.writeUInt32BE(ttl, 4); // Time-to-live.
|
|
686
|
+
answerFixed.writeUInt16BE(rdata.length, 8); // RDLENGTH.
|
|
687
|
+
// Concatenate the answer: encoded name, fixed fields, and resource data.
|
|
496
688
|
return Buffer.concat([aname, answerFixed, rdata]);
|
|
497
689
|
});
|
|
690
|
+
// Concatenate header and answers to form the complete mDNS response packet.
|
|
498
691
|
const response = Buffer.concat([header, ...answerBuffers]);
|
|
499
692
|
if (hasParameter('v') || hasParameter('verbose')) {
|
|
500
693
|
const decoded = this.decodeMdnsMessage(response);
|
|
501
694
|
this.logMdnsMessage(decoded, undefined, 'Sending response mDNS message');
|
|
502
695
|
}
|
|
696
|
+
// Send the response packet via the socket.
|
|
503
697
|
this.socket.send(response, 0, response.length, this.multicastPort, this.multicastAddress, (error) => {
|
|
504
698
|
if (error) {
|
|
505
699
|
this.log.error(`Dgram mDNS server failed to send response message: ${error instanceof Error ? error.message : error}`);
|
|
@@ -512,116 +706,128 @@ export class Mdns extends Multicast {
|
|
|
512
706
|
});
|
|
513
707
|
return response;
|
|
514
708
|
}
|
|
709
|
+
/**
|
|
710
|
+
* Converts a DNS record type numeric value to its string representation.
|
|
711
|
+
*
|
|
712
|
+
* @param {number} type - The numeric DNS record type.
|
|
713
|
+
* @returns {string} The string representation of the record type.
|
|
714
|
+
*/
|
|
515
715
|
dnsTypeToString(type) {
|
|
516
716
|
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',
|
|
717
|
+
[1 /* DnsRecordType.A */]: 'A',
|
|
718
|
+
[2 /* DnsRecordType.NS */]: 'NS',
|
|
719
|
+
[3 /* DnsRecordType.MD */]: 'MD',
|
|
720
|
+
[4 /* DnsRecordType.MF */]: 'MF',
|
|
721
|
+
[5 /* DnsRecordType.CNAME */]: 'CNAME',
|
|
722
|
+
[6 /* DnsRecordType.SOA */]: 'SOA',
|
|
723
|
+
[7 /* DnsRecordType.MB */]: 'MB',
|
|
724
|
+
[8 /* DnsRecordType.MG */]: 'MG',
|
|
725
|
+
[9 /* DnsRecordType.MR */]: 'MR',
|
|
726
|
+
[10 /* DnsRecordType.NULL */]: 'NULL',
|
|
727
|
+
[11 /* DnsRecordType.WKS */]: 'WKS',
|
|
728
|
+
[12 /* DnsRecordType.PTR */]: 'PTR',
|
|
729
|
+
[13 /* DnsRecordType.HINFO */]: 'HINFO',
|
|
730
|
+
[14 /* DnsRecordType.MINFO */]: 'MINFO',
|
|
731
|
+
[15 /* DnsRecordType.MX */]: 'MX',
|
|
732
|
+
[16 /* DnsRecordType.TXT */]: 'TXT',
|
|
733
|
+
[17 /* DnsRecordType.RP */]: 'RP',
|
|
734
|
+
[18 /* DnsRecordType.AFSDB */]: 'AFSDB',
|
|
735
|
+
[19 /* DnsRecordType.X25 */]: 'X25',
|
|
736
|
+
[20 /* DnsRecordType.ISDN */]: 'ISDN',
|
|
737
|
+
[21 /* DnsRecordType.RT */]: 'RT',
|
|
738
|
+
[22 /* DnsRecordType.NSAP */]: 'NSAP',
|
|
739
|
+
[23 /* DnsRecordType.NSAP_PTR */]: 'NSAP_PTR',
|
|
740
|
+
[24 /* DnsRecordType.SIG */]: 'SIG',
|
|
741
|
+
[25 /* DnsRecordType.KEY */]: 'KEY',
|
|
742
|
+
[26 /* DnsRecordType.PX */]: 'PX',
|
|
743
|
+
[27 /* DnsRecordType.GPOS */]: 'GPOS',
|
|
744
|
+
[28 /* DnsRecordType.AAAA */]: 'AAAA',
|
|
745
|
+
[29 /* DnsRecordType.LOC */]: 'LOC',
|
|
746
|
+
[30 /* DnsRecordType.NXT */]: 'NXT',
|
|
747
|
+
[31 /* DnsRecordType.EID */]: 'EID',
|
|
748
|
+
[32 /* DnsRecordType.NIMLOC */]: 'NIMLOC',
|
|
749
|
+
[33 /* DnsRecordType.SRV */]: 'SRV',
|
|
750
|
+
[34 /* DnsRecordType.ATMA */]: 'ATMA',
|
|
751
|
+
[35 /* DnsRecordType.NAPTR */]: 'NAPTR',
|
|
752
|
+
[36 /* DnsRecordType.KX */]: 'KX',
|
|
753
|
+
[37 /* DnsRecordType.CERT */]: 'CERT',
|
|
754
|
+
[38 /* DnsRecordType.A6 */]: 'A6',
|
|
755
|
+
[39 /* DnsRecordType.DNAME */]: 'DNAME',
|
|
756
|
+
[40 /* DnsRecordType.SINK */]: 'SINK',
|
|
757
|
+
[41 /* DnsRecordType.OPT */]: 'OPT',
|
|
758
|
+
[42 /* DnsRecordType.APL */]: 'APL',
|
|
759
|
+
[43 /* DnsRecordType.DS */]: 'DS',
|
|
760
|
+
[44 /* DnsRecordType.SSHFP */]: 'SSHFP',
|
|
761
|
+
[45 /* DnsRecordType.IPSECKEY */]: 'IPSECKEY',
|
|
762
|
+
[46 /* DnsRecordType.RRSIG */]: 'RRSIG',
|
|
763
|
+
[47 /* DnsRecordType.NSEC */]: 'NSEC',
|
|
764
|
+
[48 /* DnsRecordType.DNSKEY */]: 'DNSKEY',
|
|
765
|
+
[49 /* DnsRecordType.DHCID */]: 'DHCID',
|
|
766
|
+
[50 /* DnsRecordType.NSEC3 */]: 'NSEC3',
|
|
767
|
+
[51 /* DnsRecordType.NSEC3PARAM */]: 'NSEC3PARAM',
|
|
768
|
+
[52 /* DnsRecordType.TLSA */]: 'TLSA',
|
|
769
|
+
[53 /* DnsRecordType.SMIMEA */]: 'SMIMEA',
|
|
770
|
+
[55 /* DnsRecordType.HIP */]: 'HIP',
|
|
771
|
+
[56 /* DnsRecordType.NINFO */]: 'NINFO',
|
|
772
|
+
[57 /* DnsRecordType.RKEY */]: 'RKEY',
|
|
773
|
+
[58 /* DnsRecordType.TALINK */]: 'TALINK',
|
|
774
|
+
[59 /* DnsRecordType.CDS */]: 'CDS',
|
|
775
|
+
[60 /* DnsRecordType.CDNSKEY */]: 'CDNSKEY',
|
|
776
|
+
[61 /* DnsRecordType.OPENPGPKEY */]: 'OPENPGPKEY',
|
|
777
|
+
[62 /* DnsRecordType.CSYNC */]: 'CSYNC',
|
|
778
|
+
[63 /* DnsRecordType.ZONEMD */]: 'ZONEMD',
|
|
779
|
+
[64 /* DnsRecordType.SVCB */]: 'SVCB',
|
|
780
|
+
[65 /* DnsRecordType.HTTPS */]: 'HTTPS',
|
|
781
|
+
[99 /* DnsRecordType.SPF */]: 'SPF',
|
|
782
|
+
[100 /* DnsRecordType.UINFO */]: 'UINFO',
|
|
783
|
+
[101 /* DnsRecordType.UID */]: 'UID',
|
|
784
|
+
[102 /* DnsRecordType.GID */]: 'GID',
|
|
785
|
+
[103 /* DnsRecordType.UNSPEC */]: 'UNSPEC',
|
|
786
|
+
[104 /* DnsRecordType.NID */]: 'NID',
|
|
787
|
+
[105 /* DnsRecordType.L32 */]: 'L32',
|
|
788
|
+
[106 /* DnsRecordType.L64 */]: 'L64',
|
|
789
|
+
[107 /* DnsRecordType.LP */]: 'LP',
|
|
790
|
+
[108 /* DnsRecordType.EUI48 */]: 'EUI48',
|
|
791
|
+
[109 /* DnsRecordType.EUI64 */]: 'EUI64',
|
|
792
|
+
[249 /* DnsRecordType.TKEY */]: 'TKEY',
|
|
793
|
+
[250 /* DnsRecordType.TSIG */]: 'TSIG',
|
|
794
|
+
[251 /* DnsRecordType.IXFR */]: 'IXFR',
|
|
795
|
+
[252 /* DnsRecordType.AXFR */]: 'AXFR',
|
|
796
|
+
[253 /* DnsRecordType.MAILB */]: 'MAILB',
|
|
797
|
+
[254 /* DnsRecordType.MAILA */]: 'MAILA',
|
|
798
|
+
[255 /* DnsRecordType.ANY */]: 'ANY',
|
|
799
|
+
[256 /* DnsRecordType.URI */]: 'URI',
|
|
800
|
+
[257 /* DnsRecordType.CAA */]: 'CAA',
|
|
801
|
+
[258 /* DnsRecordType.AVC */]: 'AVC',
|
|
802
|
+
[259 /* DnsRecordType.DOA */]: 'DOA',
|
|
803
|
+
[260 /* DnsRecordType.AMTRELAY */]: 'AMTRELAY',
|
|
804
|
+
[261 /* DnsRecordType.ZONEVERSION */]: 'ZONEVERSION',
|
|
805
|
+
[32768 /* DnsRecordType.TA */]: 'TA',
|
|
806
|
+
[32769 /* DnsRecordType.DLV */]: 'DLV',
|
|
607
807
|
};
|
|
608
808
|
return typeMap[type] ?? `TYPE${type}`;
|
|
609
809
|
}
|
|
810
|
+
/**
|
|
811
|
+
* Converts a DNS response class numeric value to its string representation.
|
|
812
|
+
*
|
|
813
|
+
* @param {number} cls - The numeric DNS class.
|
|
814
|
+
* @returns {string} The string representation of the DNS class.
|
|
815
|
+
*/
|
|
610
816
|
dnsResponseClassToString(cls) {
|
|
611
|
-
const isFlush = !!(cls & 32768);
|
|
817
|
+
const isFlush = !!(cls & 32768 /* DnsClassFlag.FLUSH */);
|
|
612
818
|
const baseClass = cls & 0x7fff;
|
|
613
819
|
let classStr;
|
|
614
820
|
switch (baseClass) {
|
|
615
|
-
case 1
|
|
821
|
+
case 1 /* DnsClass.IN */:
|
|
616
822
|
classStr = 'IN';
|
|
617
823
|
break;
|
|
618
|
-
case 3
|
|
824
|
+
case 3 /* DnsClass.CH */:
|
|
619
825
|
classStr = 'CH';
|
|
620
826
|
break;
|
|
621
|
-
case 4
|
|
827
|
+
case 4 /* DnsClass.HS */:
|
|
622
828
|
classStr = 'HS';
|
|
623
829
|
break;
|
|
624
|
-
case 255
|
|
830
|
+
case 255 /* DnsClass.ANY */:
|
|
625
831
|
classStr = 'ANY';
|
|
626
832
|
break;
|
|
627
833
|
default:
|
|
@@ -629,21 +835,28 @@ export class Mdns extends Multicast {
|
|
|
629
835
|
}
|
|
630
836
|
return isFlush ? `${classStr}|FLUSH` : classStr;
|
|
631
837
|
}
|
|
838
|
+
/**
|
|
839
|
+
* Converts a DNS question class to a human-readable string.
|
|
840
|
+
* Adds support for mDNS QU (unicast-response) bit.
|
|
841
|
+
*
|
|
842
|
+
* @param {number} cls - The numeric question class.
|
|
843
|
+
* @returns {string} The string representation, e.g. "IN|QU"
|
|
844
|
+
*/
|
|
632
845
|
dnsQuestionClassToString(cls) {
|
|
633
|
-
const isQU = !!(cls & 32768);
|
|
846
|
+
const isQU = !!(cls & 32768 /* DnsClassFlag.QU */);
|
|
634
847
|
const baseClass = cls & 0x7fff;
|
|
635
848
|
let classStr;
|
|
636
849
|
switch (baseClass) {
|
|
637
|
-
case 1
|
|
850
|
+
case 1 /* DnsClass.IN */:
|
|
638
851
|
classStr = 'IN';
|
|
639
852
|
break;
|
|
640
|
-
case 3
|
|
853
|
+
case 3 /* DnsClass.CH */:
|
|
641
854
|
classStr = 'CH';
|
|
642
855
|
break;
|
|
643
|
-
case 4
|
|
856
|
+
case 4 /* DnsClass.HS */:
|
|
644
857
|
classStr = 'HS';
|
|
645
858
|
break;
|
|
646
|
-
case 255
|
|
859
|
+
case 255 /* DnsClass.ANY */:
|
|
647
860
|
classStr = 'ANY';
|
|
648
861
|
break;
|
|
649
862
|
default:
|
|
@@ -651,6 +864,13 @@ export class Mdns extends Multicast {
|
|
|
651
864
|
}
|
|
652
865
|
return isQU ? `${classStr}|QU` : classStr;
|
|
653
866
|
}
|
|
867
|
+
/**
|
|
868
|
+
* Logs the decoded mDNS message header.
|
|
869
|
+
*
|
|
870
|
+
* @param {MdnsMessage} msg - The mDNS message header object.
|
|
871
|
+
* @param {AnsiLogger} [log] - The logger to use (defaults to this.log).
|
|
872
|
+
* @param {string} [text] - Optional additional text to include in the log.
|
|
873
|
+
*/
|
|
654
874
|
logMdnsMessage(msg, log = this.log, text = 'Decoded mDNS message') {
|
|
655
875
|
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
876
|
msg.questions?.forEach((question) => {
|
|
@@ -667,9 +887,14 @@ export class Mdns extends Multicast {
|
|
|
667
887
|
});
|
|
668
888
|
log.info(`---\n`);
|
|
669
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* Logs the discovered devices from the mDNS queries and responses.
|
|
892
|
+
*/
|
|
670
893
|
logDevices() {
|
|
671
894
|
this.log.info(`Discovered query devices: ${MAGENTA}${this.deviceQueries.size}${nf}`);
|
|
895
|
+
// Collect devices into an array
|
|
672
896
|
const deviceQueryArray = Array.from(this.deviceQueries.entries());
|
|
897
|
+
// Sort the array by numeric value of the IP address
|
|
673
898
|
deviceQueryArray.sort(([addressA], [addressB]) => {
|
|
674
899
|
const partsA = addressA.split('.').map(Number);
|
|
675
900
|
const partsB = addressB.split('.').map(Number);
|
|
@@ -678,13 +903,17 @@ export class Mdns extends Multicast {
|
|
|
678
903
|
if (diff !== 0)
|
|
679
904
|
return diff;
|
|
680
905
|
}
|
|
906
|
+
// istanbul ignore next
|
|
681
907
|
return 0;
|
|
682
908
|
});
|
|
909
|
+
// Log the sorted devices
|
|
683
910
|
deviceQueryArray.forEach(([rinfo, response]) => {
|
|
684
911
|
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
912
|
});
|
|
686
913
|
this.log.info(`Discovered response devices: ${MAGENTA}${this.deviceResponses.size}${nf}`);
|
|
914
|
+
// Collect devices into an array
|
|
687
915
|
const deviceResponseArray = Array.from(this.deviceResponses.entries());
|
|
916
|
+
// Sort the array by numeric value of the IP address
|
|
688
917
|
deviceResponseArray.sort(([addressA], [addressB]) => {
|
|
689
918
|
const partsA = addressA.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
690
919
|
const partsB = addressB.split(/[:.]/).map((part) => parseInt(part, 16));
|
|
@@ -693,10 +922,13 @@ export class Mdns extends Multicast {
|
|
|
693
922
|
if (diff !== 0)
|
|
694
923
|
return diff;
|
|
695
924
|
}
|
|
925
|
+
// istanbul ignore next
|
|
696
926
|
return 0;
|
|
697
927
|
});
|
|
928
|
+
// Log the sorted devices
|
|
698
929
|
deviceResponseArray.forEach(([rinfo, response]) => {
|
|
699
930
|
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
931
|
});
|
|
701
932
|
}
|
|
702
933
|
}
|
|
934
|
+
//# sourceMappingURL=mdns.js.map
|