@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,174 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { AsyncObservable, ClassExtends, Diagnostic, Logger, StorageContext } from "#general";
8
+ import { BdxMessageType, BdxStatusCode } from "#types";
9
+ import { bdxSessionInitiator } from "./bdx-session-initiator.js";
10
+ import { BdxError } from "./BdxError.js";
11
+ import { BdxMessenger } from "./BdxMessenger.js";
12
+ import { BdxSessionConfiguration } from "./BdxSessionConfiguration.js";
13
+ import { DrivenSendingFlow } from "./flow/DrivenSendingFlow.js";
14
+ import { DrivingReceivingFlow } from "./flow/DrivingReceivingFlow.js";
15
+ import { Flow } from "./flow/Flow.js";
16
+ import { FollowingReceivingFlow } from "./flow/FollowingReceivingFlow.js";
17
+ import { FollowingSendingFlow } from "./flow/FollowingSendingFlow.js";
18
+ import { PersistedFileDesignator } from "./PersistedFileDesignator.js";
19
+
20
+ const logger = Logger.get("BdxSession");
21
+
22
+ /**
23
+ * Class to manage one BDX session.
24
+ *
25
+ * Matter BDX protocol is used to transfer files between devices.
26
+ *
27
+ * Notes:
28
+ * * Even though Matter allows 64bit values for size and offset, we do not use them, as they make no sense for now.
29
+ * We support up to MAX_SAFE_INTEGER for size and offset (which basically is 2^53 - 1 and so far enough for us).
30
+ * * We support partial transfers (startOffset or shorter dataLength) only when we act as the sender. As a receiver,
31
+ * only full transfers are supported.
32
+ * * We do not use BlockQueryWithSkip when requesting data ourselves
33
+ */
34
+ export class BdxSession {
35
+ #messenger: BdxMessenger;
36
+ #started = false;
37
+ #closed = AsyncObservable();
38
+ #isClosed = false;
39
+
40
+ #config: BdxSessionConfiguration;
41
+
42
+ #transferFlow?: Flow;
43
+
44
+ /** Initializes a BdxSession as a sender, means that we upload data to the peer. */
45
+ static asSender(messenger: BdxMessenger, options: BdxSessionConfiguration.SenderInitiatorOptions): BdxSession {
46
+ return new BdxSession(messenger, { isSender: true, ...options });
47
+ }
48
+
49
+ /** Initializes a BdxSession as a receiver, means that we download data from the peer. */
50
+ static asReceiver(messenger: BdxMessenger, options: BdxSessionConfiguration.InitiatorOptions): BdxSession {
51
+ return new BdxSession(messenger, { isSender: false, ...options });
52
+ }
53
+
54
+ /** Initializes a BdxSession from an incoming *Init message. The message determines the direction of the transfer. */
55
+ static fromMessage(
56
+ storage: StorageContext,
57
+ messenger: BdxMessenger,
58
+ options: BdxSessionConfiguration.ReceiverOptions,
59
+ ): BdxSession {
60
+ const { initMessageType, initMessage } = options;
61
+ if (initMessageType !== BdxMessageType.SendInit && initMessageType !== BdxMessageType.ReceiveInit) {
62
+ throw new BdxError(
63
+ `Invalid message type for BDX session initialization: ${BdxMessageType[initMessageType]} (${initMessageType})`,
64
+ BdxStatusCode.UnexpectedMessage,
65
+ );
66
+ }
67
+
68
+ const { fileDesignator } = initMessage;
69
+
70
+ return new BdxSession(messenger, {
71
+ isSender: initMessageType === BdxMessageType.ReceiveInit,
72
+ fileDesignator: new PersistedFileDesignator(fileDesignator, storage),
73
+ ...options,
74
+ });
75
+ }
76
+
77
+ private constructor(messenger: BdxMessenger, options: BdxSessionConfiguration.Options) {
78
+ this.#messenger = messenger;
79
+
80
+ this.#config = new BdxSessionConfiguration(options);
81
+
82
+ const exchange = messenger.exchange;
83
+ if (!exchange.channel.isReliable) {
84
+ throw new BdxError("Bdx Protocol requires a reliable channel for message exchange");
85
+ }
86
+ exchange.closed.on(async () => {
87
+ logger.debug(`Closing BDX session for exchange ${exchange.id}`);
88
+ await this.close();
89
+ });
90
+ }
91
+
92
+ /** Method called to start the session. It will end with a successful Transfer or with an error */
93
+ async processTransfer() {
94
+ if (this.#started) {
95
+ throw new BdxError("BDX session already started", BdxStatusCode.UnexpectedMessage);
96
+ }
97
+ if (this.#isClosed) {
98
+ throw new BdxError("BDX session already closed", BdxStatusCode.UnexpectedMessage);
99
+ }
100
+
101
+ const { isSender, isInitiator, fileDesignator } = this.#config;
102
+ logger.info(
103
+ `Starting BDX session`,
104
+ Diagnostic.dict({
105
+ exId: this.#messenger.exchange.id,
106
+ isSender,
107
+ isInitiator,
108
+ blobName: fileDesignator?.text,
109
+ }),
110
+ );
111
+
112
+ this.#started = true;
113
+ try {
114
+ this.#transferFlow = this.#initializeFlow(await bdxSessionInitiator(this.#messenger, this.#config));
115
+
116
+ await this.#transferFlow.processTransfer();
117
+
118
+ await this.close();
119
+ } catch (error) {
120
+ BdxError.accept(error);
121
+ await this.#messenger.sendError(error.code);
122
+
123
+ logger.warn(`BDX session failed with error:`, error);
124
+
125
+ await this.close(error);
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ #initializeFlow(transferParameters: Flow.TransferOptions): Flow {
131
+ const { transferMode, asynchronousTransfer, dataLength, isDriver, fileDesignator } = transferParameters;
132
+ const isSenderDrive = transferMode === Flow.DriverMode.SenderDrive;
133
+
134
+ const role = `${isSenderDrive ? `${asynchronousTransfer ? "async " : ""}sending` : "receiving"} ${isDriver ? "driver" : "follower"}`;
135
+ logger.debug(
136
+ `Starting transfer flow as ${role}`,
137
+ Diagnostic.dict({
138
+ exId: this.#messenger.exchange.id,
139
+ dataLength,
140
+ blobName: fileDesignator.text,
141
+ }),
142
+ );
143
+
144
+ let FlowImpl: ClassExtends<Flow>;
145
+ if (isDriver) {
146
+ if (isSenderDrive || asynchronousTransfer) {
147
+ FlowImpl = DrivenSendingFlow;
148
+ } else {
149
+ FlowImpl = DrivingReceivingFlow;
150
+ }
151
+ } else if (isSenderDrive || asynchronousTransfer) {
152
+ FlowImpl = FollowingSendingFlow;
153
+ } else {
154
+ FlowImpl = FollowingReceivingFlow;
155
+ }
156
+
157
+ return new FlowImpl(this.#messenger, transferParameters);
158
+ }
159
+
160
+ get closed() {
161
+ return this.#closed;
162
+ }
163
+
164
+ async close(error?: unknown) {
165
+ if (this.#isClosed) {
166
+ return;
167
+ }
168
+ this.#isClosed = true;
169
+ await this.#transferFlow?.close(error);
170
+ await this.#closed.emit();
171
+ }
172
+ }
173
+
174
+ export namespace BdxSession {}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { ImplementationError } from "#general";
8
+ import { BdxMessageType } from "#types";
9
+ import { Flow } from "./flow/Flow.js";
10
+ import { PersistedFileDesignator } from "./PersistedFileDesignator.js";
11
+ import { BdxInit } from "./schema/BdxInitMessagesSchema.js";
12
+
13
+ export class BdxSessionConfiguration {
14
+ #isSender: boolean;
15
+ #initMessage?: BdxInit;
16
+ #transferConfig: BdxSessionConfiguration.Config;
17
+ #fileDesignator: PersistedFileDesignator;
18
+
19
+ constructor(options: BdxSessionConfiguration.Options) {
20
+ const { isSender, fileDesignator, initMessage } = options;
21
+ this.#fileDesignator = fileDesignator;
22
+ this.#isSender = isSender;
23
+ this.#initMessage = initMessage;
24
+ this.#transferConfig = { ...BdxSessionConfiguration.DefaultConfig, ...options };
25
+
26
+ // Validate Config
27
+ const {
28
+ preferredDriverModes = [],
29
+ maxBlockSize,
30
+ maxTransferSize,
31
+ asynchronousTransferAllowed,
32
+ senderStartOffset,
33
+ senderMaxLength,
34
+ } = this.#transferConfig;
35
+ if (preferredDriverModes.length === 0) {
36
+ throw new ImplementationError("At least one preferred driver mode must be set.");
37
+ }
38
+ if (maxBlockSize !== undefined && maxBlockSize <= 0) {
39
+ throw new ImplementationError("Max block size must be greater than 0");
40
+ }
41
+ if (maxTransferSize !== undefined && maxTransferSize <= 0) {
42
+ throw new ImplementationError("Max transfer size must be greater than 0");
43
+ }
44
+ if (asynchronousTransferAllowed) {
45
+ throw new ImplementationError("Asynchronous transfer is not supported");
46
+ }
47
+ if (!isSender && (senderStartOffset !== undefined || senderMaxLength !== undefined)) {
48
+ throw new ImplementationError("Sender start offset and sender max length are only supported for senders");
49
+ }
50
+ }
51
+
52
+ get isSender(): boolean {
53
+ return this.#isSender;
54
+ }
55
+
56
+ get initMessage(): BdxInit | undefined {
57
+ return this.#initMessage;
58
+ }
59
+
60
+ get isInitiator(): boolean {
61
+ return this.#initMessage === undefined;
62
+ }
63
+
64
+ get fileDesignator(): PersistedFileDesignator {
65
+ return this.#fileDesignator;
66
+ }
67
+
68
+ get transferConfig(): BdxSessionConfiguration.Config {
69
+ return this.#transferConfig;
70
+ }
71
+ }
72
+
73
+ export namespace BdxSessionConfiguration {
74
+ export interface Config {
75
+ /**
76
+ * Array of preferred transfer driver modes, in order of preference. Use this to configure the proposed behavior.
77
+ * Default is [SenderDrive, ReceiverDrive]
78
+ */
79
+ preferredDriverModes?: Flow.DriverMode[];
80
+
81
+ /** Asynchronous transfer is not supported right now because provisional. */
82
+ asynchronousTransferAllowed?: false; // not supported right now, so must be false
83
+
84
+ /** Maximum block size to use for the session. This value is ignored if the transport only supports smaller blocks. */
85
+ maxBlockSize?: number;
86
+
87
+ /** Maximum transfer size to use for the session. Defaults to 100MB */
88
+ maxTransferSize?: number;
89
+
90
+ /** The start offset of the data to send. When using this, you need to know what you are doing. */
91
+ senderStartOffset?: number;
92
+
93
+ /** The maximum length of the data to send. When using this, you need to know what you are doing. */
94
+ senderMaxLength?: number;
95
+ }
96
+
97
+ export const DefaultConfig: BdxSessionConfiguration.Config = {
98
+ preferredDriverModes: [
99
+ Flow.DriverMode.SenderDrive, // Default if multiple is supported, so lets use this
100
+ Flow.DriverMode.ReceiverDrive,
101
+ ],
102
+ asynchronousTransferAllowed: false, // Provisional, not supported
103
+ maxTransferSize: 1_024 * 100_000, // 100 MB, lets use that as maximum transfer filesize for now just to protect
104
+ };
105
+
106
+ export interface InitiatorOptions extends BdxSessionConfiguration.Config {
107
+ /** FileDesignator to use for the session. The value is usually pre-determined with the peer. */
108
+ fileDesignator: PersistedFileDesignator;
109
+ }
110
+
111
+ export interface SenderInitiatorOptions extends InitiatorOptions {
112
+ /** The start offset of the data to send. When using this, you need to know what you are doing. */
113
+ senderStartOffset?: number;
114
+
115
+ /** The maximum length of the data to send. When using this, you need to know what you are doing. */
116
+ senderMaxLength?: number;
117
+ }
118
+
119
+ export interface ReceiverOptions extends BdxSessionConfiguration.Config {
120
+ initMessageType: BdxMessageType;
121
+ initMessage: BdxInit; // The initial message received to start the session
122
+ }
123
+
124
+ export interface Options extends BdxSessionConfiguration.Config {
125
+ /** True if the session is initiated as a sender, false for receiver */
126
+ isSender: boolean;
127
+
128
+ /** File designator to use for the session */
129
+ fileDesignator: PersistedFileDesignator;
130
+
131
+ /** The initial message received to start the session */
132
+ initMessage?: BdxInit;
133
+ }
134
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Bytes } from "#general";
8
+
9
+ /**
10
+ * Class to represent a File designator from Matter.
11
+ * Specification wise this is a bytes object, but to store in a storage we need a string name.
12
+ * This class provides a way to convert between the two.
13
+ */
14
+ export class FileDesignator {
15
+ #fd: Bytes;
16
+
17
+ /** Create a FileDesignator from a string or bytes object. */
18
+ constructor(fd: string | Bytes) {
19
+ if (typeof fd === "string") {
20
+ this.#fd = Bytes.fromString(fd);
21
+ } else {
22
+ this.#fd = fd;
23
+ }
24
+ }
25
+
26
+ /** Return the bytes representation of the FileDesignator. */
27
+ get bytes(): Bytes {
28
+ return this.#fd;
29
+ }
30
+
31
+ /** Return the textual/string representation of the FileDesignator. */
32
+ get text(): string {
33
+ const fileDesignatorData = Bytes.of(this.#fd);
34
+ // When all uint8 values are in char() range "a-z0-0-." then use this as the blob name, else hex encode it
35
+ const isValidName = fileDesignatorData.every(
36
+ byte =>
37
+ (byte >= 0x41 && byte <= 0x5a) || // A-Z
38
+ (byte >= 0x61 && byte <= 0x7a) || // a-z
39
+ (byte >= 0x30 && byte <= 0x39) || // 0..9
40
+ byte === 0x2e || // "."
41
+ byte === 0x2d, // "-"
42
+ );
43
+ if (isValidName) {
44
+ return fileDesignatorData.reduce((name, byte) => name + String.fromCharCode(byte), "");
45
+ } else {
46
+ return `0x${Bytes.toHex(fileDesignatorData)}`;
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Bytes, ImplementationError, StorageContext } from "#general";
8
+ import { FileDesignator } from "./FileDesignator.js";
9
+
10
+ /** A FileDesignator that points to a persisted file in a given StorageContext. */
11
+ export class PersistedFileDesignator extends FileDesignator {
12
+ #storage: StorageContext;
13
+ #blob?: Blob;
14
+
15
+ constructor(fd: string | Bytes, storage: StorageContext) {
16
+ super(fd);
17
+ this.#storage = storage;
18
+ }
19
+
20
+ exists() {
21
+ return this.#storage.has(this.text);
22
+ }
23
+
24
+ async openBlob() {
25
+ if (this.#blob === undefined) {
26
+ const blobName = this.text;
27
+ if (!this.#storage.has(blobName)) {
28
+ throw new ImplementationError(
29
+ "File designator must point to an existing file in the storage to send data",
30
+ );
31
+ }
32
+ this.#blob = await this.#storage.openBlob(blobName);
33
+ }
34
+ return this.#blob;
35
+ }
36
+
37
+ writeFromStream(stream: ReadableStream<Bytes>) {
38
+ return this.#storage.writeBlobFromStream(this.text, stream);
39
+ }
40
+ }
@@ -0,0 +1,246 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { ImplementationError, InternalError, Logger } from "#general";
8
+ import { BdxStatusCode, TypeFromPartialBitSchema } from "#types";
9
+ import { BdxError } from "./BdxError.js";
10
+ import { BdxMessenger } from "./BdxMessenger.js";
11
+ import { BdxSessionConfiguration } from "./BdxSessionConfiguration.js";
12
+ import { Flow } from "./flow/Flow.js";
13
+ import { BdxReceiveAccept, BdxSendAccept } from "./schema/BdxAcceptMessagesSchema.js";
14
+ import { BDX_VERSION, BdxInit, BdxTransferControlBitmap } from "./schema/BdxInitMessagesSchema.js";
15
+
16
+ const logger = Logger.get("bdxSessionInitiator");
17
+
18
+ /**
19
+ * Handles the initiation of a BDX session by exchanging *Init and *Accept messages and negotiating the transfer
20
+ * parameters.
21
+ */
22
+ export async function bdxSessionInitiator(messenger: BdxMessenger, config: BdxSessionConfiguration) {
23
+ if (config.isInitiator) {
24
+ if (config.isSender) {
25
+ // We are Sender and Initiator
26
+ const initMessage = await buildInitMessage();
27
+ const acceptMessage = await messenger.sendSendInit(initMessage);
28
+ return collectAcceptParameters(
29
+ acceptMessage,
30
+ // We define the data, so we know it are numbers
31
+ initMessage.startOffset !== undefined ? Number(initMessage.startOffset) : undefined,
32
+ initMessage.maxLength !== undefined ? Number(initMessage.maxLength) : undefined,
33
+ );
34
+ }
35
+
36
+ // We are Receiver and Initiator
37
+ const acceptMessage = await messenger.sendReceiveInit(await buildInitMessage());
38
+ return collectAcceptParameters(acceptMessage);
39
+ }
40
+
41
+ // We are starting from an incoming *Init message
42
+ const initMessage = config.initMessage;
43
+ if (initMessage === undefined) {
44
+ throw new InternalError("Initial message must be set before starting from initial message");
45
+ }
46
+ logger.debug(`Initialize BDX ${config.isSender ? "ReceiveInit" : "SendInit"} from incoming Message`, initMessage);
47
+
48
+ if (config.isSender) {
49
+ // We are Sender and Responder
50
+ if (!config.fileDesignator.exists()) {
51
+ throw new BdxError(
52
+ `File designator ${config.fileDesignator.text} does not point to an existing file in the storage to send data`,
53
+ BdxStatusCode.FileDesignatorUnknown,
54
+ );
55
+ }
56
+
57
+ let { startOffset } = initMessage;
58
+ if (startOffset !== undefined) {
59
+ startOffset = BdxMessenger.asSafeNumber(startOffset, "Start offset", BdxStatusCode.StartOffsetNotSupported);
60
+ }
61
+
62
+ const acceptMessage = await determineAcceptParameters(initMessage);
63
+
64
+ const length =
65
+ "length" in acceptMessage && typeof acceptMessage.length === "number" ? acceptMessage.length : undefined;
66
+
67
+ // If we received an Init message with a maxLength and we are the sender, we need to check if the
68
+ // available blob size is enough to send the requested maxLength.
69
+ const blobToRead = await config.fileDesignator.openBlob();
70
+
71
+ if (length !== undefined && length > 0) {
72
+ const availableSize = blobToRead.size - (startOffset ?? 0);
73
+ if (length > availableSize) {
74
+ throw new BdxError(
75
+ `Requested maxLength ${length}bytes${startOffset ? ` with startOffset ${startOffset}` : ""} exceeds available size ${blobToRead.size} for blob ${config.fileDesignator.text}`,
76
+ BdxStatusCode.LengthTooLarge,
77
+ );
78
+ }
79
+ }
80
+
81
+ await messenger.sendReceiveAccept(acceptMessage);
82
+
83
+ return collectAcceptParameters(acceptMessage, startOffset, length);
84
+ }
85
+
86
+ // We are Receiver and Responder
87
+ const acceptMessage = {
88
+ ...(await determineAcceptParameters(initMessage)),
89
+ length: undefined, // Length is not included in SendAccept, so take out to not confuse in logs
90
+ };
91
+ await messenger.sendSendAccept(acceptMessage);
92
+ return collectAcceptParameters(acceptMessage);
93
+
94
+ /** These are the proposed data that we send out to the peer device which include anything we can support */
95
+ async function buildInitMessage(): Promise<BdxInit> {
96
+ const {
97
+ senderStartOffset,
98
+ maxTransferSize,
99
+ senderMaxLength,
100
+ preferredDriverModes,
101
+ asynchronousTransferAllowed,
102
+ } = config.transferConfig;
103
+ const { isSender, fileDesignator } = config;
104
+
105
+ let startOffset: number | undefined;
106
+ let maxLength: number | undefined;
107
+ if (isSender) {
108
+ maxLength = (await fileDesignator.openBlob()).size;
109
+ if (senderStartOffset !== undefined) {
110
+ if (maxLength <= senderStartOffset) {
111
+ throw new ImplementationError(
112
+ `Available data of ${maxLength}bytes are smaller than senderStartOffset ${senderStartOffset}bytes`,
113
+ );
114
+ }
115
+ startOffset = senderStartOffset;
116
+ maxLength -= startOffset; // maxLength is the full file size we have, so subtract the start offset
117
+ }
118
+ if (maxTransferSize !== undefined) {
119
+ if (maxLength > maxTransferSize) {
120
+ throw new ImplementationError(
121
+ `Requested maxLength ${maxLength}bytes exceeds maximum transfer size ${maxTransferSize}bytes`,
122
+ );
123
+ }
124
+ }
125
+ if (senderMaxLength !== undefined) {
126
+ if (maxLength >= senderMaxLength) {
127
+ maxLength = senderMaxLength;
128
+ } else {
129
+ logger.info(
130
+ `Ignoring requested senderMaxLength ${senderMaxLength}bytes as it is larger then the relevant payload size of ${maxLength}bytes`,
131
+ );
132
+ }
133
+ }
134
+ }
135
+
136
+ let maxBlockSize = messenger.maxPayloadSize - 4; // 4 bytes for the block counter by default
137
+ const requestedBlockSize = config.transferConfig.maxBlockSize;
138
+ if (requestedBlockSize !== undefined) {
139
+ if (maxBlockSize > requestedBlockSize) {
140
+ maxBlockSize = requestedBlockSize;
141
+ } else {
142
+ logger.info(
143
+ `Ignoring requested maxBlockSize ${requestedBlockSize}, as it is larger then the transport max payload size ${maxBlockSize}bytes`,
144
+ );
145
+ }
146
+ }
147
+
148
+ return {
149
+ transferProtocol: {
150
+ version: BDX_VERSION,
151
+ senderDrive: !!preferredDriverModes?.includes(Flow.DriverMode.SenderDrive),
152
+ receiverDrive: !!preferredDriverModes?.includes(Flow.DriverMode.ReceiverDrive),
153
+ asynchronousTransfer: asynchronousTransferAllowed, // always false for now
154
+ },
155
+ maxBlockSize,
156
+ fileDesignator: fileDesignator.bytes,
157
+ startOffset,
158
+ maxLength,
159
+ };
160
+ }
161
+
162
+ /** Determine *Accept response parameters from an *Init message */
163
+ async function determineAcceptParameters(initMessage: BdxInit): Promise<BdxReceiveAccept | BdxSendAccept> {
164
+ const { transferProtocol, maxLength: initMaxLength = 0 } = initMessage;
165
+ let { maxBlockSize } = initMessage;
166
+
167
+ // We use the first matching mode between the offered and preferred modes
168
+ let finalDriverMode: Flow.DriverMode | undefined;
169
+ for (const mode of config.transferConfig.preferredDriverModes!) {
170
+ if (transferProtocol[mode]) {
171
+ finalDriverMode = mode;
172
+ break;
173
+ }
174
+ }
175
+ if (finalDriverMode === undefined) {
176
+ throw new BdxError("Can not determine a valid transfer mode", BdxStatusCode.TransferMethodNotSupported);
177
+ }
178
+
179
+ const requestedMaxBlockSize = config.transferConfig.maxBlockSize;
180
+ if (requestedMaxBlockSize !== undefined && maxBlockSize > requestedMaxBlockSize) {
181
+ maxBlockSize = requestedMaxBlockSize;
182
+ }
183
+
184
+ const maxLength = BdxMessenger.asSafeNumber(initMaxLength, "Max length", BdxStatusCode.LengthTooLarge);
185
+ // TODO: How to handle custom metadata?
186
+
187
+ const transferControl: TypeFromPartialBitSchema<typeof BdxTransferControlBitmap> = {
188
+ version: BDX_VERSION, // We support the minimum version, so no need for further checks
189
+ [finalDriverMode]: true, // this sets either senderDrive or receiveDriver property
190
+ asynchronousTransfer: false, // Not supported so ignore if it was received
191
+ };
192
+ return {
193
+ transferControl,
194
+ maxBlockSize,
195
+ length: maxLength > 0 ? maxLength : undefined,
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Collects the negotiated details from the *Accept message into the Transfer parameters.
201
+ * Also determines by the response if we are the driver or the peer.
202
+ */
203
+ function collectAcceptParameters(
204
+ acceptMessage: BdxSendAccept | BdxReceiveAccept,
205
+ startOffset = 0,
206
+ maxLength?: number,
207
+ ): Flow.TransferOptions {
208
+ const {
209
+ transferControl: { senderDrive, asynchronousTransfer },
210
+ maxBlockSize,
211
+ } = acceptMessage;
212
+ if (asynchronousTransfer) {
213
+ // Async is not supported by matter SDK and such, so always decline this for now
214
+ throw new BdxError(
215
+ "Asynchronous transfer is not supported in this implementation",
216
+ BdxStatusCode.TransferMethodNotSupported,
217
+ );
218
+ }
219
+
220
+ const dataLength =
221
+ "length" in acceptMessage && acceptMessage.length !== undefined
222
+ ? BdxMessenger.asSafeNumber(
223
+ acceptMessage.length,
224
+ "Accept message length field",
225
+ BdxStatusCode.LengthTooLarge,
226
+ )
227
+ : maxLength;
228
+
229
+ const transferParameters: Flow.TransferOptions = {
230
+ transferMode: senderDrive ? Flow.DriverMode.SenderDrive : Flow.DriverMode.ReceiverDrive,
231
+ asynchronousTransfer: false, // always false for now
232
+ dataLength,
233
+ startOffset,
234
+ blockSize: maxBlockSize,
235
+ isDriver: (config.isSender && senderDrive) || (!config.isSender && !senderDrive),
236
+ fileDesignator: config.fileDesignator,
237
+ };
238
+
239
+ logger.debug(
240
+ `${transferParameters.isDriver ? "We are" : "Peer is"} driving-${config.isSender ? "sender" : "receiver"} with negotiated transfer parameters`,
241
+ transferParameters,
242
+ );
243
+
244
+ return transferParameters;
245
+ }
246
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { OutboundFlow } from "./OutboundFlow.js";
8
+
9
+ /**
10
+ * BDX Transport flow logic for a "BDX Driving Sender":
11
+ * - Send out the Block and wait for Ack (if synchronous transfer is used)
12
+ * - Last message is sent with BlockEof and expects AckEof
13
+ */
14
+ export class DrivenSendingFlow extends OutboundFlow {
15
+ protected async transferNextChunk() {
16
+ const { asynchronousTransfer } = this.transferParameters;
17
+ const { iterator } = this.stream;
18
+
19
+ const blockCounter = this.nextMessageCounter;
20
+ // Read the next data chunk from the storage
21
+ const { data, done } = await this.readDataChunk(iterator);
22
+
23
+ if (done) {
24
+ // Send the last Block and wait for AckEof and close down
25
+ await this.messenger.sendBlockEof({ data: data ?? new Uint8Array(), blockCounter });
26
+ this.finalBlockCounter = blockCounter;
27
+ return true;
28
+ }
29
+
30
+ // Send the next Block
31
+ await this.messenger.sendBlock({ data, blockCounter });
32
+
33
+ // Sync transfer just continues when the Ack is received
34
+ if (!asynchronousTransfer) {
35
+ const { blockCounter: ackedBlockCounter } = await this.messenger.readBlockAck();
36
+ this.validateCounter(ackedBlockCounter, blockCounter);
37
+ }
38
+ return false;
39
+ }
40
+ }