matterbridge 3.2.4-dev-20250830-5c48452 → 3.2.4

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