@matter/protocol 0.14.1-alpha.0-20250605-9fc134af0 → 0.14.1-alpha.0-20250607-a93593303
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/action/server/AccessControl.d.ts +5 -7
- package/dist/cjs/action/server/AccessControl.d.ts.map +1 -1
- package/dist/cjs/action/server/AccessControl.js.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.js +23 -0
- package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.js +24 -1
- package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/cjs/action/server/DataResponse.d.ts +1 -1
- package/dist/cjs/action/server/DataResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/Subject.d.ts +25 -0
- package/dist/cjs/action/server/Subject.d.ts.map +1 -0
- package/dist/cjs/action/server/Subject.js +54 -0
- package/dist/cjs/action/server/Subject.js.map +6 -0
- package/dist/cjs/action/server/index.d.ts +1 -0
- package/dist/cjs/action/server/index.d.ts.map +1 -1
- package/dist/cjs/action/server/index.js +1 -0
- package/dist/cjs/action/server/index.js.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.d.ts +2 -2
- package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
- package/dist/cjs/cluster/client/AttributeClient.d.ts +3 -3
- package/dist/cjs/cluster/client/AttributeClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/AttributeClient.js +14 -2
- package/dist/cjs/cluster/client/AttributeClient.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.d.ts +3 -2
- package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.js +66 -1
- package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +36 -8
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/cjs/cluster/client/EventClient.d.ts +3 -3
- package/dist/cjs/cluster/client/EventClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/EventClient.js +7 -0
- package/dist/cjs/cluster/client/EventClient.js.map +1 -1
- package/dist/cjs/codec/MessageCodec.d.ts.map +1 -1
- package/dist/cjs/codec/MessageCodec.js +31 -6
- package/dist/cjs/codec/MessageCodec.js.map +1 -1
- package/dist/cjs/fabric/Fabric.d.ts +20 -30
- package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
- package/dist/cjs/fabric/Fabric.js +38 -62
- package/dist/cjs/fabric/Fabric.js.map +2 -2
- package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricManager.js +10 -4
- package/dist/cjs/fabric/FabricManager.js.map +1 -1
- package/dist/cjs/groups/FabricGroupsManager.d.ts +46 -0
- package/dist/cjs/groups/FabricGroupsManager.d.ts.map +1 -0
- package/dist/cjs/groups/FabricGroupsManager.js +155 -0
- package/dist/cjs/groups/FabricGroupsManager.js.map +6 -0
- package/dist/cjs/groups/Groups.d.ts +34 -0
- package/dist/cjs/groups/Groups.d.ts.map +1 -0
- package/dist/cjs/groups/Groups.js +89 -0
- package/dist/cjs/groups/Groups.js.map +6 -0
- package/dist/cjs/groups/KeySets.d.ts +64 -0
- package/dist/cjs/groups/KeySets.d.ts.map +1 -0
- package/dist/cjs/groups/KeySets.js +179 -0
- package/dist/cjs/groups/KeySets.js.map +6 -0
- package/dist/cjs/groups/MessagingState.d.ts +24 -0
- package/dist/cjs/groups/MessagingState.d.ts.map +1 -0
- package/dist/cjs/groups/MessagingState.js +91 -0
- package/dist/cjs/groups/MessagingState.js.map +6 -0
- package/dist/cjs/groups/index.d.ts +8 -0
- package/dist/cjs/groups/index.d.ts.map +1 -0
- package/dist/cjs/groups/index.js +25 -0
- package/dist/cjs/groups/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/interaction/AccessControlManager.d.ts +4 -13
- package/dist/cjs/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/cjs/interaction/AccessControlManager.js +38 -47
- package/dist/cjs/interaction/AccessControlManager.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts +5 -4
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +53 -3
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +15 -0
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/Subscription.d.ts +3 -3
- package/dist/cjs/interaction/Subscription.d.ts.map +1 -1
- package/dist/cjs/interaction/Subscription.js.map +1 -1
- package/dist/cjs/peer/PeerAddress.d.ts +1 -0
- package/dist/cjs/peer/PeerAddress.d.ts.map +1 -1
- package/dist/cjs/peer/PeerAddress.js +5 -0
- package/dist/cjs/peer/PeerAddress.js.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +31 -2
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ChannelManager.js +7 -8
- package/dist/cjs/protocol/ChannelManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +39 -25
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +32 -4
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/protocol/MessageReceptionState.d.ts +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/cjs/session/GroupSession.d.ts +56 -0
- package/dist/cjs/session/GroupSession.d.ts.map +1 -0
- package/dist/cjs/session/GroupSession.js +188 -0
- package/dist/cjs/session/GroupSession.js.map +6 -0
- package/dist/cjs/session/InsecureSession.d.ts +2 -1
- package/dist/cjs/session/InsecureSession.d.ts.map +1 -1
- package/dist/cjs/session/InsecureSession.js +3 -2
- package/dist/cjs/session/InsecureSession.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +88 -0
- package/dist/cjs/session/NodeSession.d.ts.map +1 -0
- package/dist/cjs/session/NodeSession.js +318 -0
- package/dist/cjs/session/NodeSession.js.map +6 -0
- package/dist/cjs/session/SecureSession.d.ts +10 -75
- package/dist/cjs/session/SecureSession.d.ts.map +1 -1
- package/dist/cjs/session/SecureSession.js +9 -280
- package/dist/cjs/session/SecureSession.js.map +2 -2
- package/dist/cjs/session/Session.d.ts +6 -5
- package/dist/cjs/session/Session.d.ts.map +1 -1
- package/dist/cjs/session/Session.js +11 -1
- package/dist/cjs/session/Session.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts +27 -9
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +83 -5
- package/dist/cjs/session/SessionManager.js.map +2 -2
- package/dist/cjs/session/case/CaseClient.d.ts +1 -1
- package/dist/cjs/session/case/CaseClient.js +2 -2
- package/dist/cjs/session/case/CaseClient.js.map +1 -1
- package/dist/cjs/session/index.d.ts +2 -0
- package/dist/cjs/session/index.d.ts.map +1 -1
- package/dist/cjs/session/index.js +2 -0
- package/dist/cjs/session/index.js.map +1 -1
- package/dist/cjs/session/pase/PaseClient.d.ts +1 -1
- package/dist/esm/action/server/AccessControl.d.ts +5 -7
- package/dist/esm/action/server/AccessControl.d.ts.map +1 -1
- package/dist/esm/action/server/AccessControl.js.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.js +23 -0
- package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.js +24 -1
- package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/esm/action/server/DataResponse.d.ts +1 -1
- package/dist/esm/action/server/DataResponse.d.ts.map +1 -1
- package/dist/esm/action/server/Subject.d.ts +25 -0
- package/dist/esm/action/server/Subject.d.ts.map +1 -0
- package/dist/esm/action/server/Subject.js +34 -0
- package/dist/esm/action/server/Subject.js.map +6 -0
- package/dist/esm/action/server/index.d.ts +1 -0
- package/dist/esm/action/server/index.d.ts.map +1 -1
- package/dist/esm/action/server/index.js +1 -0
- package/dist/esm/action/server/index.js.map +1 -1
- package/dist/esm/certificate/DeviceCertification.d.ts +2 -2
- package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/esm/certificate/DeviceCertification.js.map +1 -1
- package/dist/esm/cluster/client/AttributeClient.d.ts +3 -3
- package/dist/esm/cluster/client/AttributeClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/AttributeClient.js +13 -1
- package/dist/esm/cluster/client/AttributeClient.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.d.ts +3 -2
- package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.js +67 -2
- package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts +36 -8
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/esm/cluster/client/EventClient.d.ts +3 -3
- package/dist/esm/cluster/client/EventClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/EventClient.js +7 -0
- package/dist/esm/cluster/client/EventClient.js.map +1 -1
- package/dist/esm/codec/MessageCodec.d.ts.map +1 -1
- package/dist/esm/codec/MessageCodec.js +41 -7
- package/dist/esm/codec/MessageCodec.js.map +1 -1
- package/dist/esm/fabric/Fabric.d.ts +20 -30
- package/dist/esm/fabric/Fabric.d.ts.map +1 -1
- package/dist/esm/fabric/Fabric.js +38 -62
- package/dist/esm/fabric/Fabric.js.map +2 -2
- package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
- package/dist/esm/fabric/FabricManager.js +10 -4
- package/dist/esm/fabric/FabricManager.js.map +1 -1
- package/dist/esm/groups/FabricGroupsManager.d.ts +46 -0
- package/dist/esm/groups/FabricGroupsManager.d.ts.map +1 -0
- package/dist/esm/groups/FabricGroupsManager.js +135 -0
- package/dist/esm/groups/FabricGroupsManager.js.map +6 -0
- package/dist/esm/groups/Groups.d.ts +34 -0
- package/dist/esm/groups/Groups.d.ts.map +1 -0
- package/dist/esm/groups/Groups.js +69 -0
- package/dist/esm/groups/Groups.js.map +6 -0
- package/dist/esm/groups/KeySets.d.ts +64 -0
- package/dist/esm/groups/KeySets.d.ts.map +1 -0
- package/dist/esm/groups/KeySets.js +159 -0
- package/dist/esm/groups/KeySets.js.map +6 -0
- package/dist/esm/groups/MessagingState.d.ts +24 -0
- package/dist/esm/groups/MessagingState.d.ts.map +1 -0
- package/dist/esm/groups/MessagingState.js +71 -0
- package/dist/esm/groups/MessagingState.js.map +6 -0
- package/dist/esm/groups/index.d.ts +8 -0
- package/dist/esm/groups/index.d.ts.map +1 -0
- package/dist/esm/groups/index.js +8 -0
- package/dist/esm/groups/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/interaction/AccessControlManager.d.ts +4 -13
- package/dist/esm/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/esm/interaction/AccessControlManager.js +39 -48
- package/dist/esm/interaction/AccessControlManager.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts +5 -4
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +54 -4
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +15 -0
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/Subscription.d.ts +3 -3
- package/dist/esm/interaction/Subscription.d.ts.map +1 -1
- package/dist/esm/interaction/Subscription.js.map +1 -1
- package/dist/esm/peer/PeerAddress.d.ts +1 -0
- package/dist/esm/peer/PeerAddress.d.ts.map +1 -1
- package/dist/esm/peer/PeerAddress.js +5 -0
- package/dist/esm/peer/PeerAddress.js.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +33 -3
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/esm/protocol/ChannelManager.js +7 -8
- package/dist/esm/protocol/ChannelManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +41 -27
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +39 -5
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/protocol/MessageReceptionState.d.ts +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.js +2 -2
- package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/esm/session/GroupSession.d.ts +56 -0
- package/dist/esm/session/GroupSession.d.ts.map +1 -0
- package/dist/esm/session/GroupSession.js +177 -0
- package/dist/esm/session/GroupSession.js.map +6 -0
- package/dist/esm/session/InsecureSession.d.ts +2 -1
- package/dist/esm/session/InsecureSession.d.ts.map +1 -1
- package/dist/esm/session/InsecureSession.js +3 -2
- package/dist/esm/session/InsecureSession.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +88 -0
- package/dist/esm/session/NodeSession.d.ts.map +1 -0
- package/dist/esm/session/NodeSession.js +298 -0
- package/dist/esm/session/NodeSession.js.map +6 -0
- package/dist/esm/session/SecureSession.d.ts +10 -75
- package/dist/esm/session/SecureSession.d.ts.map +1 -1
- package/dist/esm/session/SecureSession.js +10 -291
- package/dist/esm/session/SecureSession.js.map +2 -2
- package/dist/esm/session/Session.d.ts +6 -5
- package/dist/esm/session/Session.d.ts.map +1 -1
- package/dist/esm/session/Session.js +12 -2
- package/dist/esm/session/Session.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts +27 -9
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +84 -6
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/session/case/CaseClient.d.ts +1 -1
- package/dist/esm/session/case/CaseClient.js +2 -2
- package/dist/esm/session/case/CaseClient.js.map +1 -1
- package/dist/esm/session/index.d.ts +2 -0
- package/dist/esm/session/index.d.ts.map +1 -1
- package/dist/esm/session/index.js +2 -0
- package/dist/esm/session/index.js.map +1 -1
- package/dist/esm/session/pase/PaseClient.d.ts +1 -1
- package/package.json +6 -6
- package/src/action/server/AccessControl.ts +4 -7
- package/src/action/server/AttributeWriteResponse.ts +29 -7
- package/src/action/server/CommandInvokeResponse.ts +28 -7
- package/src/action/server/DataResponse.ts +1 -1
- package/src/action/server/Subject.ts +45 -0
- package/src/action/server/index.ts +1 -0
- package/src/certificate/DeviceCertification.ts +2 -2
- package/src/cluster/client/AttributeClient.ts +15 -3
- package/src/cluster/client/ClusterClient.ts +97 -4
- package/src/cluster/client/ClusterClientTypes.ts +45 -9
- package/src/cluster/client/EventClient.ts +9 -2
- package/src/codec/MessageCodec.ts +49 -8
- package/src/fabric/Fabric.ts +51 -85
- package/src/fabric/FabricManager.ts +11 -4
- package/src/groups/FabricGroupsManager.ts +164 -0
- package/src/groups/Groups.ts +81 -0
- package/src/groups/KeySets.ts +194 -0
- package/src/groups/MessagingState.ts +76 -0
- package/src/groups/index.ts +8 -0
- package/src/index.ts +1 -0
- package/src/interaction/AccessControlManager.ts +49 -81
- package/src/interaction/InteractionClient.ts +66 -6
- package/src/interaction/InteractionMessenger.ts +15 -0
- package/src/interaction/Subscription.ts +3 -3
- package/src/peer/PeerAddress.ts +4 -0
- package/src/peer/PeerSet.ts +39 -4
- package/src/protocol/ChannelManager.ts +7 -9
- package/src/protocol/ExchangeManager.ts +51 -35
- package/src/protocol/MessageExchange.ts +42 -7
- package/src/protocol/MessageReceptionState.ts +2 -2
- package/src/securechannel/SecureChannelProtocol.ts +2 -2
- package/src/session/GroupSession.ts +223 -0
- package/src/session/InsecureSession.ts +3 -2
- package/src/session/NodeSession.ts +367 -0
- package/src/session/SecureSession.ts +14 -363
- package/src/session/Session.ts +17 -6
- package/src/session/SessionManager.ts +94 -14
- package/src/session/case/CaseClient.ts +2 -2
- package/src/session/index.ts +2 -3
|
@@ -134,7 +134,8 @@ export class InteractionClientProvider {
|
|
|
134
134
|
return client;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const
|
|
137
|
+
const isGroupAddress = PeerAddress.isGroup(address);
|
|
138
|
+
const nodeStore = isGroupAddress ? undefined : this.#peers.get(address)?.dataStore;
|
|
138
139
|
await nodeStore?.construction; // Lazy initialize the data if not already done
|
|
139
140
|
|
|
140
141
|
const exchangeProvider = await this.#peers.exchangeProviderFor(address, discoveryOptions);
|
|
@@ -167,6 +168,7 @@ export class InteractionClient {
|
|
|
167
168
|
readonly #subscriptionClient: SubscriptionClient;
|
|
168
169
|
readonly #queue?: PromiseQueue;
|
|
169
170
|
readonly #address?: PeerAddress;
|
|
171
|
+
readonly isGroupAddress: boolean;
|
|
170
172
|
|
|
171
173
|
constructor(
|
|
172
174
|
exchangeProvider: ExchangeProvider,
|
|
@@ -180,6 +182,7 @@ export class InteractionClient {
|
|
|
180
182
|
this.#subscriptionClient = subscriptionClient;
|
|
181
183
|
this.#queue = queue;
|
|
182
184
|
this.#address = address;
|
|
185
|
+
this.isGroupAddress = address !== undefined ? PeerAddress.isGroup(address) : false;
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
get address() {
|
|
@@ -321,6 +324,10 @@ export class InteractionClient {
|
|
|
321
324
|
executeQueued?: boolean;
|
|
322
325
|
} = {},
|
|
323
326
|
): Promise<DecodedDataReport> {
|
|
327
|
+
if (this.isGroupAddress) {
|
|
328
|
+
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
329
|
+
}
|
|
330
|
+
|
|
324
331
|
const {
|
|
325
332
|
attributes: attributeRequests,
|
|
326
333
|
dataVersionFilters,
|
|
@@ -411,6 +418,10 @@ export class InteractionClient {
|
|
|
411
418
|
clusterId: ClusterId;
|
|
412
419
|
attribute: A;
|
|
413
420
|
}): { value: AttributeJsType<A>; version: number } | undefined {
|
|
421
|
+
if (this.isGroupAddress) {
|
|
422
|
+
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
423
|
+
}
|
|
424
|
+
|
|
414
425
|
const { endpointId, clusterId, attribute } = options;
|
|
415
426
|
const { id: attributeId } = attribute;
|
|
416
427
|
if (this.#nodeStore !== undefined) {
|
|
@@ -430,6 +441,10 @@ export class InteractionClient {
|
|
|
430
441
|
requestFromRemote?: boolean;
|
|
431
442
|
executeQueued?: boolean;
|
|
432
443
|
}): Promise<{ value: AttributeJsType<A>; version: number } | undefined> {
|
|
444
|
+
if (this.isGroupAddress) {
|
|
445
|
+
throw new ImplementationError("Reading data from group addresses is not supported.");
|
|
446
|
+
}
|
|
447
|
+
|
|
433
448
|
const { endpointId, clusterId, attribute, requestFromRemote, isFabricFiltered, executeQueued } = options;
|
|
434
449
|
const { id: attributeId } = attribute;
|
|
435
450
|
if (this.#nodeStore !== undefined) {
|
|
@@ -516,7 +531,7 @@ export class InteractionClient {
|
|
|
516
531
|
|
|
517
532
|
async setAttribute<T>(options: {
|
|
518
533
|
attributeData: {
|
|
519
|
-
endpointId
|
|
534
|
+
endpointId?: EndpointNumber;
|
|
520
535
|
clusterId: ClusterId;
|
|
521
536
|
attribute: Attribute<T, any>;
|
|
522
537
|
value: T;
|
|
@@ -557,7 +572,7 @@ export class InteractionClient {
|
|
|
557
572
|
|
|
558
573
|
async setMultipleAttributes(options: {
|
|
559
574
|
attributes: {
|
|
560
|
-
endpointId
|
|
575
|
+
endpointId?: EndpointNumber;
|
|
561
576
|
clusterId: ClusterId;
|
|
562
577
|
attribute: Attribute<any, any>;
|
|
563
578
|
value: any;
|
|
@@ -575,9 +590,22 @@ export class InteractionClient {
|
|
|
575
590
|
attributes,
|
|
576
591
|
asTimedRequest,
|
|
577
592
|
timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT_MS,
|
|
578
|
-
suppressResponse =
|
|
593
|
+
suppressResponse = this.isGroupAddress,
|
|
579
594
|
chunkLists = true, // Should be true currently to stay in sync with chip sdk
|
|
580
595
|
} = options;
|
|
596
|
+
if (this.isGroupAddress) {
|
|
597
|
+
if (!suppressResponse) {
|
|
598
|
+
throw new ImplementationError("Writing attributes on a group address can not return a response.");
|
|
599
|
+
}
|
|
600
|
+
if (
|
|
601
|
+
attributes.some(
|
|
602
|
+
({ endpointId, clusterId, attribute }) =>
|
|
603
|
+
endpointId !== undefined || clusterId === undefined || attribute.id === undefined,
|
|
604
|
+
)
|
|
605
|
+
) {
|
|
606
|
+
throw new ImplementationError("Not all attribute write paths are valid for group address writes.");
|
|
607
|
+
}
|
|
608
|
+
}
|
|
581
609
|
logger.debug(
|
|
582
610
|
`Sending write request: ${attributes
|
|
583
611
|
.map(
|
|
@@ -621,6 +649,9 @@ export class InteractionClient {
|
|
|
621
649
|
attributes.some(({ attribute: { timed } }) => timed) ||
|
|
622
650
|
asTimedRequest === true ||
|
|
623
651
|
options.timedRequestTimeoutMs !== undefined;
|
|
652
|
+
if (this.isGroupAddress && timedRequest) {
|
|
653
|
+
throw new ImplementationError("Timed requests are not supported for group address writes.");
|
|
654
|
+
}
|
|
624
655
|
|
|
625
656
|
const response = await this.withMessenger<TypeFromSchema<typeof TlvWriteResponse> | undefined>(
|
|
626
657
|
async messenger => {
|
|
@@ -671,6 +702,9 @@ export class InteractionClient {
|
|
|
671
702
|
}): Promise<{
|
|
672
703
|
maxInterval: number;
|
|
673
704
|
}> {
|
|
705
|
+
if (this.isGroupAddress) {
|
|
706
|
+
throw new ImplementationError("Subscribing to attributes on a group address is not supported.");
|
|
707
|
+
}
|
|
674
708
|
const {
|
|
675
709
|
endpointId,
|
|
676
710
|
clusterId,
|
|
@@ -792,6 +826,9 @@ export class InteractionClient {
|
|
|
792
826
|
}): Promise<{
|
|
793
827
|
maxInterval: number;
|
|
794
828
|
}> {
|
|
829
|
+
if (this.isGroupAddress) {
|
|
830
|
+
throw new ImplementationError("Subscribing to events on a group address is not supported.");
|
|
831
|
+
}
|
|
795
832
|
const {
|
|
796
833
|
endpointId,
|
|
797
834
|
clusterId,
|
|
@@ -923,6 +960,9 @@ export class InteractionClient {
|
|
|
923
960
|
eventReports?: DecodedEventReportValue<any>[];
|
|
924
961
|
maxInterval: number;
|
|
925
962
|
}> {
|
|
963
|
+
if (this.isGroupAddress) {
|
|
964
|
+
throw new ImplementationError("Subscribing to attributes or events on a group address is not supported.");
|
|
965
|
+
}
|
|
926
966
|
const {
|
|
927
967
|
attributes: attributeRequests = [],
|
|
928
968
|
events: eventRequests = [],
|
|
@@ -1097,7 +1137,7 @@ export class InteractionClient {
|
|
|
1097
1137
|
}
|
|
1098
1138
|
|
|
1099
1139
|
async invoke<C extends Command<any, any, any>>(options: {
|
|
1100
|
-
endpointId
|
|
1140
|
+
endpointId?: EndpointNumber;
|
|
1101
1141
|
clusterId: ClusterId;
|
|
1102
1142
|
request: RequestType<C>;
|
|
1103
1143
|
command: C;
|
|
@@ -1132,6 +1172,15 @@ export class InteractionClient {
|
|
|
1132
1172
|
const timedRequest =
|
|
1133
1173
|
(timed && !skipValidation) || asTimedRequest === true || options.timedRequestTimeoutMs !== undefined;
|
|
1134
1174
|
|
|
1175
|
+
if (this.isGroupAddress) {
|
|
1176
|
+
if (endpointId !== undefined) {
|
|
1177
|
+
throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
|
|
1178
|
+
}
|
|
1179
|
+
if (timedRequest) {
|
|
1180
|
+
throw new ImplementationError("Timed requests are not supported for group address invokes.");
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1135
1184
|
if (requestSchema instanceof ObjectSchema) {
|
|
1136
1185
|
if (request === undefined) {
|
|
1137
1186
|
// If developer did not provide a request object, create an empty one if it needs to be an object
|
|
@@ -1228,8 +1277,9 @@ export class InteractionClient {
|
|
|
1228
1277
|
}
|
|
1229
1278
|
|
|
1230
1279
|
// TODO Add to ClusterClient when needed/when Group communication is implemented
|
|
1280
|
+
// TODO Additionally support it without endpoint
|
|
1231
1281
|
async invokeWithSuppressedResponse<C extends Command<any, any, any>>(options: {
|
|
1232
|
-
endpointId
|
|
1282
|
+
endpointId?: EndpointNumber;
|
|
1233
1283
|
clusterId: ClusterId;
|
|
1234
1284
|
request: RequestType<C>;
|
|
1235
1285
|
command: C;
|
|
@@ -1248,6 +1298,16 @@ export class InteractionClient {
|
|
|
1248
1298
|
timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT_MS,
|
|
1249
1299
|
} = options;
|
|
1250
1300
|
const timedRequest = timed || asTimedRequest === true || options.timedRequestTimeoutMs !== undefined;
|
|
1301
|
+
|
|
1302
|
+
if (this.isGroupAddress) {
|
|
1303
|
+
if (timed) {
|
|
1304
|
+
throw new ImplementationError("Timed requests are not supported for group address invokes.");
|
|
1305
|
+
}
|
|
1306
|
+
if (endpointId !== undefined) {
|
|
1307
|
+
throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1251
1311
|
logger.debug(
|
|
1252
1312
|
`Invoking command with suppressedResponse: ${resolveCommandName({
|
|
1253
1313
|
endpointId,
|
|
@@ -262,6 +262,12 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
262
262
|
break;
|
|
263
263
|
}
|
|
264
264
|
case MessageType.SubscribeRequest: {
|
|
265
|
+
if (isGroupSession) {
|
|
266
|
+
throw new StatusResponseError(
|
|
267
|
+
`SubscribeRequest is not supported in group sessions`,
|
|
268
|
+
Status.InvalidAction,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
265
271
|
const subscribeRequest = TlvSubscribeRequest.decode(message.payload);
|
|
266
272
|
await recipient.handleSubscribeRequest(this.exchange, subscribeRequest, this, message);
|
|
267
273
|
// response is sent by handler
|
|
@@ -274,6 +280,12 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
274
280
|
break;
|
|
275
281
|
}
|
|
276
282
|
case MessageType.TimedRequest: {
|
|
283
|
+
if (isGroupSession) {
|
|
284
|
+
throw new StatusResponseError(
|
|
285
|
+
`TimedRequest is not supported in group sessions`,
|
|
286
|
+
Status.InvalidAction,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
277
289
|
const timedRequest = TlvTimedRequest.decode(message.payload);
|
|
278
290
|
recipient.handleTimedRequest(this.exchange, timedRequest, message);
|
|
279
291
|
await this.sendStatus(StatusCode.Success, {
|
|
@@ -288,6 +300,9 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
288
300
|
Status.InvalidAction,
|
|
289
301
|
);
|
|
290
302
|
}
|
|
303
|
+
if (isGroupSession) {
|
|
304
|
+
break; // We do not support multiple messages in group sessions
|
|
305
|
+
}
|
|
291
306
|
}
|
|
292
307
|
} catch (error: any) {
|
|
293
308
|
let errorStatusCode = StatusCode.Failure;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { AsyncObservable, InternalError, Logger } from "#general";
|
|
8
|
-
import {
|
|
8
|
+
import { NodeSession } from "#session/NodeSession.js";
|
|
9
9
|
import { TlvAttributePath, TlvDataVersionFilter, TlvEventFilter, TlvEventPath, TypeFromSchema } from "#types";
|
|
10
10
|
|
|
11
11
|
const logger = Logger.get("Subscription");
|
|
@@ -24,7 +24,7 @@ export interface SubscriptionCriteria {
|
|
|
24
24
|
* A single active subscription.
|
|
25
25
|
*/
|
|
26
26
|
export abstract class Subscription {
|
|
27
|
-
#session:
|
|
27
|
+
#session: NodeSession;
|
|
28
28
|
#id: SubscriptionId;
|
|
29
29
|
#isClosed?: boolean;
|
|
30
30
|
#isCanceledByPeer?: boolean;
|
|
@@ -32,7 +32,7 @@ export abstract class Subscription {
|
|
|
32
32
|
#cancelled = AsyncObservable<[subscription: Subscription]>();
|
|
33
33
|
#maxIntervalMs?: number;
|
|
34
34
|
|
|
35
|
-
constructor(session:
|
|
35
|
+
constructor(session: NodeSession, id: SubscriptionId, criteria: SubscriptionCriteria) {
|
|
36
36
|
this.#session = session;
|
|
37
37
|
this.#id = id;
|
|
38
38
|
this.#criteria = criteria;
|
package/src/peer/PeerAddress.ts
CHANGED
package/src/peer/PeerSet.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ObservableSet,
|
|
26
26
|
ServerAddressIp,
|
|
27
27
|
serverAddressToString,
|
|
28
|
+
STANDARD_MATTER_PORT,
|
|
28
29
|
Time,
|
|
29
30
|
Timer,
|
|
30
31
|
} from "#general";
|
|
@@ -34,7 +35,7 @@ import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
|
|
|
34
35
|
import { ChannelStatusResponseError } from "#securechannel/index.js";
|
|
35
36
|
import { CaseClient, SecureSession, Session } from "#session/index.js";
|
|
36
37
|
import { SessionManager } from "#session/SessionManager.js";
|
|
37
|
-
import { NodeId, ProtocolStatusCode, SECURE_CHANNEL_PROTOCOL_ID } from "#types";
|
|
38
|
+
import { GroupId, NodeId, ProtocolStatusCode, SECURE_CHANNEL_PROTOCOL_ID } from "#types";
|
|
38
39
|
import { ChannelManager } from "../protocol/ChannelManager.js";
|
|
39
40
|
import { ChannelNotConnectedError, ExchangeManager, MessageChannel } from "../protocol/ExchangeManager.js";
|
|
40
41
|
import { DedicatedChannelExchangeProvider, ReconnectableExchangeProvider } from "../protocol/ExchangeProvider.js";
|
|
@@ -240,14 +241,20 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
|
|
|
240
241
|
operationalAddress?: ServerAddressIp;
|
|
241
242
|
},
|
|
242
243
|
) {
|
|
244
|
+
address = PeerAddress(address);
|
|
245
|
+
|
|
246
|
+
const isGroupNode = PeerAddress.isGroup(address);
|
|
243
247
|
const { discoveryOptions, allowUnknownPeer, operationalAddress } = options;
|
|
244
|
-
if (!this.#peersByAddress.has(address) && !allowUnknownPeer) {
|
|
248
|
+
if (!this.#peersByAddress.has(address) && !allowUnknownPeer && !isGroupNode) {
|
|
245
249
|
throw new UnknownNodeError(`Cannot connect to unknown device ${PeerAddress(address)}`);
|
|
246
250
|
}
|
|
247
251
|
|
|
248
|
-
address = PeerAddress(address);
|
|
249
|
-
|
|
250
252
|
if (!this.#channels.hasChannel(address)) {
|
|
253
|
+
if (isGroupNode) {
|
|
254
|
+
await this.#createGroupChannel(address);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
251
258
|
const { promise: existingReconnectPromise } = this.#runningPeerReconnections.get(address) ?? {};
|
|
252
259
|
if (existingReconnectPromise !== undefined) {
|
|
253
260
|
return existingReconnectPromise;
|
|
@@ -278,6 +285,13 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
|
|
|
278
285
|
return new DedicatedChannelExchangeProvider(this.#exchanges, addressOrChannel);
|
|
279
286
|
}
|
|
280
287
|
const address: PeerAddress = addressOrChannel;
|
|
288
|
+
if (PeerAddress.isGroup(address)) {
|
|
289
|
+
if (!this.#channels.hasChannel(address)) {
|
|
290
|
+
// Ensure that we have a group channel
|
|
291
|
+
await this.#createGroupChannel(address);
|
|
292
|
+
}
|
|
293
|
+
return new DedicatedChannelExchangeProvider(this.#exchanges, this.#channels.getChannel(address));
|
|
294
|
+
}
|
|
281
295
|
let initiallyConnected = this.#channels.hasChannel(address);
|
|
282
296
|
return new ReconnectableExchangeProvider(this.#exchanges, this.#channels, address, async () => {
|
|
283
297
|
if (!initiallyConnected && !this.#channels.hasChannel(address)) {
|
|
@@ -620,6 +634,27 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
|
|
|
620
634
|
}
|
|
621
635
|
}
|
|
622
636
|
|
|
637
|
+
async #createGroupChannel(address: PeerAddress) {
|
|
638
|
+
const groupId = GroupId.fromNodeId(address.nodeId);
|
|
639
|
+
GroupId.assertGroupId(groupId);
|
|
640
|
+
const multicastAddress = this.#sessions.fabricFor(address).groups.multicastAddressFor(groupId);
|
|
641
|
+
|
|
642
|
+
const operationalInterface = this.#netInterfaces.interfaceFor(ChannelType.UDP, multicastAddress);
|
|
643
|
+
if (operationalInterface === undefined) {
|
|
644
|
+
throw new PairRetransmissionLimitReachedError(`IPv6 interface not initialized`);
|
|
645
|
+
}
|
|
646
|
+
const operationalChannel = await operationalInterface.openChannel({
|
|
647
|
+
type: ChannelType.UDP,
|
|
648
|
+
ip: multicastAddress,
|
|
649
|
+
port: STANDARD_MATTER_PORT,
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
const session = this.#sessions.groupSessionForAddress(address);
|
|
653
|
+
const channel = new MessageChannel(operationalChannel, session);
|
|
654
|
+
await this.#channels.setChannel(address, channel);
|
|
655
|
+
return channel;
|
|
656
|
+
}
|
|
657
|
+
|
|
623
658
|
/** Pair with an operational device (already commissioned) and establish a CASE session. */
|
|
624
659
|
async #pair(
|
|
625
660
|
address: PeerAddress,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { AsyncObservable, Channel, Environment, Environmental, Logger, MatterError } from "#general";
|
|
8
8
|
import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
|
|
9
|
-
import {
|
|
9
|
+
import { NodeSession } from "../session/NodeSession.js";
|
|
10
10
|
import { Session } from "../session/Session.js";
|
|
11
11
|
import { MessageChannel } from "./ExchangeManager.js";
|
|
12
12
|
|
|
@@ -91,10 +91,9 @@ export class ChannelManager {
|
|
|
91
91
|
* Returns the last established session for a Fabric and Node
|
|
92
92
|
*/
|
|
93
93
|
getChannelForSession(session: Session) {
|
|
94
|
-
if (session
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const nodeId = secureSession.peerNodeId;
|
|
94
|
+
if (NodeSession.is(session) && !session.isPase) {
|
|
95
|
+
const fabric = session.fabric;
|
|
96
|
+
const nodeId = session.peerNodeId;
|
|
98
97
|
if (fabric === undefined) {
|
|
99
98
|
return this.#paseChannels.get(session);
|
|
100
99
|
}
|
|
@@ -142,12 +141,11 @@ export class ChannelManager {
|
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
async getOrCreateChannel(byteArrayChannel: Channel<Uint8Array>, session: Session) {
|
|
145
|
-
if (!session
|
|
144
|
+
if (!NodeSession.is(session)) {
|
|
146
145
|
return this.getOrCreateAsPaseChannel(byteArrayChannel, session);
|
|
147
146
|
}
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
const nodeId = secureSession.peerNodeId;
|
|
147
|
+
const fabric = session.fabric;
|
|
148
|
+
const nodeId = session.peerNodeId;
|
|
151
149
|
if (fabric === undefined) {
|
|
152
150
|
return this.getOrCreateAsPaseChannel(byteArrayChannel, session);
|
|
153
151
|
}
|
|
@@ -15,18 +15,18 @@ import {
|
|
|
15
15
|
MatterAggregateError,
|
|
16
16
|
MatterError,
|
|
17
17
|
MatterFlowError,
|
|
18
|
-
NotImplementedError,
|
|
19
18
|
ObserverGroup,
|
|
20
19
|
TransportInterface,
|
|
21
20
|
TransportInterfaceSet,
|
|
22
21
|
UdpInterface,
|
|
22
|
+
UnexpectedDataError,
|
|
23
23
|
} from "#general";
|
|
24
24
|
import { PeerAddress } from "#peer/PeerAddress.js";
|
|
25
25
|
import { NodeId, SECURE_CHANNEL_PROTOCOL_ID, SecureMessageType } from "#types";
|
|
26
|
-
import { Message, MessageCodec, SessionType } from "../codec/MessageCodec.js";
|
|
26
|
+
import { DecodedMessage, Message, MessageCodec, SessionType } from "../codec/MessageCodec.js";
|
|
27
27
|
import { SecureChannelMessenger } from "../securechannel/SecureChannelMessenger.js";
|
|
28
28
|
import { SecureChannelProtocol } from "../securechannel/SecureChannelProtocol.js";
|
|
29
|
-
import {
|
|
29
|
+
import { NodeSession } from "../session/NodeSession.js";
|
|
30
30
|
import { Session } from "../session/Session.js";
|
|
31
31
|
import { SessionManager, UNICAST_UNSECURE_SESSION_ID } from "../session/SessionManager.js";
|
|
32
32
|
import { ChannelManager } from "./ChannelManager.js";
|
|
@@ -73,7 +73,7 @@ export class MessageChannel implements Channel<Message> {
|
|
|
73
73
|
return this.channel.maxPayloadSize;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
send(message: Message, logContext?: ExchangeLogContext)
|
|
76
|
+
async send(message: Message, logContext?: ExchangeLogContext) {
|
|
77
77
|
logger.debug("Message »", MessageCodec.messageDiagnostics(message, logContext));
|
|
78
78
|
const packet = this.session.encode(message);
|
|
79
79
|
const bytes = MessageCodec.encodePacket(packet);
|
|
@@ -83,7 +83,7 @@ export class MessageChannel implements Channel<Message> {
|
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
return this.channel.send(bytes);
|
|
86
|
+
return await this.channel.send(bytes);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
get name() {
|
|
@@ -202,11 +202,13 @@ export class ExchangeManager {
|
|
|
202
202
|
|
|
203
203
|
private async onMessage(channel: Channel<Uint8Array>, messageBytes: Uint8Array) {
|
|
204
204
|
const packet = MessageCodec.decodePacket(messageBytes);
|
|
205
|
+
const aad = messageBytes.slice(0, messageBytes.length - packet.applicationPayload.length); // Header+Extensions
|
|
205
206
|
|
|
206
|
-
|
|
207
|
-
throw new NotImplementedError("Group messages are not supported");
|
|
207
|
+
const messageId = packet.header.messageId;
|
|
208
208
|
|
|
209
|
+
let isDuplicate: boolean;
|
|
209
210
|
let session: Session | undefined;
|
|
211
|
+
let message: DecodedMessage | undefined;
|
|
210
212
|
if (packet.header.sessionType === SessionType.Unicast) {
|
|
211
213
|
if (packet.header.sessionId === UNICAST_UNSECURE_SESSION_ID) {
|
|
212
214
|
if (this.#closing) return;
|
|
@@ -219,35 +221,46 @@ export class ExchangeManager {
|
|
|
219
221
|
} else {
|
|
220
222
|
session = this.#sessionManager.getSession(packet.header.sessionId);
|
|
221
223
|
}
|
|
224
|
+
|
|
225
|
+
if (session === undefined) {
|
|
226
|
+
throw new MatterFlowError(
|
|
227
|
+
`Cannot find a session for ID ${packet.header.sessionId}${
|
|
228
|
+
packet.header.sourceNodeId !== undefined
|
|
229
|
+
? ` and source NodeId ${packet.header.sourceNodeId}`
|
|
230
|
+
: ""
|
|
231
|
+
}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
message = session.decode(packet, aad);
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
session.updateMessageCounter(messageId);
|
|
239
|
+
isDuplicate = false;
|
|
240
|
+
} catch (e) {
|
|
241
|
+
DuplicateMessageError.accept(e);
|
|
242
|
+
isDuplicate = true;
|
|
243
|
+
}
|
|
222
244
|
} else if (packet.header.sessionType === SessionType.Group) {
|
|
223
245
|
if (this.#closing) return;
|
|
224
|
-
if (packet.header.sourceNodeId
|
|
225
|
-
|
|
246
|
+
if (packet.header.sourceNodeId === undefined) {
|
|
247
|
+
throw new UnexpectedDataError("Group session message must include a source NodeId");
|
|
226
248
|
}
|
|
227
|
-
// if (packet.header.destGroupId !== undefined) { ???
|
|
228
|
-
}
|
|
229
249
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
`Cannot find a session for ID ${packet.header.sessionId}${
|
|
233
|
-
packet.header.sourceNodeId !== undefined ? ` and source NodeId ${packet.header.sourceNodeId}` : ""
|
|
234
|
-
}`,
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const messageId = packet.header.messageId;
|
|
250
|
+
let key: Uint8Array;
|
|
251
|
+
({ session, message, key } = this.#sessionManager.groupSessionFromPacket(packet, aad));
|
|
239
252
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
253
|
+
try {
|
|
254
|
+
session.updateMessageCounter(messageId, packet.header.sourceNodeId, key);
|
|
255
|
+
isDuplicate = false;
|
|
256
|
+
} catch (e) {
|
|
257
|
+
DuplicateMessageError.accept(e);
|
|
258
|
+
isDuplicate = true;
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
throw new MatterFlowError(`Unsupported session type: ${packet.header.sessionType}`);
|
|
247
262
|
}
|
|
248
263
|
|
|
249
|
-
const aad = messageBytes.slice(0, messageBytes.length - packet.applicationPayload.length); // Header+Extensions
|
|
250
|
-
const message = session.decode(packet, aad);
|
|
251
264
|
const exchangeIndex = message.payloadHeader.isInitiatorMessage
|
|
252
265
|
? message.payloadHeader.exchangeId
|
|
253
266
|
: message.payloadHeader.exchangeId | 0x10000;
|
|
@@ -343,9 +356,12 @@ export class ExchangeManager {
|
|
|
343
356
|
throw new MatterFlowError(`Unsupported protocol ${message.payloadHeader.protocolId}`);
|
|
344
357
|
}
|
|
345
358
|
if (isDuplicate) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
359
|
+
if (message.packetHeader.destGroupId === undefined) {
|
|
360
|
+
// Duplicate Non-Group messages are still interesting to log to know them
|
|
361
|
+
logger.info(
|
|
362
|
+
`Ignoring duplicate message ${messageId} (requires no ack) for protocol ${message.payloadHeader.protocolId} on channel ${channel.name}`,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
349
365
|
return;
|
|
350
366
|
} else {
|
|
351
367
|
logger.info(
|
|
@@ -365,12 +381,12 @@ export class ExchangeManager {
|
|
|
365
381
|
return;
|
|
366
382
|
}
|
|
367
383
|
const { session } = exchange;
|
|
368
|
-
if (session
|
|
384
|
+
if (NodeSession.is(session) && session.closingAfterExchangeFinished) {
|
|
369
385
|
logger.debug(
|
|
370
386
|
`Exchange index ${exchangeIndex} Session ${session.name} is already marked for closure. Close session now.`,
|
|
371
387
|
);
|
|
372
388
|
try {
|
|
373
|
-
await this.#closeSession(session
|
|
389
|
+
await this.#closeSession(session);
|
|
374
390
|
} catch (error) {
|
|
375
391
|
logger.error(`Error closing session ${session.name}. Ignoring.`, error);
|
|
376
392
|
}
|
|
@@ -378,7 +394,7 @@ export class ExchangeManager {
|
|
|
378
394
|
this.#exchanges.delete(exchangeIndex);
|
|
379
395
|
}
|
|
380
396
|
|
|
381
|
-
async #closeSession(session:
|
|
397
|
+
async #closeSession(session: NodeSession) {
|
|
382
398
|
const sessionId = session.id;
|
|
383
399
|
const sessionName = session.name;
|
|
384
400
|
|
|
@@ -18,8 +18,16 @@ import {
|
|
|
18
18
|
Timer,
|
|
19
19
|
createPromise,
|
|
20
20
|
} from "#general";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import { GroupSession } from "#session/index.js";
|
|
22
|
+
import {
|
|
23
|
+
GroupId,
|
|
24
|
+
NodeId,
|
|
25
|
+
SECURE_CHANNEL_PROTOCOL_ID,
|
|
26
|
+
SecureMessageType,
|
|
27
|
+
StatusCode,
|
|
28
|
+
StatusResponseError,
|
|
29
|
+
} from "#types";
|
|
30
|
+
import { Message, MessageCodec, PacketHeader, SessionType } from "../codec/MessageCodec.js";
|
|
23
31
|
import { SecureChannelProtocol } from "../securechannel/SecureChannelProtocol.js";
|
|
24
32
|
import {
|
|
25
33
|
SESSION_ACTIVE_INTERVAL_MS,
|
|
@@ -404,18 +412,43 @@ export class MessageExchange {
|
|
|
404
412
|
}
|
|
405
413
|
}
|
|
406
414
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
packetHeader
|
|
415
|
+
let packetHeader: PacketHeader;
|
|
416
|
+
if (this.session.type === SessionType.Unicast) {
|
|
417
|
+
packetHeader = {
|
|
410
418
|
sessionId: this.#peerSessionId,
|
|
411
|
-
sessionType: SessionType.Unicast,
|
|
419
|
+
sessionType: SessionType.Unicast,
|
|
412
420
|
messageId: await this.session.getIncrementedMessageCounter(),
|
|
413
421
|
destNodeId: this.#peerNodeId,
|
|
414
422
|
sourceNodeId: this.#nodeId,
|
|
415
423
|
hasPrivacyEnhancements: false,
|
|
416
424
|
isControlMessage: false,
|
|
417
425
|
hasMessageExtensions: false,
|
|
418
|
-
}
|
|
426
|
+
};
|
|
427
|
+
} else if (this.session.type === SessionType.Group) {
|
|
428
|
+
const session = this.session;
|
|
429
|
+
if (!GroupSession.is(session)) {
|
|
430
|
+
throw new InternalError("Session is not a GroupSession, but session type is Group.");
|
|
431
|
+
}
|
|
432
|
+
const destGroupId = GroupId.fromNodeId(this.#peerNodeId!); // TODO !!! Where get from?
|
|
433
|
+
if (destGroupId === 0) {
|
|
434
|
+
throw new InternalError(`Invalid GroupId extracted from NodeId ${this.#peerNodeId}`);
|
|
435
|
+
}
|
|
436
|
+
packetHeader = {
|
|
437
|
+
sessionId: this.#peerSessionId,
|
|
438
|
+
sessionType: SessionType.Group,
|
|
439
|
+
messageId: await session.getIncrementedMessageCounter(),
|
|
440
|
+
destGroupId,
|
|
441
|
+
sourceNodeId: this.#nodeId, // We are the source node, so use our NodeId
|
|
442
|
+
hasPrivacyEnhancements: false,
|
|
443
|
+
isControlMessage: false,
|
|
444
|
+
hasMessageExtensions: false,
|
|
445
|
+
};
|
|
446
|
+
} else {
|
|
447
|
+
throw new InternalError(`Unknown session type: ${this.session.type}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const message: Message = {
|
|
451
|
+
packetHeader,
|
|
419
452
|
payloadHeader: {
|
|
420
453
|
exchangeId: this.#exchangeId,
|
|
421
454
|
protocolId:
|
|
@@ -466,6 +499,8 @@ export class MessageExchange {
|
|
|
466
499
|
let timeout: number;
|
|
467
500
|
if (options?.timeoutMs !== undefined) {
|
|
468
501
|
timeout = options.timeoutMs;
|
|
502
|
+
} else if (this.#messagesQueue.size > 0) {
|
|
503
|
+
timeout = 0; // If we have messages in the queue, we can return them immediately
|
|
469
504
|
} else {
|
|
470
505
|
switch (this.channel.type) {
|
|
471
506
|
case "tcp":
|
|
@@ -21,7 +21,7 @@ export abstract class MessageReceptionState {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Implements a message reception state for encrypted messages without rollover.
|
|
24
|
-
* A counter in the range [(max_message_counter + 1) to (
|
|
24
|
+
* A counter in the range [(max_message_counter + 1) to (2^31 - 1)] SHALL be considered new, and cause the
|
|
25
25
|
* max_message_counter value to be updated.
|
|
26
26
|
* Message counters within the range of the bitmap SHALL be considered duplicate if the corresponding bit
|
|
27
27
|
* offset is set to true. All other message counters SHALL be considered duplicate.
|
|
@@ -121,7 +121,7 @@ export class MessageReceptionStateEncryptedWithoutRollover extends MessageRecept
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
const diff = this.calculateDiff(messageCounter);
|
|
124
|
-
// A counter in the range [(max_message_counter + 1) to (
|
|
124
|
+
// A counter in the range [(max_message_counter + 1) to (2^31 - 1)] SHALL be considered new, and cause the
|
|
125
125
|
// max_message_counter value to be updated.
|
|
126
126
|
// Message counters within the range of the bitmap SHALL be considered duplicate if the corresponding bit
|
|
127
127
|
// offset is set to true. All other message counters SHALL be considered duplicate.
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { Message } from "../codec/MessageCodec.js";
|
|
20
20
|
import { MessageExchange } from "../protocol/MessageExchange.js";
|
|
21
21
|
import { ProtocolHandler } from "../protocol/ProtocolHandler.js";
|
|
22
|
-
import {
|
|
22
|
+
import { SecureSession } from "../session/SecureSession.js";
|
|
23
23
|
import { CaseServer } from "../session/case/CaseServer.js";
|
|
24
24
|
import { MaximumPasePairingErrorsReachedError, PaseServer } from "../session/pase/PaseServer.js";
|
|
25
25
|
import { ChannelStatusResponseError, SecureChannelMessenger } from "./SecureChannelMessenger.js";
|
|
@@ -79,7 +79,7 @@ export class StatusReportOnlySecureChannelProtocol implements ProtocolHandler {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const { session } = exchange;
|
|
82
|
-
|
|
82
|
+
SecureSession.assert(session);
|
|
83
83
|
logger.debug(`Peer requested to close session ${session.name}. Remove session now.`);
|
|
84
84
|
// TODO: and do more - see Core Specs 5.5
|
|
85
85
|
await session.destroy(false, false);
|