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