matterbridge 3.1.7-dev-20250723-8e073ce → 3.1.7

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