matterbridge 3.4.6-dev-20260102-b04c53d → 3.4.6

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