@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,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
|
+
}
|
package/src/bdx/index.ts
ADDED
|
@@ -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();
|
|
@@ -0,0 +1,99 @@
|
|
|
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 { Schema } from "#types";
|
|
9
|
+
|
|
10
|
+
interface BdxCounterOnly {
|
|
11
|
+
blockCounter: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.2 */
|
|
15
|
+
export interface BdxBlockQuery extends BdxCounterOnly {}
|
|
16
|
+
|
|
17
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.6 */
|
|
18
|
+
export interface BdxBlockAck extends BdxCounterOnly {}
|
|
19
|
+
|
|
20
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.7 */
|
|
21
|
+
export interface BdxBlockAckEof extends BdxCounterOnly {}
|
|
22
|
+
|
|
23
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.3 */
|
|
24
|
+
export interface BdxBlockQueryWithSkip extends BdxCounterOnly {
|
|
25
|
+
bytesToSkip: number | bigint;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.4 */
|
|
29
|
+
export interface BdxBlock extends BdxCounterOnly {
|
|
30
|
+
data: Bytes;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** @see {@link MatterSpecification.v141.Core}, section 11.22.6.5 */
|
|
34
|
+
export interface BdxBlockEof extends BdxBlock {}
|
|
35
|
+
|
|
36
|
+
/** Schema for BDX messages that only contain a block counter: BlockQuery, BlockAck, BlockAckEof. */
|
|
37
|
+
export class BdxCounterOnlyMessageSchema extends Schema<BdxCounterOnly> {
|
|
38
|
+
encodeInternal(message: BdxCounterOnly) {
|
|
39
|
+
const { blockCounter } = message;
|
|
40
|
+
|
|
41
|
+
const writer = new DataWriter(Endian.Little);
|
|
42
|
+
writer.writeUInt32(blockCounter);
|
|
43
|
+
return writer.toByteArray();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
decodeInternal(bytes: Bytes): BdxCounterOnly {
|
|
47
|
+
const reader = new DataReader(bytes, Endian.Little);
|
|
48
|
+
return {
|
|
49
|
+
blockCounter: reader.readUInt32(),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const BdxCounterOnlyMessage = new BdxCounterOnlyMessageSchema();
|
|
54
|
+
export const BdxBlockQueryMessage = BdxCounterOnlyMessage;
|
|
55
|
+
export const BdxBlockAckMessage = BdxCounterOnlyMessage;
|
|
56
|
+
export const BdxBlockAckEofMessage = BdxCounterOnlyMessage;
|
|
57
|
+
|
|
58
|
+
/** Schema for BDX BlockQueryWithSkip message. */
|
|
59
|
+
export class BdxBlockQueryWithSkipMessageSchema extends Schema<BdxBlockQueryWithSkip> {
|
|
60
|
+
encodeInternal(message: BdxBlockQueryWithSkip) {
|
|
61
|
+
const { blockCounter, bytesToSkip } = message;
|
|
62
|
+
|
|
63
|
+
const writer = new DataWriter(Endian.Little);
|
|
64
|
+
writer.writeUInt32(blockCounter);
|
|
65
|
+
writer.writeUInt64(bytesToSkip);
|
|
66
|
+
return writer.toByteArray();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
decodeInternal(bytes: Bytes): BdxBlockQueryWithSkip {
|
|
70
|
+
const reader = new DataReader(bytes, Endian.Little);
|
|
71
|
+
return {
|
|
72
|
+
blockCounter: reader.readUInt32(),
|
|
73
|
+
bytesToSkip: reader.readUInt64(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export const BdxBlockQueryWithSkipMessage = new BdxBlockQueryWithSkipMessageSchema();
|
|
78
|
+
|
|
79
|
+
/** Schema for BDX Block and BlockEof message that contain Block data. */
|
|
80
|
+
export class BdxBlockMessageSchema extends Schema<BdxBlock> {
|
|
81
|
+
encodeInternal(message: BdxBlock) {
|
|
82
|
+
const { blockCounter, data } = message;
|
|
83
|
+
|
|
84
|
+
const writer = new DataWriter(Endian.Little);
|
|
85
|
+
writer.writeUInt32(blockCounter);
|
|
86
|
+
writer.writeByteArray(data);
|
|
87
|
+
return writer.toByteArray();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
decodeInternal(bytes: Bytes): BdxBlock {
|
|
91
|
+
const reader = new DataReader(bytes, Endian.Little);
|
|
92
|
+
return {
|
|
93
|
+
blockCounter: reader.readUInt32(),
|
|
94
|
+
data: reader.remainingBytes,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export const BdxBlockMessage = new BdxBlockMessageSchema();
|
|
99
|
+
export const BdxBlockEofMessage = BdxBlockMessage;
|