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