@matter/protocol 0.14.0 → 0.14.1-alpha.0-20250606-a9bcd03f9
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 +60 -1
- package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +33 -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 +61 -2
- package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts +33 -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 +90 -4
- package/src/cluster/client/ClusterClientTypes.ts +38 -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
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Copyright 2022-2023 Project CHIP Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
import { Subject } from "#action/server/Subject.js";
|
|
6
7
|
import { AccessControl } from "#clusters/access-control";
|
|
7
|
-
import {
|
|
8
|
+
import { MatterFlowError } from "#general";
|
|
8
9
|
import { AccessLevel } from "#model";
|
|
9
10
|
import {
|
|
10
11
|
CaseAuthenticatedTag,
|
|
@@ -15,11 +16,9 @@ import {
|
|
|
15
16
|
NodeId,
|
|
16
17
|
StatusCode,
|
|
17
18
|
StatusResponseError,
|
|
19
|
+
SubjectId,
|
|
18
20
|
} from "#types";
|
|
19
|
-
import {
|
|
20
|
-
import { SecureSession } from "../session/SecureSession.js";
|
|
21
|
-
|
|
22
|
-
const logger = Logger.get("AccessControlManager");
|
|
21
|
+
import { AccessControl as AccessControlContext } from "../action/server/AccessControl.js";
|
|
23
22
|
|
|
24
23
|
export type AclEntry = Omit<AccessControl.AccessControlEntry, "privilege"> & {
|
|
25
24
|
privilege: AccessLevel;
|
|
@@ -49,7 +48,7 @@ enum AuthModeNone {
|
|
|
49
48
|
export type IncomingSubjectDescriptor = {
|
|
50
49
|
isCommissioning: boolean;
|
|
51
50
|
authMode: AccessControl.AccessControlEntryAuthMode | AuthModeNone;
|
|
52
|
-
subjects:
|
|
51
|
+
subjects: SubjectId[];
|
|
53
52
|
fabricIndex: FabricIndex;
|
|
54
53
|
};
|
|
55
54
|
|
|
@@ -98,22 +97,24 @@ export class AccessControlManager {
|
|
|
98
97
|
/**
|
|
99
98
|
* Get the Access Control List for a given fabric.
|
|
100
99
|
*/
|
|
101
|
-
#getAccessControlEntriesForFabric(
|
|
102
|
-
return this.#aclList.filter(entry => entry.fabricIndex ===
|
|
100
|
+
#getAccessControlEntriesForFabric(fabricIndex: FabricIndex): AclList {
|
|
101
|
+
return this.#aclList.filter(entry => entry.fabricIndex === fabricIndex);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
/**
|
|
106
105
|
* Subjects must match exactly, or both are CAT with matching CAT ID and acceptable CAT version
|
|
107
106
|
*/
|
|
108
|
-
#subjectMatches(aclSubject:
|
|
109
|
-
if (aclSubject === isdSubject) {
|
|
107
|
+
#subjectMatches(aclSubject: SubjectId, isdSubject: SubjectId): boolean {
|
|
108
|
+
if (BigInt(aclSubject) === BigInt(isdSubject)) {
|
|
110
109
|
return true;
|
|
111
110
|
}
|
|
112
|
-
|
|
111
|
+
const aclNode = NodeId(aclSubject);
|
|
112
|
+
const isdNode = NodeId(isdSubject);
|
|
113
|
+
if (!NodeId.isCaseAuthenticatedTag(aclNode) || !NodeId.isCaseAuthenticatedTag(isdNode)) {
|
|
113
114
|
return false;
|
|
114
115
|
}
|
|
115
|
-
const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(
|
|
116
|
-
const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(
|
|
116
|
+
const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(aclNode);
|
|
117
|
+
const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(isdNode);
|
|
117
118
|
return (
|
|
118
119
|
CaseAuthenticatedTag.getIdentifyValue(aclSubjectCat) ===
|
|
119
120
|
CaseAuthenticatedTag.getIdentifyValue(isdSubjectCat) &&
|
|
@@ -149,40 +150,16 @@ export class AccessControlManager {
|
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
/**
|
|
152
|
-
*
|
|
153
|
+
* Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.
|
|
153
154
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
getGrantedPrivileges(
|
|
156
|
+
context: AccessControlContext.Session,
|
|
156
157
|
endpoint: AclEndpointContext,
|
|
157
158
|
clusterId: ClusterId,
|
|
158
|
-
|
|
159
|
-
): boolean {
|
|
160
|
-
const grantedPrivileges = this.getGrantedPrivileges(session, endpoint, clusterId);
|
|
161
|
-
if (grantedPrivileges.includes(privilege)) {
|
|
162
|
-
return true;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
logger.notice(
|
|
166
|
-
`Failed access control check for ${endpoint.id}/0x${toHex(clusterId)} and fabricIndex ${session.associatedFabric.fabricIndex}, acl=`,
|
|
167
|
-
this.#getAccessControlEntriesForFabric(session.associatedFabric),
|
|
168
|
-
"with ISD=",
|
|
169
|
-
this.#getIsdFromMessage(session),
|
|
170
|
-
"granted privileges=",
|
|
171
|
-
grantedPrivileges,
|
|
172
|
-
"not contains",
|
|
173
|
-
privilege,
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.
|
|
181
|
-
*/
|
|
182
|
-
getGrantedPrivileges(session: SecureSession, endpoint: AclEndpointContext, clusterId: ClusterId): AccessLevel[] {
|
|
159
|
+
): AccessLevel[] {
|
|
183
160
|
const endpointId = endpoint.id;
|
|
184
|
-
const fabric =
|
|
185
|
-
const subjectDesc = this.#getIsdFromMessage(
|
|
161
|
+
const fabric = context.fabric;
|
|
162
|
+
const subjectDesc = this.#getIsdFromMessage(context);
|
|
186
163
|
const acl = fabric ? this.#getAccessControlEntriesForFabric(fabric) : [ImplicitDefaultPaseAclEntry];
|
|
187
164
|
|
|
188
165
|
// Granted privileges set is initially empty
|
|
@@ -203,17 +180,11 @@ export class AccessControlManager {
|
|
|
203
180
|
// other than the implicit PASE entry, which we will not see explicitly in the
|
|
204
181
|
// access control list
|
|
205
182
|
if (aclEntry.fabricIndex === FabricIndex.NO_FABRIC || aclEntry.fabricIndex !== subjectDesc.fabricIndex) {
|
|
206
|
-
logger.debug(
|
|
207
|
-
"Skipping ACL entry with mismatched fabric index",
|
|
208
|
-
aclEntry.fabricIndex,
|
|
209
|
-
subjectDesc.fabricIndex,
|
|
210
|
-
);
|
|
211
183
|
continue;
|
|
212
184
|
}
|
|
213
185
|
|
|
214
186
|
// Auth mode must match
|
|
215
187
|
if (aclEntry.authMode !== subjectDesc.authMode) {
|
|
216
|
-
logger.debug("Skipping ACL entry with mismatched auth mode", aclEntry.authMode, subjectDesc.authMode);
|
|
217
188
|
continue;
|
|
218
189
|
}
|
|
219
190
|
|
|
@@ -304,50 +275,47 @@ export class AccessControlManager {
|
|
|
304
275
|
/**
|
|
305
276
|
* Determines the Incoming Subject Descriptor (ISD) from the given session.
|
|
306
277
|
*/
|
|
307
|
-
#getIsdFromMessage(session:
|
|
308
|
-
const
|
|
278
|
+
#getIsdFromMessage(session: AccessControlContext.Session) {
|
|
279
|
+
const fabricIndex = session.fabric;
|
|
309
280
|
const isd: IncomingSubjectDescriptor = {
|
|
310
281
|
isCommissioning: false,
|
|
311
282
|
authMode: AuthModeNone.None,
|
|
312
|
-
subjects: new Array<
|
|
283
|
+
subjects: new Array<SubjectId>(),
|
|
313
284
|
fabricIndex: FabricIndex.NO_FABRIC,
|
|
314
285
|
};
|
|
315
286
|
|
|
316
|
-
|
|
287
|
+
const { subject } = session;
|
|
288
|
+
if (subject === undefined) {
|
|
289
|
+
throw new MatterFlowError("ACL error: ACL checks require an authorized subject");
|
|
290
|
+
}
|
|
291
|
+
if (subject.id === NodeId.UNSPECIFIED_NODE_ID) {
|
|
292
|
+
// Pase Session
|
|
317
293
|
isd.authMode = AccessControl.AccessControlEntryAuthMode.Pase;
|
|
318
294
|
isd.isCommissioning = true; // Or how "commissioning channel" is defined?
|
|
319
|
-
isd.subjects.push(NodeId
|
|
320
|
-
if (
|
|
321
|
-
isd.fabricIndex =
|
|
295
|
+
isd.subjects.push(NodeId.UNSPECIFIED_NODE_ID); // Default Commissioning Passcode ID
|
|
296
|
+
if (fabricIndex !== undefined && fabricIndex !== FabricIndex.NO_FABRIC) {
|
|
297
|
+
isd.fabricIndex = fabricIndex;
|
|
322
298
|
}
|
|
323
|
-
} else {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
// isd.AuthMode = AuthModeEnum.Group
|
|
334
|
-
// isd.Subjects.append(group_id)
|
|
335
|
-
// isd.FabricIndex = sessions_metadata.get_fabric_index(message)
|
|
336
|
-
// assert(isd.FabricIndex != 0) # cannot be zero
|
|
337
|
-
//
|
|
338
|
-
// isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;
|
|
339
|
-
// } else {
|
|
340
|
-
|
|
299
|
+
} else if (Subject.isGroup(subject)) {
|
|
300
|
+
if (fabricIndex === undefined || fabricIndex === FabricIndex.NO_FABRIC) {
|
|
301
|
+
throw new MatterFlowError("ACL error: fabric needs to be associated for group sessions");
|
|
302
|
+
}
|
|
303
|
+
if (subject.hasValidMapping) {
|
|
304
|
+
isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;
|
|
305
|
+
isd.subjects.push(subject.id);
|
|
306
|
+
isd.fabricIndex = fabricIndex;
|
|
307
|
+
}
|
|
308
|
+
} else if (Subject.isNode(subject)) {
|
|
341
309
|
// CASE session
|
|
310
|
+
if (fabricIndex === undefined || fabricIndex === FabricIndex.NO_FABRIC) {
|
|
311
|
+
throw new MatterFlowError("ACL error: Case session must be associated with a fabric");
|
|
312
|
+
}
|
|
342
313
|
isd.authMode = AccessControl.AccessControlEntryAuthMode.Case;
|
|
343
|
-
isd.subjects.push(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// }
|
|
347
|
-
if (fabric === undefined) {
|
|
348
|
-
throw new MatterFlowError("ACL error: fabric is undefined");
|
|
314
|
+
isd.subjects.push(subject.id);
|
|
315
|
+
if (subject.catSubjects !== undefined) {
|
|
316
|
+
isd.subjects.push(...subject.catSubjects);
|
|
349
317
|
}
|
|
350
|
-
isd.fabricIndex =
|
|
318
|
+
isd.fabricIndex = fabricIndex;
|
|
351
319
|
}
|
|
352
320
|
|
|
353
321
|
return isd;
|
|
@@ -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
|
}
|