@matter/protocol 0.16.0-alpha.0-20250913-0bc2515df → 0.16.0-alpha.0-20250920-809524dba
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.
- package/dist/cjs/bdx/BdxClient.d.ts +31 -0
- package/dist/cjs/bdx/BdxClient.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxClient.js +57 -0
- package/dist/cjs/bdx/BdxClient.js.map +6 -0
- package/dist/cjs/bdx/BdxError.d.ts +21 -0
- package/dist/cjs/bdx/BdxError.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxError.js +54 -0
- package/dist/cjs/bdx/BdxError.js.map +6 -0
- package/dist/cjs/bdx/BdxMessenger.d.ts +77 -0
- package/dist/cjs/bdx/BdxMessenger.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxMessenger.js +245 -0
- package/dist/cjs/bdx/BdxMessenger.js.map +6 -0
- package/dist/cjs/bdx/BdxProtocol.d.ts +25 -0
- package/dist/cjs/bdx/BdxProtocol.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxProtocol.js +102 -0
- package/dist/cjs/bdx/BdxProtocol.js.map +6 -0
- package/dist/cjs/bdx/BdxSession.d.ts +36 -0
- package/dist/cjs/bdx/BdxSession.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxSession.js +153 -0
- package/dist/cjs/bdx/BdxSession.js.map +6 -0
- package/dist/cjs/bdx/BdxSessionConfiguration.d.ts +61 -0
- package/dist/cjs/bdx/BdxSessionConfiguration.d.ts.map +1 -0
- package/dist/cjs/bdx/BdxSessionConfiguration.js +95 -0
- package/dist/cjs/bdx/BdxSessionConfiguration.js.map +6 -0
- package/dist/cjs/bdx/FileDesignator.d.ts +21 -0
- package/dist/cjs/bdx/FileDesignator.d.ts.map +1 -0
- package/dist/cjs/bdx/FileDesignator.js +62 -0
- package/dist/cjs/bdx/FileDesignator.js.map +6 -0
- package/dist/cjs/bdx/PersistedFileDesignator.d.ts +16 -0
- package/dist/cjs/bdx/PersistedFileDesignator.d.ts.map +1 -0
- package/dist/cjs/bdx/PersistedFileDesignator.js +57 -0
- package/dist/cjs/bdx/PersistedFileDesignator.js.map +6 -0
- package/dist/cjs/bdx/bdx-session-initiator.d.ts +14 -0
- package/dist/cjs/bdx/bdx-session-initiator.d.ts.map +1 -0
- package/dist/cjs/bdx/bdx-session-initiator.js +218 -0
- package/dist/cjs/bdx/bdx-session-initiator.js.map +6 -0
- package/dist/cjs/bdx/flow/DrivenSendingFlow.d.ts +15 -0
- package/dist/cjs/bdx/flow/DrivenSendingFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/DrivenSendingFlow.js +49 -0
- package/dist/cjs/bdx/flow/DrivenSendingFlow.js.map +6 -0
- package/dist/cjs/bdx/flow/DrivingReceivingFlow.d.ts +15 -0
- package/dist/cjs/bdx/flow/DrivingReceivingFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/DrivingReceivingFlow.js +47 -0
- package/dist/cjs/bdx/flow/DrivingReceivingFlow.js.map +6 -0
- package/dist/cjs/bdx/flow/Flow.d.ts +48 -0
- package/dist/cjs/bdx/flow/Flow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/Flow.js +112 -0
- package/dist/cjs/bdx/flow/Flow.js.map +6 -0
- package/dist/cjs/bdx/flow/FollowingReceivingFlow.d.ts +16 -0
- package/dist/cjs/bdx/flow/FollowingReceivingFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/FollowingReceivingFlow.js +60 -0
- package/dist/cjs/bdx/flow/FollowingReceivingFlow.js.map +6 -0
- package/dist/cjs/bdx/flow/FollowingSendingFlow.d.ts +15 -0
- package/dist/cjs/bdx/flow/FollowingSendingFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/FollowingSendingFlow.js +49 -0
- package/dist/cjs/bdx/flow/FollowingSendingFlow.js.map +6 -0
- package/dist/cjs/bdx/flow/InboundFlow.d.ts +26 -0
- package/dist/cjs/bdx/flow/InboundFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/InboundFlow.js +101 -0
- package/dist/cjs/bdx/flow/InboundFlow.js.map +6 -0
- package/dist/cjs/bdx/flow/OutboundFlow.d.ts +31 -0
- package/dist/cjs/bdx/flow/OutboundFlow.d.ts.map +1 -0
- package/dist/cjs/bdx/flow/OutboundFlow.js +124 -0
- package/dist/cjs/bdx/flow/OutboundFlow.js.map +6 -0
- package/dist/cjs/bdx/index.d.ts +16 -0
- package/dist/cjs/bdx/index.d.ts.map +1 -0
- package/dist/cjs/bdx/index.js +33 -0
- package/dist/cjs/bdx/index.js.map +6 -0
- package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.d.ts +50 -0
- package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.js +125 -0
- package/dist/cjs/bdx/schema/BdxAcceptMessagesSchema.js.map +6 -0
- package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.d.ts +53 -0
- package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.js +92 -0
- package/dist/cjs/bdx/schema/BdxBlockMessagesSchema.js.map +6 -0
- package/dist/cjs/bdx/schema/BdxInitMessagesSchema.d.ts +117 -0
- package/dist/cjs/bdx/schema/BdxInitMessagesSchema.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/BdxInitMessagesSchema.js +153 -0
- package/dist/cjs/bdx/schema/BdxInitMessagesSchema.js.map +6 -0
- package/dist/cjs/bdx/schema/BdxMessage.d.ts +23 -0
- package/dist/cjs/bdx/schema/BdxMessage.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/BdxMessage.js +75 -0
- package/dist/cjs/bdx/schema/BdxMessage.js.map +6 -0
- package/dist/cjs/bdx/schema/BdxStatusMessageSchema.d.ts +12 -0
- package/dist/cjs/bdx/schema/BdxStatusMessageSchema.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/BdxStatusMessageSchema.js +35 -0
- package/dist/cjs/bdx/schema/BdxStatusMessageSchema.js.map +6 -0
- package/dist/cjs/bdx/schema/index.d.ts +11 -0
- package/dist/cjs/bdx/schema/index.d.ts.map +1 -0
- package/dist/cjs/bdx/schema/index.js +28 -0
- package/dist/cjs/bdx/schema/index.js.map +6 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mdns/MdnsClient.js +2 -2
- package/dist/cjs/mdns/MdnsClient.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +4 -2
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +2 -0
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +14 -8
- package/dist/cjs/protocol/MessageExchange.js.map +2 -2
- package/dist/cjs/protocol/ProtocolStatusMessage.d.ts +1 -1
- package/dist/cjs/protocol/ProtocolStatusMessage.d.ts.map +1 -1
- package/dist/cjs/protocol/ProtocolStatusMessage.js.map +1 -1
- package/dist/esm/bdx/BdxClient.d.ts +31 -0
- package/dist/esm/bdx/BdxClient.d.ts.map +1 -0
- package/dist/esm/bdx/BdxClient.js +37 -0
- package/dist/esm/bdx/BdxClient.js.map +6 -0
- package/dist/esm/bdx/BdxError.d.ts +21 -0
- package/dist/esm/bdx/BdxError.d.ts.map +1 -0
- package/dist/esm/bdx/BdxError.js +34 -0
- package/dist/esm/bdx/BdxError.js.map +6 -0
- package/dist/esm/bdx/BdxMessenger.d.ts +77 -0
- package/dist/esm/bdx/BdxMessenger.d.ts.map +1 -0
- package/dist/esm/bdx/BdxMessenger.js +233 -0
- package/dist/esm/bdx/BdxMessenger.js.map +6 -0
- package/dist/esm/bdx/BdxProtocol.d.ts +25 -0
- package/dist/esm/bdx/BdxProtocol.d.ts.map +1 -0
- package/dist/esm/bdx/BdxProtocol.js +82 -0
- package/dist/esm/bdx/BdxProtocol.js.map +6 -0
- package/dist/esm/bdx/BdxSession.d.ts +36 -0
- package/dist/esm/bdx/BdxSession.d.ts.map +1 -0
- package/dist/esm/bdx/BdxSession.js +133 -0
- package/dist/esm/bdx/BdxSession.js.map +6 -0
- package/dist/esm/bdx/BdxSessionConfiguration.d.ts +61 -0
- package/dist/esm/bdx/BdxSessionConfiguration.d.ts.map +1 -0
- package/dist/esm/bdx/BdxSessionConfiguration.js +75 -0
- package/dist/esm/bdx/BdxSessionConfiguration.js.map +6 -0
- package/dist/esm/bdx/FileDesignator.d.ts +21 -0
- package/dist/esm/bdx/FileDesignator.d.ts.map +1 -0
- package/dist/esm/bdx/FileDesignator.js +42 -0
- package/dist/esm/bdx/FileDesignator.js.map +6 -0
- package/dist/esm/bdx/PersistedFileDesignator.d.ts +16 -0
- package/dist/esm/bdx/PersistedFileDesignator.d.ts.map +1 -0
- package/dist/esm/bdx/PersistedFileDesignator.js +37 -0
- package/dist/esm/bdx/PersistedFileDesignator.js.map +6 -0
- package/dist/esm/bdx/bdx-session-initiator.d.ts +14 -0
- package/dist/esm/bdx/bdx-session-initiator.d.ts.map +1 -0
- package/dist/esm/bdx/bdx-session-initiator.js +198 -0
- package/dist/esm/bdx/bdx-session-initiator.js.map +6 -0
- package/dist/esm/bdx/flow/DrivenSendingFlow.d.ts +15 -0
- package/dist/esm/bdx/flow/DrivenSendingFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/DrivenSendingFlow.js +29 -0
- package/dist/esm/bdx/flow/DrivenSendingFlow.js.map +6 -0
- package/dist/esm/bdx/flow/DrivingReceivingFlow.d.ts +15 -0
- package/dist/esm/bdx/flow/DrivingReceivingFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/DrivingReceivingFlow.js +27 -0
- package/dist/esm/bdx/flow/DrivingReceivingFlow.js.map +6 -0
- package/dist/esm/bdx/flow/Flow.d.ts +48 -0
- package/dist/esm/bdx/flow/Flow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/Flow.js +92 -0
- package/dist/esm/bdx/flow/Flow.js.map +6 -0
- package/dist/esm/bdx/flow/FollowingReceivingFlow.d.ts +16 -0
- package/dist/esm/bdx/flow/FollowingReceivingFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/FollowingReceivingFlow.js +40 -0
- package/dist/esm/bdx/flow/FollowingReceivingFlow.js.map +6 -0
- package/dist/esm/bdx/flow/FollowingSendingFlow.d.ts +15 -0
- package/dist/esm/bdx/flow/FollowingSendingFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/FollowingSendingFlow.js +29 -0
- package/dist/esm/bdx/flow/FollowingSendingFlow.js.map +6 -0
- package/dist/esm/bdx/flow/InboundFlow.d.ts +26 -0
- package/dist/esm/bdx/flow/InboundFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/InboundFlow.js +81 -0
- package/dist/esm/bdx/flow/InboundFlow.js.map +6 -0
- package/dist/esm/bdx/flow/OutboundFlow.d.ts +31 -0
- package/dist/esm/bdx/flow/OutboundFlow.d.ts.map +1 -0
- package/dist/esm/bdx/flow/OutboundFlow.js +104 -0
- package/dist/esm/bdx/flow/OutboundFlow.js.map +6 -0
- package/dist/esm/bdx/index.d.ts +16 -0
- package/dist/esm/bdx/index.d.ts.map +1 -0
- package/dist/esm/bdx/index.js +16 -0
- package/dist/esm/bdx/index.js.map +6 -0
- package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.d.ts +50 -0
- package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.d.ts.map +1 -0
- package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.js +109 -0
- package/dist/esm/bdx/schema/BdxAcceptMessagesSchema.js.map +6 -0
- package/dist/esm/bdx/schema/BdxBlockMessagesSchema.d.ts +53 -0
- package/dist/esm/bdx/schema/BdxBlockMessagesSchema.d.ts.map +1 -0
- package/dist/esm/bdx/schema/BdxBlockMessagesSchema.js +72 -0
- package/dist/esm/bdx/schema/BdxBlockMessagesSchema.js.map +6 -0
- package/dist/esm/bdx/schema/BdxInitMessagesSchema.d.ts +117 -0
- package/dist/esm/bdx/schema/BdxInitMessagesSchema.d.ts.map +1 -0
- package/dist/esm/bdx/schema/BdxInitMessagesSchema.js +133 -0
- package/dist/esm/bdx/schema/BdxInitMessagesSchema.js.map +6 -0
- package/dist/esm/bdx/schema/BdxMessage.d.ts +23 -0
- package/dist/esm/bdx/schema/BdxMessage.d.ts.map +1 -0
- package/dist/esm/bdx/schema/BdxMessage.js +62 -0
- package/dist/esm/bdx/schema/BdxMessage.js.map +6 -0
- package/dist/esm/bdx/schema/BdxStatusMessageSchema.d.ts +12 -0
- package/dist/esm/bdx/schema/BdxStatusMessageSchema.d.ts.map +1 -0
- package/dist/esm/bdx/schema/BdxStatusMessageSchema.js +15 -0
- package/dist/esm/bdx/schema/BdxStatusMessageSchema.js.map +6 -0
- package/dist/esm/bdx/schema/index.d.ts +11 -0
- package/dist/esm/bdx/schema/index.d.ts.map +1 -0
- package/dist/esm/bdx/schema/index.js +11 -0
- package/dist/esm/bdx/schema/index.js.map +6 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mdns/MdnsClient.js +2 -2
- package/dist/esm/mdns/MdnsClient.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +4 -2
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +2 -0
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +14 -8
- package/dist/esm/protocol/MessageExchange.js.map +2 -2
- package/dist/esm/protocol/ProtocolStatusMessage.d.ts +1 -1
- package/dist/esm/protocol/ProtocolStatusMessage.d.ts.map +1 -1
- package/dist/esm/protocol/ProtocolStatusMessage.js.map +1 -1
- package/package.json +6 -6
- package/src/bdx/BdxClient.ts +47 -0
- package/src/bdx/BdxError.ts +39 -0
- package/src/bdx/BdxMessenger.ts +291 -0
- package/src/bdx/BdxProtocol.ts +93 -0
- package/src/bdx/BdxSession.ts +174 -0
- package/src/bdx/BdxSessionConfiguration.ts +134 -0
- package/src/bdx/FileDesignator.ts +49 -0
- package/src/bdx/PersistedFileDesignator.ts +40 -0
- package/src/bdx/bdx-session-initiator.ts +246 -0
- package/src/bdx/flow/DrivenSendingFlow.ts +40 -0
- package/src/bdx/flow/DrivingReceivingFlow.ts +39 -0
- package/src/bdx/flow/Flow.ts +124 -0
- package/src/bdx/flow/FollowingReceivingFlow.ts +53 -0
- package/src/bdx/flow/FollowingSendingFlow.ts +38 -0
- package/src/bdx/flow/InboundFlow.ts +104 -0
- package/src/bdx/flow/OutboundFlow.ts +124 -0
- package/src/bdx/index.ts +16 -0
- package/src/bdx/schema/BdxAcceptMessagesSchema.ts +159 -0
- package/src/bdx/schema/BdxBlockMessagesSchema.ts +99 -0
- package/src/bdx/schema/BdxInitMessagesSchema.ts +213 -0
- package/src/bdx/schema/BdxMessage.ts +70 -0
- package/src/bdx/schema/BdxStatusMessageSchema.ts +14 -0
- package/src/bdx/schema/index.ts +11 -0
- package/src/index.ts +1 -0
- package/src/mdns/MdnsClient.ts +2 -2
- package/src/protocol/ExchangeManager.ts +2 -0
- package/src/protocol/MessageExchange.ts +17 -6
- package/src/protocol/ProtocolStatusMessage.ts +1 -1
|
@@ -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
|
+
}
|
|
@@ -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
|
+
}
|