@matter/protocol 0.16.0-alpha.0-20250916-d577beb1d → 0.16.0-alpha.0-20250921-b7a3dda23

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 (254) hide show
  1. package/dist/cjs/bdx/BdxClient.d.ts +31 -0
  2. package/dist/cjs/bdx/BdxClient.d.ts.map +1 -0
  3. package/dist/cjs/bdx/BdxClient.js +57 -0
  4. package/dist/cjs/bdx/BdxClient.js.map +6 -0
  5. package/dist/cjs/bdx/BdxError.d.ts +21 -0
  6. package/dist/cjs/bdx/BdxError.d.ts.map +1 -0
  7. package/dist/cjs/bdx/BdxError.js +54 -0
  8. package/dist/cjs/bdx/BdxError.js.map +6 -0
  9. package/dist/cjs/bdx/BdxMessenger.d.ts +77 -0
  10. package/dist/cjs/bdx/BdxMessenger.d.ts.map +1 -0
  11. package/dist/cjs/bdx/BdxMessenger.js +245 -0
  12. package/dist/cjs/bdx/BdxMessenger.js.map +6 -0
  13. package/dist/cjs/bdx/BdxProtocol.d.ts +25 -0
  14. package/dist/cjs/bdx/BdxProtocol.d.ts.map +1 -0
  15. package/dist/cjs/bdx/BdxProtocol.js +102 -0
  16. package/dist/cjs/bdx/BdxProtocol.js.map +6 -0
  17. package/dist/cjs/bdx/BdxSession.d.ts +36 -0
  18. package/dist/cjs/bdx/BdxSession.d.ts.map +1 -0
  19. package/dist/cjs/bdx/BdxSession.js +153 -0
  20. package/dist/cjs/bdx/BdxSession.js.map +6 -0
  21. package/dist/cjs/bdx/BdxSessionConfiguration.d.ts +61 -0
  22. package/dist/cjs/bdx/BdxSessionConfiguration.d.ts.map +1 -0
  23. package/dist/cjs/bdx/BdxSessionConfiguration.js +95 -0
  24. package/dist/cjs/bdx/BdxSessionConfiguration.js.map +6 -0
  25. package/dist/cjs/bdx/FileDesignator.d.ts +21 -0
  26. package/dist/cjs/bdx/FileDesignator.d.ts.map +1 -0
  27. package/dist/cjs/bdx/FileDesignator.js +62 -0
  28. package/dist/cjs/bdx/FileDesignator.js.map +6 -0
  29. package/dist/cjs/bdx/PersistedFileDesignator.d.ts +16 -0
  30. package/dist/cjs/bdx/PersistedFileDesignator.d.ts.map +1 -0
  31. package/dist/cjs/bdx/PersistedFileDesignator.js +57 -0
  32. package/dist/cjs/bdx/PersistedFileDesignator.js.map +6 -0
  33. package/dist/cjs/bdx/bdx-session-initiator.d.ts +14 -0
  34. package/dist/cjs/bdx/bdx-session-initiator.d.ts.map +1 -0
  35. package/dist/cjs/bdx/bdx-session-initiator.js +218 -0
  36. package/dist/cjs/bdx/bdx-session-initiator.js.map +6 -0
  37. package/dist/cjs/bdx/flow/DrivenSendingFlow.d.ts +15 -0
  38. package/dist/cjs/bdx/flow/DrivenSendingFlow.d.ts.map +1 -0
  39. package/dist/cjs/bdx/flow/DrivenSendingFlow.js +49 -0
  40. package/dist/cjs/bdx/flow/DrivenSendingFlow.js.map +6 -0
  41. package/dist/cjs/bdx/flow/DrivingReceivingFlow.d.ts +15 -0
  42. package/dist/cjs/bdx/flow/DrivingReceivingFlow.d.ts.map +1 -0
  43. package/dist/cjs/bdx/flow/DrivingReceivingFlow.js +47 -0
  44. package/dist/cjs/bdx/flow/DrivingReceivingFlow.js.map +6 -0
  45. package/dist/cjs/bdx/flow/Flow.d.ts +48 -0
  46. package/dist/cjs/bdx/flow/Flow.d.ts.map +1 -0
  47. package/dist/cjs/bdx/flow/Flow.js +112 -0
  48. package/dist/cjs/bdx/flow/Flow.js.map +6 -0
  49. package/dist/cjs/bdx/flow/FollowingReceivingFlow.d.ts +16 -0
  50. package/dist/cjs/bdx/flow/FollowingReceivingFlow.d.ts.map +1 -0
  51. package/dist/cjs/bdx/flow/FollowingReceivingFlow.js +60 -0
  52. package/dist/cjs/bdx/flow/FollowingReceivingFlow.js.map +6 -0
  53. package/dist/cjs/bdx/flow/FollowingSendingFlow.d.ts +15 -0
  54. package/dist/cjs/bdx/flow/FollowingSendingFlow.d.ts.map +1 -0
  55. package/dist/cjs/bdx/flow/FollowingSendingFlow.js +49 -0
  56. package/dist/cjs/bdx/flow/FollowingSendingFlow.js.map +6 -0
  57. package/dist/cjs/bdx/flow/InboundFlow.d.ts +26 -0
  58. package/dist/cjs/bdx/flow/InboundFlow.d.ts.map +1 -0
  59. package/dist/cjs/bdx/flow/InboundFlow.js +101 -0
  60. package/dist/cjs/bdx/flow/InboundFlow.js.map +6 -0
  61. package/dist/cjs/bdx/flow/OutboundFlow.d.ts +31 -0
  62. package/dist/cjs/bdx/flow/OutboundFlow.d.ts.map +1 -0
  63. package/dist/cjs/bdx/flow/OutboundFlow.js +124 -0
  64. package/dist/cjs/bdx/flow/OutboundFlow.js.map +6 -0
  65. package/dist/cjs/bdx/index.d.ts +16 -0
  66. package/dist/cjs/bdx/index.d.ts.map +1 -0
  67. package/dist/cjs/bdx/index.js +33 -0
  68. package/dist/cjs/bdx/index.js.map +6 -0
  69. package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.d.ts +50 -0
  70. package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.d.ts.map +1 -0
  71. package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.js +125 -0
  72. package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.js.map +6 -0
  73. package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.d.ts +53 -0
  74. package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.d.ts.map +1 -0
  75. package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.js +92 -0
  76. package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.js.map +6 -0
  77. package/dist/cjs/bdx/schema/BdxInitMessagesSchema.d.ts +117 -0
  78. package/dist/cjs/bdx/schema/BdxInitMessagesSchema.d.ts.map +1 -0
  79. package/dist/cjs/bdx/schema/BdxInitMessagesSchema.js +153 -0
  80. package/dist/cjs/bdx/schema/BdxInitMessagesSchema.js.map +6 -0
  81. package/dist/cjs/bdx/schema/BdxMessage.d.ts +23 -0
  82. package/dist/cjs/bdx/schema/BdxMessage.d.ts.map +1 -0
  83. package/dist/cjs/bdx/schema/BdxMessage.js +75 -0
  84. package/dist/cjs/bdx/schema/BdxMessage.js.map +6 -0
  85. package/dist/cjs/bdx/schema/BdxStatusMessageSchema.d.ts +12 -0
  86. package/dist/cjs/bdx/schema/BdxStatusMessageSchema.d.ts.map +1 -0
  87. package/dist/cjs/bdx/schema/BdxStatusMessageSchema.js +35 -0
  88. package/dist/cjs/bdx/schema/BdxStatusMessageSchema.js.map +6 -0
  89. package/dist/cjs/bdx/schema/index.d.ts +11 -0
  90. package/dist/cjs/bdx/schema/index.d.ts.map +1 -0
  91. package/dist/cjs/bdx/schema/index.js +28 -0
  92. package/dist/cjs/bdx/schema/index.js.map +6 -0
  93. package/dist/cjs/index.d.ts +1 -0
  94. package/dist/cjs/index.d.ts.map +1 -1
  95. package/dist/cjs/index.js +1 -0
  96. package/dist/cjs/index.js.map +1 -1
  97. package/dist/cjs/interaction/InteractionClient.d.ts +4 -4
  98. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  99. package/dist/cjs/interaction/InteractionClient.js +27 -39
  100. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  101. package/dist/cjs/mdns/MdnsClient.js +2 -2
  102. package/dist/cjs/mdns/MdnsClient.js.map +1 -1
  103. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  104. package/dist/cjs/protocol/ExchangeManager.js +4 -2
  105. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  106. package/dist/cjs/protocol/MessageExchange.d.ts +2 -0
  107. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  108. package/dist/cjs/protocol/MessageExchange.js +14 -8
  109. package/dist/cjs/protocol/MessageExchange.js.map +2 -2
  110. package/dist/cjs/protocol/ProtocolStatusMessage.d.ts +1 -1
  111. package/dist/cjs/protocol/ProtocolStatusMessage.d.ts.map +1 -1
  112. package/dist/cjs/protocol/ProtocolStatusMessage.js.map +1 -1
  113. package/dist/esm/bdx/BdxClient.d.ts +31 -0
  114. package/dist/esm/bdx/BdxClient.d.ts.map +1 -0
  115. package/dist/esm/bdx/BdxClient.js +37 -0
  116. package/dist/esm/bdx/BdxClient.js.map +6 -0
  117. package/dist/esm/bdx/BdxError.d.ts +21 -0
  118. package/dist/esm/bdx/BdxError.d.ts.map +1 -0
  119. package/dist/esm/bdx/BdxError.js +34 -0
  120. package/dist/esm/bdx/BdxError.js.map +6 -0
  121. package/dist/esm/bdx/BdxMessenger.d.ts +77 -0
  122. package/dist/esm/bdx/BdxMessenger.d.ts.map +1 -0
  123. package/dist/esm/bdx/BdxMessenger.js +233 -0
  124. package/dist/esm/bdx/BdxMessenger.js.map +6 -0
  125. package/dist/esm/bdx/BdxProtocol.d.ts +25 -0
  126. package/dist/esm/bdx/BdxProtocol.d.ts.map +1 -0
  127. package/dist/esm/bdx/BdxProtocol.js +82 -0
  128. package/dist/esm/bdx/BdxProtocol.js.map +6 -0
  129. package/dist/esm/bdx/BdxSession.d.ts +36 -0
  130. package/dist/esm/bdx/BdxSession.d.ts.map +1 -0
  131. package/dist/esm/bdx/BdxSession.js +133 -0
  132. package/dist/esm/bdx/BdxSession.js.map +6 -0
  133. package/dist/esm/bdx/BdxSessionConfiguration.d.ts +61 -0
  134. package/dist/esm/bdx/BdxSessionConfiguration.d.ts.map +1 -0
  135. package/dist/esm/bdx/BdxSessionConfiguration.js +75 -0
  136. package/dist/esm/bdx/BdxSessionConfiguration.js.map +6 -0
  137. package/dist/esm/bdx/FileDesignator.d.ts +21 -0
  138. package/dist/esm/bdx/FileDesignator.d.ts.map +1 -0
  139. package/dist/esm/bdx/FileDesignator.js +42 -0
  140. package/dist/esm/bdx/FileDesignator.js.map +6 -0
  141. package/dist/esm/bdx/PersistedFileDesignator.d.ts +16 -0
  142. package/dist/esm/bdx/PersistedFileDesignator.d.ts.map +1 -0
  143. package/dist/esm/bdx/PersistedFileDesignator.js +37 -0
  144. package/dist/esm/bdx/PersistedFileDesignator.js.map +6 -0
  145. package/dist/esm/bdx/bdx-session-initiator.d.ts +14 -0
  146. package/dist/esm/bdx/bdx-session-initiator.d.ts.map +1 -0
  147. package/dist/esm/bdx/bdx-session-initiator.js +198 -0
  148. package/dist/esm/bdx/bdx-session-initiator.js.map +6 -0
  149. package/dist/esm/bdx/flow/DrivenSendingFlow.d.ts +15 -0
  150. package/dist/esm/bdx/flow/DrivenSendingFlow.d.ts.map +1 -0
  151. package/dist/esm/bdx/flow/DrivenSendingFlow.js +29 -0
  152. package/dist/esm/bdx/flow/DrivenSendingFlow.js.map +6 -0
  153. package/dist/esm/bdx/flow/DrivingReceivingFlow.d.ts +15 -0
  154. package/dist/esm/bdx/flow/DrivingReceivingFlow.d.ts.map +1 -0
  155. package/dist/esm/bdx/flow/DrivingReceivingFlow.js +27 -0
  156. package/dist/esm/bdx/flow/DrivingReceivingFlow.js.map +6 -0
  157. package/dist/esm/bdx/flow/Flow.d.ts +48 -0
  158. package/dist/esm/bdx/flow/Flow.d.ts.map +1 -0
  159. package/dist/esm/bdx/flow/Flow.js +92 -0
  160. package/dist/esm/bdx/flow/Flow.js.map +6 -0
  161. package/dist/esm/bdx/flow/FollowingReceivingFlow.d.ts +16 -0
  162. package/dist/esm/bdx/flow/FollowingReceivingFlow.d.ts.map +1 -0
  163. package/dist/esm/bdx/flow/FollowingReceivingFlow.js +40 -0
  164. package/dist/esm/bdx/flow/FollowingReceivingFlow.js.map +6 -0
  165. package/dist/esm/bdx/flow/FollowingSendingFlow.d.ts +15 -0
  166. package/dist/esm/bdx/flow/FollowingSendingFlow.d.ts.map +1 -0
  167. package/dist/esm/bdx/flow/FollowingSendingFlow.js +29 -0
  168. package/dist/esm/bdx/flow/FollowingSendingFlow.js.map +6 -0
  169. package/dist/esm/bdx/flow/InboundFlow.d.ts +26 -0
  170. package/dist/esm/bdx/flow/InboundFlow.d.ts.map +1 -0
  171. package/dist/esm/bdx/flow/InboundFlow.js +81 -0
  172. package/dist/esm/bdx/flow/InboundFlow.js.map +6 -0
  173. package/dist/esm/bdx/flow/OutboundFlow.d.ts +31 -0
  174. package/dist/esm/bdx/flow/OutboundFlow.d.ts.map +1 -0
  175. package/dist/esm/bdx/flow/OutboundFlow.js +104 -0
  176. package/dist/esm/bdx/flow/OutboundFlow.js.map +6 -0
  177. package/dist/esm/bdx/index.d.ts +16 -0
  178. package/dist/esm/bdx/index.d.ts.map +1 -0
  179. package/dist/esm/bdx/index.js +16 -0
  180. package/dist/esm/bdx/index.js.map +6 -0
  181. package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.d.ts +50 -0
  182. package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.d.ts.map +1 -0
  183. package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.js +109 -0
  184. package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.js.map +6 -0
  185. package/dist/esm/bdx/schema/BdxBlockMessagesSchema.d.ts +53 -0
  186. package/dist/esm/bdx/schema/BdxBlockMessagesSchema.d.ts.map +1 -0
  187. package/dist/esm/bdx/schema/BdxBlockMessagesSchema.js +72 -0
  188. package/dist/esm/bdx/schema/BdxBlockMessagesSchema.js.map +6 -0
  189. package/dist/esm/bdx/schema/BdxInitMessagesSchema.d.ts +117 -0
  190. package/dist/esm/bdx/schema/BdxInitMessagesSchema.d.ts.map +1 -0
  191. package/dist/esm/bdx/schema/BdxInitMessagesSchema.js +133 -0
  192. package/dist/esm/bdx/schema/BdxInitMessagesSchema.js.map +6 -0
  193. package/dist/esm/bdx/schema/BdxMessage.d.ts +23 -0
  194. package/dist/esm/bdx/schema/BdxMessage.d.ts.map +1 -0
  195. package/dist/esm/bdx/schema/BdxMessage.js +62 -0
  196. package/dist/esm/bdx/schema/BdxMessage.js.map +6 -0
  197. package/dist/esm/bdx/schema/BdxStatusMessageSchema.d.ts +12 -0
  198. package/dist/esm/bdx/schema/BdxStatusMessageSchema.d.ts.map +1 -0
  199. package/dist/esm/bdx/schema/BdxStatusMessageSchema.js +15 -0
  200. package/dist/esm/bdx/schema/BdxStatusMessageSchema.js.map +6 -0
  201. package/dist/esm/bdx/schema/index.d.ts +11 -0
  202. package/dist/esm/bdx/schema/index.d.ts.map +1 -0
  203. package/dist/esm/bdx/schema/index.js +11 -0
  204. package/dist/esm/bdx/schema/index.js.map +6 -0
  205. package/dist/esm/index.d.ts +1 -0
  206. package/dist/esm/index.d.ts.map +1 -1
  207. package/dist/esm/index.js +1 -0
  208. package/dist/esm/index.js.map +1 -1
  209. package/dist/esm/interaction/InteractionClient.d.ts +4 -4
  210. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  211. package/dist/esm/interaction/InteractionClient.js +27 -39
  212. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  213. package/dist/esm/mdns/MdnsClient.js +2 -2
  214. package/dist/esm/mdns/MdnsClient.js.map +1 -1
  215. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  216. package/dist/esm/protocol/ExchangeManager.js +4 -2
  217. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  218. package/dist/esm/protocol/MessageExchange.d.ts +2 -0
  219. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  220. package/dist/esm/protocol/MessageExchange.js +14 -8
  221. package/dist/esm/protocol/MessageExchange.js.map +2 -2
  222. package/dist/esm/protocol/ProtocolStatusMessage.d.ts +1 -1
  223. package/dist/esm/protocol/ProtocolStatusMessage.d.ts.map +1 -1
  224. package/dist/esm/protocol/ProtocolStatusMessage.js.map +1 -1
  225. package/package.json +6 -6
  226. package/src/bdx/BdxClient.ts +47 -0
  227. package/src/bdx/BdxError.ts +39 -0
  228. package/src/bdx/BdxMessenger.ts +291 -0
  229. package/src/bdx/BdxProtocol.ts +93 -0
  230. package/src/bdx/BdxSession.ts +174 -0
  231. package/src/bdx/BdxSessionConfiguration.ts +134 -0
  232. package/src/bdx/FileDesignator.ts +49 -0
  233. package/src/bdx/PersistedFileDesignator.ts +40 -0
  234. package/src/bdx/bdx-session-initiator.ts +246 -0
  235. package/src/bdx/flow/DrivenSendingFlow.ts +40 -0
  236. package/src/bdx/flow/DrivingReceivingFlow.ts +39 -0
  237. package/src/bdx/flow/Flow.ts +124 -0
  238. package/src/bdx/flow/FollowingReceivingFlow.ts +53 -0
  239. package/src/bdx/flow/FollowingSendingFlow.ts +38 -0
  240. package/src/bdx/flow/InboundFlow.ts +104 -0
  241. package/src/bdx/flow/OutboundFlow.ts +124 -0
  242. package/src/bdx/index.ts +16 -0
  243. package/src/bdx/schema/BdxAcceptMessagesSchema.ts +159 -0
  244. package/src/bdx/schema/BdxBlockMessagesSchema.ts +99 -0
  245. package/src/bdx/schema/BdxInitMessagesSchema.ts +213 -0
  246. package/src/bdx/schema/BdxMessage.ts +70 -0
  247. package/src/bdx/schema/BdxStatusMessageSchema.ts +14 -0
  248. package/src/bdx/schema/index.ts +11 -0
  249. package/src/index.ts +1 -0
  250. package/src/interaction/InteractionClient.ts +34 -48
  251. package/src/mdns/MdnsClient.ts +2 -2
  252. package/src/protocol/ExchangeManager.ts +2 -0
  253. package/src/protocol/MessageExchange.ts +17 -6
  254. package/src/protocol/ProtocolStatusMessage.ts +1 -1
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { InboundFlow } from "./InboundFlow.js";
8
+
9
+ /**
10
+ * BDX Transport flow logic for a "BDX Driving Receiver":
11
+ * - Requests the next Blow using BlockQuery and then reads the Block
12
+ * - Last message is confirmed with an AckEof
13
+ */
14
+ export class DrivingReceivingFlow extends InboundFlow {
15
+ async transferNextChunk() {
16
+ const { writeController } = this.stream;
17
+
18
+ const blockCounter = this.nextMessageCounter;
19
+
20
+ // Query next block (We never Ack block from before because we are usually never sleepy)
21
+ // Think about cases to use BlockQueryWithSkip
22
+ await this.messenger.sendBlockQuery({ blockCounter });
23
+
24
+ // Read returned Block
25
+ const {
26
+ kind: messageType,
27
+ message: { blockCounter: dataBlockCounter, data },
28
+ } = await this.messenger.readBlock();
29
+ this.validateCounter(dataBlockCounter, blockCounter);
30
+
31
+ // Write the received data chunk into the writing stream
32
+ if (this.writeDataChunk(writeController, data, messageType)) {
33
+ this.finalBlockCounter = dataBlockCounter;
34
+ return true;
35
+ }
36
+
37
+ return false;
38
+ }
39
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { InternalError } from "#general";
8
+ import { BdxStatusCode } from "#types";
9
+ import { BdxError } from "../BdxError.js";
10
+ import { BdxMessenger } from "../BdxMessenger.js";
11
+ import { PersistedFileDesignator } from "../PersistedFileDesignator.js";
12
+
13
+ /** Base class for BDX transfer flows. */
14
+ export abstract class Flow {
15
+ readonly #transferParameters: Flow.TransferOptions;
16
+ readonly #messenger: BdxMessenger;
17
+ #isClosed = false;
18
+ #blockCounter = 0;
19
+ #bytesLeft?: number;
20
+ #finalBlockCounter?: number;
21
+
22
+ constructor(messenger: BdxMessenger, transferParameters: Flow.TransferOptions) {
23
+ this.#messenger = messenger;
24
+ this.#transferParameters = transferParameters;
25
+ this.#bytesLeft = transferParameters.dataLength;
26
+ }
27
+
28
+ protected get transferParameters(): Flow.TransferOptions {
29
+ return this.#transferParameters;
30
+ }
31
+
32
+ protected get isClosed() {
33
+ return this.#isClosed;
34
+ }
35
+
36
+ protected get messenger() {
37
+ return this.#messenger;
38
+ }
39
+
40
+ protected get bytesLeft(): number | undefined {
41
+ return this.#bytesLeft;
42
+ }
43
+
44
+ protected set bytesLeft(value: number) {
45
+ this.#bytesLeft = value;
46
+ }
47
+
48
+ protected set finalBlockCounter(blockCounter: number) {
49
+ if (this.#finalBlockCounter !== undefined) {
50
+ throw new InternalError("Transfer already finalized. finalizeTransfer() should only be called once.");
51
+ }
52
+ this.#finalBlockCounter = blockCounter;
53
+ }
54
+
55
+ protected get finalBlockCounter() {
56
+ if (this.#finalBlockCounter === undefined) {
57
+ throw new InternalError("Transfer not finalized. Call finalizeTransfer() after completing the transfer.");
58
+ }
59
+ return this.#finalBlockCounter;
60
+ }
61
+
62
+ /** Determines the next message counter to use for the next message, also handles wrapping around at 2^32. */
63
+ protected get nextMessageCounter() {
64
+ this.#blockCounter = (this.#blockCounter + 1) % 0x100000000; // wrap around at 2^32
65
+ return this.#blockCounter;
66
+ }
67
+
68
+ /** Utility function to check if a block counter is valid */
69
+ protected validateCounter(messageBlockCounter: number, expectedCounter = this.nextMessageCounter) {
70
+ if (messageBlockCounter !== expectedCounter) {
71
+ throw new BdxError(
72
+ `Received Block with unexpected block counter: ${messageBlockCounter}, expected: ${expectedCounter}`,
73
+ BdxStatusCode.BadBlockCounter,
74
+ );
75
+ }
76
+ return messageBlockCounter;
77
+ }
78
+
79
+ async close(_error?: unknown) {
80
+ this.#isClosed = true;
81
+ }
82
+
83
+ /**
84
+ * Main logic method to execute the flow.
85
+ * The promise resolves when the flow is complete, or rejects on any error or unexpected conditions.
86
+ */
87
+ async processTransfer() {
88
+ await this.initTransfer();
89
+
90
+ // Continue to transfer chunks until done or closed
91
+ while (!this.isClosed) {
92
+ if (await this.transferNextChunk()) {
93
+ break;
94
+ }
95
+ }
96
+
97
+ if (!this.isClosed) {
98
+ await this.finalizeTransfer();
99
+ }
100
+ }
101
+
102
+ protected abstract initTransfer(): Promise<void>;
103
+
104
+ protected abstract transferNextChunk(): Promise<boolean>;
105
+
106
+ protected abstract finalizeTransfer(): Promise<void>;
107
+ }
108
+
109
+ export namespace Flow {
110
+ export interface TransferOptions {
111
+ transferMode: DriverMode;
112
+ asynchronousTransfer: false; // Not supported currently, so always false
113
+ dataLength?: number;
114
+ startOffset: number;
115
+ blockSize: number;
116
+ isDriver: boolean;
117
+ fileDesignator: PersistedFileDesignator;
118
+ }
119
+
120
+ export enum DriverMode {
121
+ SenderDrive = "senderDrive",
122
+ ReceiverDrive = "receiverDrive",
123
+ }
124
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Logger } from "#general";
8
+ import { BdxMessageType, BdxStatusCode } from "#types";
9
+ import { BdxMessenger } from "../BdxMessenger.js";
10
+ import { BdxMessage } from "../schema/BdxMessage.js";
11
+ import { OutboundFlow } from "./OutboundFlow.js";
12
+
13
+ const logger = Logger.get("BdxFollowingReceivingFlow");
14
+ /**
15
+ * BDX Transport flow logic for a "BDX Following Receiver":
16
+ * - Reads BlockQuery(WithSkip) messages and responds with Block or (for last block) BlockEof.
17
+ * Data are skipped over when requested by the peer.
18
+ * - After the last block is send it expects an AckEof
19
+ */
20
+ export class FollowingReceivingFlow extends OutboundFlow {
21
+ protected async transferNextChunk() {
22
+ const { iterator, streamReader } = this.stream;
23
+
24
+ // Read the data query from the peer
25
+ const blockQuery = await this.messenger.readBlockQuery();
26
+ const bytesToSkip = BdxMessage.is(blockQuery, BdxMessageType.BlockQueryWithSkip)
27
+ ? BdxMessenger.asSafeNumber(
28
+ blockQuery.message.bytesToSkip,
29
+ "BytesToSkip",
30
+ BdxStatusCode.TransferFailedUnknownError,
31
+ )
32
+ : 0;
33
+
34
+ const { blockCounter } = blockQuery.message;
35
+ this.validateCounter(blockCounter);
36
+
37
+ if (bytesToSkip > 0) {
38
+ const skipped = await streamReader.skip(bytesToSkip);
39
+ logger.debug(`Skipped ${skipped}bytes of data (requested ${bytesToSkip}bytes)`);
40
+ }
41
+ const { data, done } = await this.readDataChunk(iterator);
42
+
43
+ if (done) {
44
+ await this.messenger.sendBlockEof({ data, blockCounter });
45
+ this.finalBlockCounter = blockCounter;
46
+ return true;
47
+ }
48
+
49
+ await this.messenger.sendBlock({ data, blockCounter });
50
+ // Ack or next BlockQuery is read on the next iteration
51
+ return false;
52
+ }
53
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { InboundFlow } from "./InboundFlow.js";
8
+
9
+ /**
10
+ * BDX Transport flow logic for a "BDX Following Sender":
11
+ * - Reads the Block and sends an Ack (if synchronous transfer is used)
12
+ * - Last message is confirmed with an AckEof
13
+ */
14
+ export class FollowingSendingFlow extends InboundFlow {
15
+ protected async transferNextChunk() {
16
+ const { asynchronousTransfer } = this.transferParameters;
17
+ const { writeController } = this.stream;
18
+
19
+ const {
20
+ kind: messageType,
21
+ message: { data, blockCounter },
22
+ } = await this.messenger.readBlock();
23
+ this.validateCounter(blockCounter);
24
+
25
+ // Write the received data chunk into the writing stream
26
+ if (this.writeDataChunk(writeController, data, messageType)) {
27
+ this.finalBlockCounter = blockCounter;
28
+ return true;
29
+ }
30
+
31
+ if (!asynchronousTransfer) {
32
+ // Sync transfer just requires Ack to be sent back
33
+ await this.messenger.sendBlockAck({ blockCounter });
34
+ }
35
+
36
+ return false;
37
+ }
38
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Bytes, InternalError, MaybePromise } from "#general";
8
+ import { BdxMessageType, BdxStatusCode } from "#types";
9
+ import { BdxError } from "../BdxError.js";
10
+ import { Flow } from "./Flow.js";
11
+
12
+ /**
13
+ * Base class for inbound BDX transfer flows where data is received from the peer and written to our node.
14
+ */
15
+ export abstract class InboundFlow extends Flow {
16
+ #closeStreams?: (error?: unknown) => Promise<void>;
17
+ #writeController?: ReadableStreamDefaultController<Bytes>;
18
+ #writePromise?: MaybePromise<void>;
19
+
20
+ /**
21
+ * Returns initialized streams for the transfer and initializes the #closeStream class function
22
+ */
23
+ protected async initTransfer() {
24
+ // Create a ReadableStream that we can write to and start to write the data into the blob
25
+ let writeController!: ReadableStreamDefaultController<Bytes>; // variable is set on creation of the ReadableStream
26
+ const stream = new ReadableStream<Bytes>({
27
+ start: controller => {
28
+ writeController = controller;
29
+ },
30
+ });
31
+ const { fileDesignator } = this.transferParameters;
32
+ const writePromise = fileDesignator.writeFromStream(stream);
33
+
34
+ // Method to be used by main close() method to make sure all streams are correctly closed or cancelled
35
+ this.#closeStreams = async (error?: unknown) => {
36
+ if (writeController !== undefined) {
37
+ if (error != undefined) {
38
+ // When this is called, we are either done successfully or failed, error the write controller in error case
39
+ writeController.error(error);
40
+ try {
41
+ await writePromise;
42
+ } catch {
43
+ // Ignore the error because we generated it
44
+ }
45
+ }
46
+ }
47
+ // When writing and errored the stream might stay locked, so we cannot cancel it without an exception
48
+ if (!stream.locked) {
49
+ await stream.cancel();
50
+ }
51
+ };
52
+
53
+ this.#writeController = writeController;
54
+ this.#writePromise = writePromise;
55
+ }
56
+
57
+ protected get stream() {
58
+ if (!this.#writeController || !this.#writePromise) {
59
+ throw new InternalError("Transfer not initialized. Call initTransfer() before starting the transfer.");
60
+ }
61
+ return { writeController: this.#writeController, writePromise: this.#writePromise };
62
+ }
63
+
64
+ protected async finalizeTransfer() {
65
+ const { writePromise } = this.stream;
66
+ const blockCounter = this.finalBlockCounter;
67
+ await writePromise;
68
+ await this.messenger.sendBlockAckEof({ blockCounter });
69
+ }
70
+
71
+ protected writeDataChunk(
72
+ writeController: ReadableStreamDefaultController<Bytes>,
73
+ data: Bytes,
74
+ messageType: BdxMessageType,
75
+ ) {
76
+ // Enqueue the received data chunk into the writing stream
77
+ writeController.enqueue(data);
78
+ if (this.bytesLeft !== undefined) {
79
+ this.bytesLeft -= data.byteLength;
80
+ }
81
+
82
+ let done = false;
83
+
84
+ // Last block received
85
+ if (messageType === BdxMessageType.BlockEof) {
86
+ if (this.bytesLeft !== undefined && this.bytesLeft !== 0) {
87
+ throw new BdxError(
88
+ `Received BlockEof with ${this.bytesLeft}bytes left, but no more data available`,
89
+ this.bytesLeft > 0 ? BdxStatusCode.LengthTooShort : BdxStatusCode.LengthTooLarge,
90
+ );
91
+ }
92
+
93
+ done = true;
94
+ writeController.close();
95
+ }
96
+
97
+ return done;
98
+ }
99
+
100
+ override async close(error?: unknown) {
101
+ await super.close(error);
102
+ await this.#closeStreams?.(error);
103
+ }
104
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { BytesStreamReader, InternalError } from "#general";
8
+ import { BdxStatusCode } from "#types";
9
+ import { BdxError } from "../BdxError.js";
10
+ import { Flow } from "./Flow.js";
11
+
12
+ /**
13
+ * Base class for outbound BDX transfer flows where data is read from our node and sent to the peer.
14
+ */
15
+ export abstract class OutboundFlow extends Flow {
16
+ #closeStreams?: (error?: unknown) => Promise<void>;
17
+ #iterator?: AsyncGenerator<Uint8Array<ArrayBufferLike>, void, unknown>;
18
+ #streamReader?: BytesStreamReader;
19
+
20
+ protected get stream() {
21
+ if (this.#iterator === undefined || this.#streamReader === undefined) {
22
+ throw new InternalError("Read stream not initialized");
23
+ }
24
+ return { iterator: this.#iterator, streamReader: this.#streamReader };
25
+ }
26
+
27
+ /**
28
+ * Returns initialized streams for the transfer and initializes the #closeStream class function
29
+ */
30
+ protected async initTransfer() {
31
+ const { blockSize } = this.transferParameters;
32
+
33
+ const blob = await this.transferParameters.fileDesignator.openBlob();
34
+ const blobSize = blob.size;
35
+
36
+ // Get the full or relevant part of the stream by startOffset and length
37
+ const { startOffset = 0, dataLength = blobSize } = this.transferParameters;
38
+
39
+ const dataBlob =
40
+ startOffset > 0 || dataLength !== blobSize ? blob.slice(startOffset, startOffset + dataLength) : blob;
41
+
42
+ const stream = dataBlob.stream();
43
+
44
+ const reader = stream.getReader();
45
+ // Method to be used by main close() method to make sure all streams are correctly closed or cancelled
46
+ this.#closeStreams = async (_error?: unknown) => {
47
+ if (stream.locked) {
48
+ reader?.releaseLock();
49
+ try {
50
+ await reader?.cancel();
51
+ } catch (error) {
52
+ // A TypeError is expected when the stream is already cancelled, so we ignore it
53
+ if (!(error instanceof TypeError)) {
54
+ throw error;
55
+ }
56
+ }
57
+ }
58
+ await stream.cancel();
59
+ };
60
+
61
+ const streamReader = new BytesStreamReader(reader);
62
+ this.#iterator = streamReader.read(blockSize);
63
+ this.#streamReader = streamReader;
64
+ }
65
+
66
+ /**
67
+ * Reads one data chunk from the reader and does some basic checks.
68
+ */
69
+ protected async readDataChunk(reader: AsyncGenerator<Uint8Array<ArrayBufferLike>, void, unknown>) {
70
+ const { blockSize, dataLength } = this.transferParameters;
71
+ let { value, done = false } = await reader.next();
72
+ if (value === undefined) {
73
+ // Done needs to be true when value is undefined or there is something broken
74
+ if (!done) {
75
+ throw new BdxError(
76
+ `Data length too short, expected ${blockSize}bytes, but got less`,
77
+ BdxStatusCode.LengthTooShort,
78
+ );
79
+ }
80
+ value = new Uint8Array(); // Simulate an empty value when we reached the end of the stream
81
+ } else if (value.byteLength < blockSize) {
82
+ // When we get less data than blocksize it is the last block, so validate that
83
+ ({ done = false } = await reader.next());
84
+ if (!done) {
85
+ throw new BdxError(
86
+ `Data length too short, expected ${blockSize}bytes, but got less`,
87
+ BdxStatusCode.LengthTooShort,
88
+ );
89
+ }
90
+ }
91
+
92
+ if (this.bytesLeft !== undefined && dataLength !== undefined) {
93
+ this.bytesLeft -= value.byteLength;
94
+ if (this.bytesLeft < 0) {
95
+ throw new BdxError(
96
+ `Data length exceeded, expected ${dataLength}bytes, but got ${-this.bytesLeft}bytes more`,
97
+ BdxStatusCode.LengthTooLarge,
98
+ );
99
+ }
100
+ if (done && this.bytesLeft > 0) {
101
+ throw new BdxError(
102
+ `Data length too short, expected ${dataLength}bytes, but got ${this.bytesLeft}bytes less`,
103
+ BdxStatusCode.LengthTooShort,
104
+ );
105
+ }
106
+ if (this.bytesLeft === 0) {
107
+ done = true;
108
+ }
109
+ }
110
+
111
+ return { data: value, done };
112
+ }
113
+
114
+ protected async finalizeTransfer() {
115
+ const blockCounter = this.finalBlockCounter;
116
+ const { blockCounter: ackedBlockCounter } = await this.messenger.readBlockAckEof();
117
+ this.validateCounter(ackedBlockCounter, blockCounter);
118
+ }
119
+
120
+ override async close(error?: unknown) {
121
+ await super.close(error);
122
+ await this.#closeStreams?.(error);
123
+ }
124
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ export * from "./BdxClient.js";
8
+ export * from "./BdxError.js";
9
+ export * from "./BdxMessenger.js";
10
+ export * from "./BdxProtocol.js";
11
+ export * from "./BdxSession.js";
12
+ export * from "./BdxSessionConfiguration.js";
13
+ export * from "./FileDesignator.js";
14
+ export * from "./flow/Flow.js";
15
+ export * from "./PersistedFileDesignator.js";
16
+ export * from "./schema/index.js";
@@ -0,0 +1,159 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Bytes, DataReader, DataWriter, Endian } from "#general";
8
+ import { BdxStatusCode, Schema, TypeFromPartialBitSchema } from "#types";
9
+ import { BdxError } from "../BdxError.js";
10
+ import {
11
+ BDX_VERSION,
12
+ BdxRangeControlSchema,
13
+ BdxTransferControlBitmap,
14
+ BdxTransferControlSchema,
15
+ } from "./BdxInitMessagesSchema.js";
16
+
17
+ /** @see {@link MatterSpecification.v141.Core}, section 11.22.5.2 */
18
+ export interface BdxSendAccept {
19
+ /**
20
+ * Transfer control details
21
+ * TC
22
+ * 1 octet
23
+ */
24
+ transferControl: TypeFromPartialBitSchema<typeof BdxTransferControlBitmap>;
25
+
26
+ /**
27
+ * Specifies the maximum data size (in bytes) of the block that the Initiator supports, exclusive of block header
28
+ * fields, such as a block counter.
29
+ * MBS, 2 octets
30
+ */
31
+ maxBlockSize: number;
32
+
33
+ /**
34
+ * Allows the Initiator to send additional application-specific information about the file to be transferred
35
+ * MD, Variable length, TLV
36
+ */
37
+ metaData?: Bytes;
38
+ }
39
+
40
+ /** @see {@link MatterSpecification.v141.Core}, section 11.22.5.3 */
41
+ export interface BdxReceiveAccept extends BdxSendAccept {
42
+ /**
43
+ * Specifies a predetermined definite length for the transfer
44
+ * DEFLEN, 4/8 octets
45
+ */
46
+ length?: number | bigint;
47
+ }
48
+
49
+ /** Schema for BDX SendAccept message */
50
+ export class BdxSendAcceptMessageSchema<M extends BdxSendAccept> extends Schema<M> {
51
+ encodeInternal(message: M) {
52
+ this.validate(message);
53
+ const { transferControl, maxBlockSize, metaData } = message;
54
+
55
+ const writer = new DataWriter(Endian.Little);
56
+ writer.writeUInt8(BdxTransferControlSchema.encode(transferControl));
57
+ writer.writeUInt16(maxBlockSize);
58
+
59
+ if (metaData && metaData.byteLength > 0) {
60
+ writer.writeByteArray(metaData);
61
+ }
62
+
63
+ return writer.toByteArray();
64
+ }
65
+
66
+ decodeInternal(bytes: Bytes): M {
67
+ const reader = new DataReader(bytes, Endian.Little);
68
+ const transferControl = BdxTransferControlSchema.decode(reader.readUInt8());
69
+ const maxBlockSize = reader.readUInt16();
70
+
71
+ const metaData = reader.remainingBytesCount > 0 ? reader.remainingBytes : undefined;
72
+
73
+ const result = {
74
+ transferControl,
75
+ maxBlockSize,
76
+ metaData,
77
+ } as M;
78
+ this.validate(result);
79
+ return result;
80
+ }
81
+
82
+ override validate({ transferControl, maxBlockSize }: M) {
83
+ if (transferControl.version !== BDX_VERSION) {
84
+ throw new BdxError(
85
+ `Unsupported BDX version: ${transferControl.version}`,
86
+ BdxStatusCode.VersionNotSupported,
87
+ );
88
+ }
89
+ if (!transferControl.senderDrive && !transferControl.receiverDrive && !transferControl.asynchronousTransfer) {
90
+ throw new BdxError(
91
+ "BDX transfer control need to specify at least one of sender drive, receiver drive or asynchronousTransfer",
92
+ BdxStatusCode.BadMessageContent,
93
+ );
94
+ }
95
+ if (maxBlockSize < 1 || maxBlockSize > 0xffff) {
96
+ throw new BdxError("Max Block Size must be between 1 and 65535bytes", BdxStatusCode.BadMessageContent);
97
+ }
98
+ }
99
+ }
100
+ export const BdxSendAcceptMessage = new BdxSendAcceptMessageSchema();
101
+
102
+ /** Schema for Bdx ReceiveAccept message */
103
+ export class BdxReceiveAcceptMessageSchema extends BdxSendAcceptMessageSchema<BdxReceiveAccept> {
104
+ override encodeInternal(message: BdxReceiveAccept) {
105
+ this.validate(message);
106
+ const { transferControl, maxBlockSize, metaData, length } = message;
107
+
108
+ const rangeControl = {
109
+ definiteLength: length !== undefined && length !== 0,
110
+ wideRange: typeof length === "bigint",
111
+ };
112
+
113
+ const writer = new DataWriter(Endian.Little);
114
+ writer.writeUInt8(BdxTransferControlSchema.encode(transferControl));
115
+ writer.writeUInt8(BdxRangeControlSchema.encode(rangeControl));
116
+ writer.writeUInt16(maxBlockSize);
117
+
118
+ if (length !== undefined && length !== 0) {
119
+ if (rangeControl.wideRange) {
120
+ writer.writeUInt64(length);
121
+ } else {
122
+ writer.writeUInt32(length);
123
+ }
124
+ }
125
+
126
+ if (metaData && metaData.byteLength > 0) {
127
+ writer.writeByteArray(metaData);
128
+ }
129
+
130
+ return writer.toByteArray();
131
+ }
132
+
133
+ override decodeInternal(bytes: Bytes): BdxReceiveAccept {
134
+ const reader = new DataReader(bytes, Endian.Little);
135
+ const transferControl = BdxTransferControlSchema.decode(reader.readUInt8());
136
+ const rangeControl = BdxRangeControlSchema.decode(reader.readUInt8());
137
+ const maxBlockSize = reader.readUInt16();
138
+
139
+ let length = rangeControl.definiteLength
140
+ ? rangeControl.wideRange
141
+ ? reader.readUInt64()
142
+ : reader.readUInt32()
143
+ : undefined;
144
+ if (length === 0) {
145
+ length = undefined; // 0 also means indefinite length
146
+ }
147
+ const metaData = reader.remainingBytesCount > 0 ? reader.remainingBytes : undefined;
148
+
149
+ const result = {
150
+ transferControl,
151
+ maxBlockSize,
152
+ metaData,
153
+ length,
154
+ };
155
+ this.validate(result);
156
+ return result;
157
+ }
158
+ }
159
+ export const BdxReceiveAcceptMessage = new BdxReceiveAcceptMessageSchema();