@matter/protocol 0.16.0-alpha.0-20251018-dd1ea6a8a → 0.16.0-alpha.0-20251021-cca02fb0e
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/client/ClientInteraction.d.ts.map +1 -1
- package/dist/cjs/action/client/ClientInteraction.js +2 -2
- package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.js +5 -0
- package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
- package/dist/cjs/common/FailsafeContext.d.ts +2 -1
- package/dist/cjs/common/FailsafeContext.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +10 -5
- package/dist/cjs/common/FailsafeContext.js.map +1 -1
- package/dist/cjs/common/FailsafeTimer.d.ts +2 -0
- package/dist/cjs/common/FailsafeTimer.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeTimer.js +9 -0
- package/dist/cjs/common/FailsafeTimer.js.map +1 -1
- package/dist/cjs/fabric/FabricAuthority.d.ts +12 -18
- package/dist/cjs/fabric/FabricAuthority.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricAuthority.js +16 -29
- package/dist/cjs/fabric/FabricAuthority.js.map +2 -2
- package/dist/cjs/fabric/TestFabric.d.ts +1 -1
- package/dist/cjs/fabric/TestFabric.d.ts.map +1 -1
- package/dist/cjs/fabric/TestFabric.js +15 -15
- package/dist/cjs/fabric/TestFabric.js.map +1 -1
- package/dist/cjs/interaction/FabricAccessControl.d.ts.map +1 -1
- package/dist/cjs/interaction/FabricAccessControl.js +4 -1
- package/dist/cjs/interaction/FabricAccessControl.js.map +1 -1
- package/dist/cjs/mdns/MdnsClient.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsClient.js +34 -19
- package/dist/cjs/mdns/MdnsClient.js.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.js +6 -7
- package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
- package/dist/cjs/protocol/DeviceAdvertiser.js +2 -2
- package/dist/cjs/protocol/DeviceAdvertiser.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +2 -2
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.d.ts.map +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js +3 -3
- package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +1 -0
- package/dist/cjs/session/NodeSession.d.ts.map +1 -1
- package/dist/cjs/session/NodeSession.js +4 -0
- package/dist/cjs/session/NodeSession.js.map +1 -1
- package/dist/cjs/session/Session.d.ts +1 -0
- package/dist/cjs/session/Session.d.ts.map +1 -1
- package/dist/cjs/session/Session.js +4 -0
- package/dist/cjs/session/Session.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts +13 -12
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.js.map +1 -1
- package/dist/cjs/session/index.d.ts +1 -0
- package/dist/cjs/session/index.d.ts.map +1 -1
- package/dist/cjs/session/index.js +1 -0
- package/dist/cjs/session/index.js.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.js.map +1 -1
- package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/esm/action/client/ClientInteraction.js +1 -1
- package/dist/esm/action/client/ClientInteraction.js.map +1 -1
- package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/esm/certificate/DeviceCertification.js +5 -0
- package/dist/esm/certificate/DeviceCertification.js.map +1 -1
- package/dist/esm/common/FailsafeContext.d.ts +2 -1
- package/dist/esm/common/FailsafeContext.d.ts.map +1 -1
- package/dist/esm/common/FailsafeContext.js +10 -5
- package/dist/esm/common/FailsafeContext.js.map +1 -1
- package/dist/esm/common/FailsafeTimer.d.ts +2 -0
- package/dist/esm/common/FailsafeTimer.d.ts.map +1 -1
- package/dist/esm/common/FailsafeTimer.js +9 -0
- package/dist/esm/common/FailsafeTimer.js.map +1 -1
- package/dist/esm/fabric/FabricAuthority.d.ts +12 -18
- package/dist/esm/fabric/FabricAuthority.d.ts.map +1 -1
- package/dist/esm/fabric/FabricAuthority.js +16 -29
- package/dist/esm/fabric/FabricAuthority.js.map +2 -2
- package/dist/esm/fabric/TestFabric.d.ts +1 -1
- package/dist/esm/fabric/TestFabric.d.ts.map +1 -1
- package/dist/esm/fabric/TestFabric.js +15 -15
- package/dist/esm/fabric/TestFabric.js.map +1 -1
- package/dist/esm/interaction/FabricAccessControl.d.ts.map +1 -1
- package/dist/esm/interaction/FabricAccessControl.js +5 -2
- package/dist/esm/interaction/FabricAccessControl.js.map +1 -1
- package/dist/esm/mdns/MdnsClient.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsClient.js +34 -19
- package/dist/esm/mdns/MdnsClient.js.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.js +6 -7
- package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
- package/dist/esm/protocol/DeviceAdvertiser.js +2 -2
- package/dist/esm/protocol/DeviceAdvertiser.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +2 -2
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.d.ts.map +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.js +3 -3
- package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +1 -0
- package/dist/esm/session/NodeSession.d.ts.map +1 -1
- package/dist/esm/session/NodeSession.js +4 -0
- package/dist/esm/session/NodeSession.js.map +1 -1
- package/dist/esm/session/Session.d.ts +1 -0
- package/dist/esm/session/Session.d.ts.map +1 -1
- package/dist/esm/session/Session.js +4 -0
- package/dist/esm/session/Session.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts +13 -12
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/case/CaseMessenger.js.map +1 -1
- package/dist/esm/session/index.d.ts +1 -0
- package/dist/esm/session/index.d.ts.map +1 -1
- package/dist/esm/session/index.js +1 -0
- package/dist/esm/session/index.js.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.js.map +1 -1
- package/package.json +6 -6
- package/src/action/client/ClientInteraction.ts +1 -1
- package/src/certificate/DeviceCertification.ts +10 -0
- package/src/common/FailsafeContext.ts +15 -6
- package/src/common/FailsafeTimer.ts +11 -0
- package/src/fabric/FabricAuthority.ts +24 -38
- package/src/fabric/TestFabric.ts +15 -16
- package/src/interaction/FabricAccessControl.ts +5 -2
- package/src/mdns/MdnsClient.ts +36 -19
- package/src/peer/ControllerDiscovery.ts +6 -7
- package/src/protocol/DeviceAdvertiser.ts +2 -2
- package/src/protocol/MessageExchange.ts +2 -2
- package/src/securechannel/SecureChannelProtocol.ts +3 -4
- package/src/session/NodeSession.ts +5 -0
- package/src/session/Session.ts +5 -0
- package/src/session/SessionManager.ts +14 -2
- package/src/session/case/CaseMessenger.ts +2 -0
- package/src/session/index.ts +1 -0
- package/src/session/pase/PaseMessenger.ts +2 -0
|
@@ -24,21 +24,15 @@ const logger = Logger.get("FabricAuthority");
|
|
|
24
24
|
/**
|
|
25
25
|
* Configuration for fabrics controlled by a FabricAuthority.
|
|
26
26
|
*/
|
|
27
|
-
interface FabricAuthorityConfiguration {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* Concrete {@link FabricAuthorityConfiguration} for environmental configuration.
|
|
37
|
-
*/
|
|
38
|
-
export class FabricAuthorityConfigurationProvider implements FabricAuthorityConfiguration {
|
|
39
|
-
get adminFabricLabel(): string {
|
|
40
|
-
throw new ImplementationError("Admin Fabric Label must be set for FabricAuthorityConfigurationProvider.");
|
|
41
|
-
}
|
|
27
|
+
export interface FabricAuthorityConfiguration {
|
|
28
|
+
readonly adminFabricLabel: string;
|
|
29
|
+
readonly adminVendorId?: VendorId;
|
|
30
|
+
readonly adminNodeId?: NodeId;
|
|
31
|
+
|
|
32
|
+
/** @deprecated Fabric index is assigned automatically, please do not specify this. */
|
|
33
|
+
readonly adminFabricIndex?: FabricIndex;
|
|
34
|
+
readonly adminFabricId?: FabricId;
|
|
35
|
+
readonly caseAuthenticatedTags?: CaseAuthenticatedTag[];
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
/**
|
|
@@ -47,7 +41,6 @@ export class FabricAuthorityConfigurationProvider implements FabricAuthorityConf
|
|
|
47
41
|
export interface FabricAuthorityContext {
|
|
48
42
|
ca: CertificateAuthority;
|
|
49
43
|
fabrics: FabricManager;
|
|
50
|
-
config: FabricAuthorityConfiguration;
|
|
51
44
|
}
|
|
52
45
|
|
|
53
46
|
export const DEFAULT_ADMIN_VENDOR_ID = VendorId(0xfff1);
|
|
@@ -59,13 +52,11 @@ export class FabricAuthority {
|
|
|
59
52
|
#construction: Construction<FabricAuthority>;
|
|
60
53
|
#ca: CertificateAuthority;
|
|
61
54
|
#fabrics: FabricManager;
|
|
62
|
-
#config: FabricAuthorityConfiguration;
|
|
63
55
|
#fabricAdded = new Observable<[Fabric]>();
|
|
64
56
|
|
|
65
|
-
constructor({ ca, fabrics
|
|
57
|
+
constructor({ ca, fabrics }: FabricAuthorityContext) {
|
|
66
58
|
this.#ca = ca;
|
|
67
59
|
this.#fabrics = fabrics;
|
|
68
|
-
this.#config = config;
|
|
69
60
|
|
|
70
61
|
this.#construction = Construction(this, async () => {
|
|
71
62
|
await this.#ca.construction;
|
|
@@ -87,18 +78,19 @@ export class FabricAuthority {
|
|
|
87
78
|
/**
|
|
88
79
|
* Obtain the default fabric for this authority.
|
|
89
80
|
*/
|
|
90
|
-
async defaultFabric() {
|
|
81
|
+
async defaultFabric(config: FabricAuthorityConfiguration) {
|
|
91
82
|
// First search for a fabric associated with the CA's root certificate
|
|
92
|
-
const
|
|
83
|
+
const caRootCert = this.#ca.rootCert;
|
|
84
|
+
const fabric = this.fabrics.find(fabric => Bytes.areEqual(fabric.rootCert, caRootCert));
|
|
93
85
|
if (fabric !== undefined) {
|
|
94
|
-
if (fabric.label !==
|
|
95
|
-
await fabric.setLabel(
|
|
86
|
+
if (fabric.label !== config.adminFabricLabel) {
|
|
87
|
+
await fabric.setLabel(config.adminFabricLabel);
|
|
96
88
|
}
|
|
97
89
|
return fabric;
|
|
98
90
|
}
|
|
99
91
|
|
|
100
92
|
// Create a new fabric
|
|
101
|
-
return await this.createFabric();
|
|
93
|
+
return await this.createFabric(config);
|
|
102
94
|
}
|
|
103
95
|
|
|
104
96
|
/**
|
|
@@ -125,11 +117,11 @@ export class FabricAuthority {
|
|
|
125
117
|
/**
|
|
126
118
|
* Create a new fabric under our control.
|
|
127
119
|
*/
|
|
128
|
-
async createFabric() {
|
|
129
|
-
const rootNodeId = NodeId.randomOperationalNodeId(this.#fabrics.crypto);
|
|
120
|
+
async createFabric(config: FabricAuthorityConfiguration) {
|
|
121
|
+
const rootNodeId = config.adminNodeId ?? NodeId.randomOperationalNodeId(this.#fabrics.crypto);
|
|
130
122
|
const ipkValue = this.#fabrics.crypto.randomBytes(CRYPTO_SYMMETRIC_KEY_LENGTH);
|
|
131
123
|
|
|
132
|
-
let vendorId =
|
|
124
|
+
let vendorId = config.adminVendorId;
|
|
133
125
|
if (vendorId === undefined) {
|
|
134
126
|
vendorId = DEFAULT_ADMIN_VENDOR_ID;
|
|
135
127
|
logger.warn(`Using test vendor ID 0x${vendorId.toString(16)} for controller fabric`);
|
|
@@ -140,20 +132,15 @@ export class FabricAuthority {
|
|
|
140
132
|
fabricBuilder
|
|
141
133
|
.setRootNodeId(rootNodeId)
|
|
142
134
|
.setIdentityProtectionKey(ipkValue)
|
|
143
|
-
.setRootVendorId(
|
|
144
|
-
.setLabel(
|
|
135
|
+
.setRootVendorId(vendorId)
|
|
136
|
+
.setLabel(config.adminFabricLabel);
|
|
145
137
|
|
|
146
|
-
const fabricId =
|
|
138
|
+
const fabricId = config.adminFabricId ?? FabricId(this.#fabrics.crypto.randomBigInt(8));
|
|
147
139
|
await fabricBuilder.setOperationalCert(
|
|
148
|
-
await this.#ca.generateNoc(
|
|
149
|
-
fabricBuilder.publicKey,
|
|
150
|
-
fabricId,
|
|
151
|
-
rootNodeId,
|
|
152
|
-
this.#config.caseAuthenticatedTags,
|
|
153
|
-
),
|
|
140
|
+
await this.#ca.generateNoc(fabricBuilder.publicKey, fabricId, rootNodeId, config.caseAuthenticatedTags),
|
|
154
141
|
);
|
|
155
142
|
|
|
156
|
-
let index =
|
|
143
|
+
let index = config.adminFabricIndex;
|
|
157
144
|
if (index === undefined) {
|
|
158
145
|
index = this.#fabrics.allocateFabricIndex();
|
|
159
146
|
} else if (this.#fabrics.findByIndex(index) !== undefined) {
|
|
@@ -173,7 +160,6 @@ export class FabricAuthority {
|
|
|
173
160
|
const instance = new FabricAuthority({
|
|
174
161
|
ca: env.get(CertificateAuthority),
|
|
175
162
|
fabrics: env.get(FabricManager),
|
|
176
|
-
config: env.get(FabricAuthorityConfigurationProvider),
|
|
177
163
|
});
|
|
178
164
|
env.set(FabricAuthority, instance);
|
|
179
165
|
return instance;
|
package/src/fabric/TestFabric.ts
CHANGED
|
@@ -19,8 +19,14 @@ import { FabricManager } from "./FabricManager.js";
|
|
|
19
19
|
*/
|
|
20
20
|
export async function TestFabric(options: TestFabric.Options = {}) {
|
|
21
21
|
const authority = await TestFabric.Authority(options);
|
|
22
|
+
const { index } = options;
|
|
22
23
|
|
|
23
|
-
return authority.createFabric(
|
|
24
|
+
return authority.createFabric({
|
|
25
|
+
adminFabricLabel: `mock-fabric-${index}`,
|
|
26
|
+
adminVendorId: VendorId(0xfff1),
|
|
27
|
+
adminFabricIndex: index !== undefined ? FabricIndex(index) : undefined,
|
|
28
|
+
adminFabricId: FabricId(1),
|
|
29
|
+
});
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
export namespace TestFabric {
|
|
@@ -31,35 +37,28 @@ export namespace TestFabric {
|
|
|
31
37
|
*
|
|
32
38
|
* Crypto matter is stable with respect to {@link index}.
|
|
33
39
|
*/
|
|
34
|
-
export async function Authority(
|
|
35
|
-
|
|
40
|
+
export async function Authority(options: Options = {}) {
|
|
41
|
+
let { fabrics } = options;
|
|
42
|
+
if (options.index === undefined) {
|
|
36
43
|
if (fabrics) {
|
|
37
|
-
index = fabrics.allocateFabricIndex();
|
|
44
|
+
options.index = fabrics.allocateFabricIndex();
|
|
38
45
|
} else {
|
|
39
|
-
index = 1;
|
|
46
|
+
options.index = 1;
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
if (index < 1 || index > 254) {
|
|
50
|
+
if (options.index < 1 || options.index > 254) {
|
|
44
51
|
throw new ImplementationError("Test fabric indexes must be in the range 1-254");
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
if (!fabrics) {
|
|
48
|
-
fabrics = new FabricManager(MockCrypto(index));
|
|
55
|
+
fabrics = new FabricManager(MockCrypto(options.index));
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
return new FabricAuthority({
|
|
52
59
|
ca: await CertificateAuthority.create(fabrics.crypto),
|
|
53
|
-
config: {
|
|
54
|
-
adminFabricLabel: `mock-fabric-${index}`,
|
|
55
|
-
adminVendorId: VendorId(0xfff1),
|
|
56
|
-
fabricIndex: FabricIndex(index),
|
|
57
|
-
fabricId: FabricId(1),
|
|
58
|
-
},
|
|
59
60
|
fabrics,
|
|
60
61
|
});
|
|
61
|
-
|
|
62
|
-
return authority;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
export interface Options {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { Subject } from "#action/server/Subject.js";
|
|
7
7
|
import { AccessControl } from "#clusters/access-control";
|
|
8
8
|
import type { Fabric } from "#fabric/Fabric.js";
|
|
9
|
-
import { InternalError, Logger, MatterFlowError } from "#general";
|
|
9
|
+
import { Diagnostic, InternalError, Logger, MatterFlowError } from "#general";
|
|
10
10
|
import { AccessLevel } from "#model";
|
|
11
11
|
import {
|
|
12
12
|
CaseAuthenticatedTag,
|
|
@@ -94,7 +94,10 @@ export class FabricAccessControl {
|
|
|
94
94
|
throw new InternalError("ACL entries must match the fabric index of the manager");
|
|
95
95
|
}
|
|
96
96
|
this.#aclList = [...aclList] as unknown as AclList; // It is the same structure we just use an internal type for privilege
|
|
97
|
-
logger.info(
|
|
97
|
+
logger.info(
|
|
98
|
+
"ACL List updated",
|
|
99
|
+
this.#aclList.map(e => Diagnostic.dict(e)),
|
|
100
|
+
);
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
set extensionEntryAccessCheck(
|
package/src/mdns/MdnsClient.ts
CHANGED
|
@@ -184,9 +184,10 @@ export class MdnsClient implements Scanner {
|
|
|
184
184
|
this.#updateScanTargets();
|
|
185
185
|
logger.info(
|
|
186
186
|
"MDNS Scan targets updated :",
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
Diagnostic.dict({
|
|
188
|
+
commissionable: this.#scanForCommissionableDevices,
|
|
189
|
+
operational: this.#operationalScanTargets,
|
|
190
|
+
}),
|
|
190
191
|
);
|
|
191
192
|
}
|
|
192
193
|
|
|
@@ -220,7 +221,7 @@ export class MdnsClient implements Scanner {
|
|
|
220
221
|
this.#updateListeningStatus();
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
/** Update the status
|
|
224
|
+
/** Update the status if we care about MDNS messages or not */
|
|
224
225
|
#updateListeningStatus() {
|
|
225
226
|
const formerListenStatus = this.#listening;
|
|
226
227
|
// Are we interested in MDNS traffic or not?
|
|
@@ -786,25 +787,41 @@ export class MdnsClient implements Scanner {
|
|
|
786
787
|
},
|
|
787
788
|
);
|
|
788
789
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
790
|
+
// We scan continuously, so make sure we are registered for commissionable devices
|
|
791
|
+
const criteria: MdnsScannerTargetCriteria = { commissionable: true, operationalTargets: [] };
|
|
792
|
+
this.targetCriteriaProviders.add(criteria);
|
|
793
|
+
|
|
794
|
+
try {
|
|
795
|
+
let lastDiscoveredDevices: CommissionableDevice[] | undefined = undefined;
|
|
796
|
+
while (!canceled) {
|
|
797
|
+
this.#getCommissionableDeviceRecords(identifier).forEach(device => {
|
|
798
|
+
const { deviceIdentifier } = device;
|
|
799
|
+
if (!discoveredDevices.has(deviceIdentifier)) {
|
|
800
|
+
discoveredDevices.add(deviceIdentifier);
|
|
801
|
+
callback(device);
|
|
802
|
+
}
|
|
803
|
+
});
|
|
797
804
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
805
|
+
let remainingTime;
|
|
806
|
+
if (discoveryEndTime !== undefined) {
|
|
807
|
+
remainingTime = Seconds.ceil(Timespan(Time.nowMs, discoveryEndTime).duration);
|
|
808
|
+
if (remainingTime <= 0) {
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
803
811
|
}
|
|
812
|
+
lastDiscoveredDevices = await this.#registerWaiterPromise(
|
|
813
|
+
queryId,
|
|
814
|
+
true,
|
|
815
|
+
remainingTime,
|
|
816
|
+
() => this.#getCommissionableDeviceRecords(identifier),
|
|
817
|
+
false,
|
|
818
|
+
queryResolver,
|
|
819
|
+
);
|
|
804
820
|
}
|
|
805
|
-
|
|
821
|
+
return lastDiscoveredDevices ?? this.#getCommissionableDeviceRecords(identifier);
|
|
822
|
+
} finally {
|
|
823
|
+
this.targetCriteriaProviders.delete(criteria);
|
|
806
824
|
}
|
|
807
|
-
return this.#getCommissionableDeviceRecords(identifier);
|
|
808
825
|
}
|
|
809
826
|
|
|
810
827
|
getDiscoveredCommissionableDevices(identifier: CommissionableDeviceIdentifiers) {
|
|
@@ -88,9 +88,9 @@ export class ControllerDiscovery {
|
|
|
88
88
|
): Promise<CommissionableDevice[]> {
|
|
89
89
|
const discoveredDevices = new Map<string, CommissionableDevice>();
|
|
90
90
|
|
|
91
|
-
await Promise.all(
|
|
92
|
-
scanners.map(async scanner =>
|
|
93
|
-
|
|
91
|
+
const results = await Promise.all(
|
|
92
|
+
scanners.map(async scanner =>
|
|
93
|
+
scanner.findCommissionableDevicesContinuously(
|
|
94
94
|
identifier,
|
|
95
95
|
device => {
|
|
96
96
|
const { deviceIdentifier } = device;
|
|
@@ -100,14 +100,13 @@ export class ControllerDiscovery {
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
timeout,
|
|
103
|
-
)
|
|
104
|
-
|
|
103
|
+
),
|
|
104
|
+
),
|
|
105
105
|
);
|
|
106
106
|
|
|
107
107
|
// The final answer only consists the devices still left, so expired ones will be excluded
|
|
108
108
|
const finalDiscoveredDevices = new Map<string, CommissionableDevice>();
|
|
109
|
-
|
|
110
|
-
const devices = scanner.getDiscoveredCommissionableDevices(identifier);
|
|
109
|
+
results.forEach(devices => {
|
|
111
110
|
devices.forEach(device => {
|
|
112
111
|
const { deviceIdentifier } = device;
|
|
113
112
|
if (!discoveredDevices.has(deviceIdentifier)) {
|
|
@@ -166,7 +166,7 @@ export class DeviceAdvertiser {
|
|
|
166
166
|
* Advertise the device as operational.
|
|
167
167
|
*/
|
|
168
168
|
enterOperationalMode() {
|
|
169
|
-
if (this.#isOperational) {
|
|
169
|
+
if (this.#isOperational || this.#isClosing) {
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -179,7 +179,7 @@ export class DeviceAdvertiser {
|
|
|
179
179
|
* Begin automatic broadcast for fabrics if in operational mode.
|
|
180
180
|
*/
|
|
181
181
|
#startOperationalAdvertisement() {
|
|
182
|
-
if (!this.#isOperational) {
|
|
182
|
+
if (!this.#isOperational || this.#isClosing) {
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
|
|
@@ -494,10 +494,10 @@ export class MessageExchange {
|
|
|
494
494
|
|
|
495
495
|
#retransmitMessage(message: Message, expectedProcessingTime?: Duration) {
|
|
496
496
|
this.#retransmissionCounter++;
|
|
497
|
-
if (this.#retransmissionCounter >= MRP.MAX_TRANSMISSIONS) {
|
|
497
|
+
if (this.#isClosing || this.#retransmissionCounter >= MRP.MAX_TRANSMISSIONS) {
|
|
498
498
|
// Ok all 4 resubmissions are done, but we need to wait a bit longer because of processing time and
|
|
499
499
|
// the resubmissions from the other side
|
|
500
|
-
if (expectedProcessingTime) {
|
|
500
|
+
if (expectedProcessingTime && !this.#isClosing) {
|
|
501
501
|
// We already have waited after the last message was sent, so deduct this time from the final wait time
|
|
502
502
|
const finalWaitTime = Millis(
|
|
503
503
|
this.channel.calculateMaximumPeerResponseTime(
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { FabricManager } from "#fabric/FabricManager.js";
|
|
8
8
|
import { AsyncObservable, Environment, Environmental, Logger, MatterFlowError } from "#general";
|
|
9
9
|
import { ExchangeManager } from "#protocol/ExchangeManager.js";
|
|
10
|
+
import { NodeSession } from "#session/NodeSession.js";
|
|
10
11
|
import { SessionManager } from "#session/SessionManager.js";
|
|
11
12
|
import {
|
|
12
13
|
GeneralStatusCode,
|
|
@@ -19,7 +20,6 @@ import {
|
|
|
19
20
|
import { Message } from "../codec/MessageCodec.js";
|
|
20
21
|
import { MessageExchange } from "../protocol/MessageExchange.js";
|
|
21
22
|
import { ProtocolHandler } from "../protocol/ProtocolHandler.js";
|
|
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";
|
|
@@ -83,10 +83,9 @@ export class StatusReportOnlySecureChannelProtocol implements ProtocolHandler {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const { session } = exchange;
|
|
86
|
-
|
|
86
|
+
NodeSession.assert(session);
|
|
87
87
|
logger.debug(`Peer requested to close session ${session.name}. Remove session now.`);
|
|
88
|
-
|
|
89
|
-
await session.destroy(false, false);
|
|
88
|
+
await session.closeByPeer();
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
async close() {
|
|
@@ -331,6 +331,11 @@ export class NodeSession extends SecureSession {
|
|
|
331
331
|
await this.destroy(sendClose, closeAfterExchangeFinished);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
async closeByPeer() {
|
|
335
|
+
await this.destroy(false, false);
|
|
336
|
+
await this.closedByPeer.emit();
|
|
337
|
+
}
|
|
338
|
+
|
|
334
339
|
/** Destroys a session. Outstanding subscription data will be discarded. */
|
|
335
340
|
async destroy(sendClose = false, closeAfterExchangeFinished = true) {
|
|
336
341
|
await this.clearSubscriptions(false);
|
package/src/session/Session.ts
CHANGED
|
@@ -97,6 +97,7 @@ export abstract class Session {
|
|
|
97
97
|
*/
|
|
98
98
|
closer?: Promise<void>;
|
|
99
99
|
#destroyed = AsyncObservable<[]>();
|
|
100
|
+
#closedByPeer = AsyncObservable<[]>();
|
|
100
101
|
|
|
101
102
|
constructor(args: {
|
|
102
103
|
manager?: SessionManager;
|
|
@@ -143,6 +144,10 @@ export abstract class Session {
|
|
|
143
144
|
return this.#destroyed;
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
get closedByPeer() {
|
|
148
|
+
return this.#closedByPeer;
|
|
149
|
+
}
|
|
150
|
+
|
|
146
151
|
notifyActivity(messageReceived: boolean) {
|
|
147
152
|
this.timestamp = Time.nowMs;
|
|
148
153
|
if (messageReceived) {
|
|
@@ -31,7 +31,7 @@ import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
|
|
|
31
31
|
import { GroupSession } from "#session/GroupSession.js";
|
|
32
32
|
import { CaseAuthenticatedTag, DEFAULT_MAX_PATHS_PER_INVOKE, FabricId, FabricIndex, GroupId, NodeId } from "#types";
|
|
33
33
|
import { UnexpectedDataError } from "@matter/general";
|
|
34
|
-
import { Fabric } from "../fabric/Fabric.js";
|
|
34
|
+
import { ExposedFabricInformation, Fabric } from "../fabric/Fabric.js";
|
|
35
35
|
import { MessageCounter } from "../protocol/MessageCounter.js";
|
|
36
36
|
import { InsecureSession } from "./InsecureSession.js";
|
|
37
37
|
import { NodeSession } from "./NodeSession.js";
|
|
@@ -90,6 +90,18 @@ type ResumptionStorageRecord = {
|
|
|
90
90
|
caseAuthenticatedTags?: CaseAuthenticatedTag[];
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
+
export interface ActiveSessionInformation {
|
|
94
|
+
name: string;
|
|
95
|
+
nodeId: NodeId;
|
|
96
|
+
peerNodeId: NodeId;
|
|
97
|
+
fabric?: ExposedFabricInformation;
|
|
98
|
+
isPeerActive: boolean;
|
|
99
|
+
secure: boolean;
|
|
100
|
+
lastInteractionTimestamp?: number;
|
|
101
|
+
lastActiveTimestamp?: number;
|
|
102
|
+
numberOfActiveSubscriptions: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
93
105
|
/**
|
|
94
106
|
* Interfaces {@link SessionManager} with other components.
|
|
95
107
|
*/
|
|
@@ -654,7 +666,7 @@ export class SessionManager {
|
|
|
654
666
|
);
|
|
655
667
|
}
|
|
656
668
|
|
|
657
|
-
getActiveSessionInformation() {
|
|
669
|
+
getActiveSessionInformation(): ActiveSessionInformation[] {
|
|
658
670
|
this.#construction.assert();
|
|
659
671
|
return [...this.#sessions]
|
|
660
672
|
.filter(session => session.isSecure && !session.isPase)
|
|
@@ -47,6 +47,8 @@ export class CaseClientMessenger extends SecureChannelMessenger {
|
|
|
47
47
|
payload,
|
|
48
48
|
payloadHeader: { messageType },
|
|
49
49
|
} = await this.anyNextMessage("Sigma2(Resume)");
|
|
50
|
+
|
|
51
|
+
// TODO Add support for BUSY response and resend the message after waiting time
|
|
50
52
|
switch (messageType) {
|
|
51
53
|
case SecureMessageType.Sigma2:
|
|
52
54
|
return { sigma2Bytes: payload, sigma2: TlvCaseSigma2.decode(payload) as CaseSigma2 };
|
package/src/session/index.ts
CHANGED
|
@@ -60,6 +60,8 @@ export class PaseClientMessenger extends SecureChannelMessenger {
|
|
|
60
60
|
SecureMessageType.PbkdfParamResponse,
|
|
61
61
|
DEFAULT_NORMAL_PROCESSING_TIME,
|
|
62
62
|
);
|
|
63
|
+
|
|
64
|
+
// TODO Add support for BUSY response and resend the message after waiting time
|
|
63
65
|
return { responsePayload: payload, response: TlvPbkdfParamResponse.decode(payload) as PbkdfParamResponse };
|
|
64
66
|
}
|
|
65
67
|
|