@matter/protocol 0.15.3 → 0.15.5

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.
Files changed (105) hide show
  1. package/dist/cjs/action/client/ReadScope.d.ts +4 -0
  2. package/dist/cjs/action/client/ReadScope.d.ts.map +1 -1
  3. package/dist/cjs/action/client/ReadScope.js +2 -1
  4. package/dist/cjs/action/client/ReadScope.js.map +1 -1
  5. package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
  6. package/dist/cjs/fabric/Fabric.js.map +1 -1
  7. package/dist/cjs/fabric/FabricAuthority.d.ts +0 -1
  8. package/dist/cjs/fabric/FabricAuthority.d.ts.map +1 -1
  9. package/dist/cjs/fabric/FabricAuthority.js +2 -3
  10. package/dist/cjs/fabric/FabricAuthority.js.map +1 -1
  11. package/dist/cjs/fabric/TestFabric.d.ts.map +1 -1
  12. package/dist/cjs/fabric/TestFabric.js +2 -1
  13. package/dist/cjs/fabric/TestFabric.js.map +1 -1
  14. package/dist/cjs/interaction/AttributeDataDecoder.d.ts +9 -7
  15. package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
  16. package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
  17. package/dist/cjs/interaction/DecodedDataReport.d.ts +1 -0
  18. package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
  19. package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
  20. package/dist/cjs/interaction/InteractionClient.d.ts +15 -5
  21. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  22. package/dist/cjs/interaction/InteractionClient.js +117 -102
  23. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  24. package/dist/cjs/interaction/InteractionMessenger.d.ts +10 -90
  25. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  26. package/dist/cjs/interaction/InteractionMessenger.js +98 -22
  27. package/dist/cjs/interaction/InteractionMessenger.js.map +2 -2
  28. package/dist/cjs/interaction/SubscriptionClient.d.ts +2 -2
  29. package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -1
  30. package/dist/cjs/interaction/SubscriptionClient.js +1 -1
  31. package/dist/cjs/interaction/SubscriptionClient.js.map +1 -1
  32. package/dist/cjs/mdns/MdnsScanner.d.ts.map +1 -1
  33. package/dist/cjs/mdns/MdnsScanner.js +1 -2
  34. package/dist/cjs/mdns/MdnsScanner.js.map +1 -1
  35. package/dist/cjs/mdns/MdnsServer.js +1 -1
  36. package/dist/cjs/mdns/MdnsServer.js.map +1 -1
  37. package/dist/cjs/peer/PeerAddressStore.d.ts +3 -1
  38. package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
  39. package/dist/cjs/peer/PeerAddressStore.js.map +1 -1
  40. package/dist/cjs/session/SessionManager.d.ts.map +1 -1
  41. package/dist/cjs/session/SessionManager.js +17 -9
  42. package/dist/cjs/session/SessionManager.js.map +1 -1
  43. package/dist/cjs/session/pase/PaseServer.d.ts.map +1 -1
  44. package/dist/cjs/session/pase/PaseServer.js +2 -1
  45. package/dist/cjs/session/pase/PaseServer.js.map +1 -1
  46. package/dist/esm/action/client/ReadScope.d.ts +4 -0
  47. package/dist/esm/action/client/ReadScope.d.ts.map +1 -1
  48. package/dist/esm/action/client/ReadScope.js +2 -1
  49. package/dist/esm/action/client/ReadScope.js.map +1 -1
  50. package/dist/esm/fabric/Fabric.d.ts.map +1 -1
  51. package/dist/esm/fabric/Fabric.js.map +1 -1
  52. package/dist/esm/fabric/FabricAuthority.d.ts +0 -1
  53. package/dist/esm/fabric/FabricAuthority.d.ts.map +1 -1
  54. package/dist/esm/fabric/FabricAuthority.js +2 -3
  55. package/dist/esm/fabric/FabricAuthority.js.map +1 -1
  56. package/dist/esm/fabric/TestFabric.d.ts.map +1 -1
  57. package/dist/esm/fabric/TestFabric.js +3 -2
  58. package/dist/esm/fabric/TestFabric.js.map +1 -1
  59. package/dist/esm/interaction/AttributeDataDecoder.d.ts +9 -7
  60. package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
  61. package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
  62. package/dist/esm/interaction/DecodedDataReport.d.ts +1 -0
  63. package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
  64. package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
  65. package/dist/esm/interaction/InteractionClient.d.ts +15 -5
  66. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  67. package/dist/esm/interaction/InteractionClient.js +119 -103
  68. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  69. package/dist/esm/interaction/InteractionMessenger.d.ts +10 -90
  70. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  71. package/dist/esm/interaction/InteractionMessenger.js +98 -22
  72. package/dist/esm/interaction/InteractionMessenger.js.map +2 -2
  73. package/dist/esm/interaction/SubscriptionClient.d.ts +2 -2
  74. package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -1
  75. package/dist/esm/interaction/SubscriptionClient.js +1 -1
  76. package/dist/esm/interaction/SubscriptionClient.js.map +1 -1
  77. package/dist/esm/mdns/MdnsScanner.d.ts.map +1 -1
  78. package/dist/esm/mdns/MdnsScanner.js +1 -2
  79. package/dist/esm/mdns/MdnsScanner.js.map +1 -1
  80. package/dist/esm/mdns/MdnsServer.js +1 -1
  81. package/dist/esm/mdns/MdnsServer.js.map +1 -1
  82. package/dist/esm/peer/PeerAddressStore.d.ts +3 -1
  83. package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
  84. package/dist/esm/peer/PeerAddressStore.js.map +1 -1
  85. package/dist/esm/session/SessionManager.d.ts.map +1 -1
  86. package/dist/esm/session/SessionManager.js +19 -10
  87. package/dist/esm/session/SessionManager.js.map +1 -1
  88. package/dist/esm/session/pase/PaseServer.d.ts.map +1 -1
  89. package/dist/esm/session/pase/PaseServer.js +2 -1
  90. package/dist/esm/session/pase/PaseServer.js.map +1 -1
  91. package/package.json +6 -6
  92. package/src/action/client/ReadScope.ts +7 -0
  93. package/src/fabric/Fabric.ts +1 -1
  94. package/src/fabric/FabricAuthority.ts +2 -2
  95. package/src/fabric/TestFabric.ts +2 -1
  96. package/src/interaction/AttributeDataDecoder.ts +4 -1
  97. package/src/interaction/DecodedDataReport.ts +1 -0
  98. package/src/interaction/InteractionClient.ts +183 -122
  99. package/src/interaction/InteractionMessenger.ts +126 -22
  100. package/src/interaction/SubscriptionClient.ts +6 -5
  101. package/src/mdns/MdnsScanner.ts +1 -2
  102. package/src/mdns/MdnsServer.ts +2 -2
  103. package/src/peer/PeerAddressStore.ts +3 -1
  104. package/src/session/SessionManager.ts +35 -24
  105. package/src/session/pase/PaseServer.ts +2 -1
@@ -13,14 +13,20 @@ import {
13
13
  NoResponseTimeoutError,
14
14
  UnexpectedDataError,
15
15
  } from "#general";
16
+ import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
17
+ import { DecodedDataReport } from "#interaction/DecodedDataReport.js";
16
18
  import { Specification } from "#model";
17
19
  import { ChannelNotConnectedError } from "#protocol/MessageChannel.js";
18
20
  import {
21
+ AttributeId,
22
+ ClusterId,
23
+ EndpointNumber,
19
24
  ReceivedStatusResponseError,
20
25
  Status,
21
26
  StatusCode,
22
27
  StatusResponseError,
23
28
  TlvAny,
29
+ TlvAttributeReport,
24
30
  TlvDataReport,
25
31
  TlvDataReportForSend,
26
32
  TlvDataVersionFilter,
@@ -796,8 +802,105 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
796
802
  return message;
797
803
  }
798
804
 
799
- async readAggregateDataReport(expectedSubscriptionIds?: number[]): Promise<DataReport> {
800
- let result: DataReport | undefined;
805
+ /**
806
+ * Reads data report stream and aggregates them into a single report.
807
+ * Additionally, a callback can be provided that is called for each cluster chunk received.
808
+ */
809
+ async readAggregateDataReport(
810
+ chunkListener?: (chunk: DecodedAttributeReportValue<any>[]) => Promise<void>,
811
+ expectedSubscriptionIds?: number[],
812
+ ): Promise<DecodedDataReport> {
813
+ let result: DecodedDataReport | undefined = undefined;
814
+ let currentEndpointId: EndpointNumber | undefined = undefined;
815
+ let currentClusterId: ClusterId | undefined = undefined;
816
+ const currentClusterChunk = new Array<DecodedAttributeReportValue<any>>();
817
+ let pendingAttributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined = undefined;
818
+
819
+ const handleAttributeReportEntries = (
820
+ attributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined,
821
+ previousPendingAttributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined,
822
+ ) => {
823
+ if (previousPendingAttributeReports?.length) {
824
+ attributeReports = attributeReports ?? [];
825
+ attributeReports.unshift(...previousPendingAttributeReports);
826
+ }
827
+
828
+ let lastAttributeDataIndex = -1;
829
+ if (attributeReports?.length) {
830
+ let lastEndpointId: EndpointNumber | undefined = undefined;
831
+ let lastClusterId: ClusterId | undefined = undefined;
832
+ let lastAttributeId: AttributeId | undefined = undefined;
833
+ for (let i = attributeReports.length - 1; i >= 0; i--) {
834
+ const attributeReport = attributeReports[i];
835
+ if (attributeReport.attributeData === undefined) {
836
+ break; // No data report, so nothing more to search for
837
+ }
838
+ const {
839
+ path: { endpointId, clusterId, attributeId },
840
+ } = attributeReport.attributeData;
841
+ if (lastEndpointId === undefined && lastClusterId === undefined && lastAttributeId === undefined) {
842
+ // Remember path of the last attribute data entry and check if previous entries match
843
+ lastEndpointId = endpointId;
844
+ lastClusterId = clusterId;
845
+ lastAttributeId = attributeId;
846
+ }
847
+ if (
848
+ endpointId === lastEndpointId &&
849
+ clusterId === lastClusterId &&
850
+ attributeId === lastAttributeId
851
+ ) {
852
+ lastAttributeDataIndex = i;
853
+ continue;
854
+ }
855
+ break; // We found an attribute that does not match the last one, so we are done
856
+ }
857
+
858
+ if (lastAttributeDataIndex > 0) {
859
+ return attributeReports.splice(lastAttributeDataIndex);
860
+ }
861
+ }
862
+ };
863
+
864
+ const processDecodedReport = async (
865
+ decodedReport: DecodedDataReport,
866
+ result: DecodedDataReport | undefined,
867
+ ) => {
868
+ if (!result) {
869
+ result = decodedReport;
870
+ } else {
871
+ if (!result.attributeReports) {
872
+ result.attributeReports = decodedReport.attributeReports;
873
+ } else {
874
+ result.attributeReports.push(...decodedReport.attributeReports);
875
+ }
876
+ if (Array.isArray(decodedReport.eventReports)) {
877
+ if (!result.eventReports) {
878
+ result.eventReports = decodedReport.eventReports;
879
+ } else {
880
+ result.eventReports.push(...decodedReport.eventReports);
881
+ }
882
+ }
883
+ }
884
+
885
+ if (chunkListener !== undefined && decodedReport.attributeReports) {
886
+ for (const data of decodedReport.attributeReports) {
887
+ const {
888
+ path: { endpointId, clusterId },
889
+ } = data;
890
+ if (currentEndpointId !== endpointId || currentClusterId !== clusterId) {
891
+ // We switched the cluster, so we need to send the current chunk first
892
+ if (currentClusterChunk.length > 0) {
893
+ await chunkListener(currentClusterChunk);
894
+ currentClusterChunk.length = 0;
895
+ }
896
+ currentEndpointId = endpointId;
897
+ currentClusterId = clusterId;
898
+ }
899
+ currentClusterChunk.push(data);
900
+ }
901
+ }
902
+ return result;
903
+ };
801
904
 
802
905
  for await (const report of this.readDataReports()) {
803
906
  if (expectedSubscriptionIds !== undefined) {
@@ -820,24 +923,25 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
820
923
  throw new UnexpectedDataError(`Invalid subscription ID ${report.subscriptionId} received`);
821
924
  }
822
925
 
823
- if (!result) {
824
- result = report;
825
- } else {
826
- if (Array.isArray(report.attributeReports)) {
827
- if (!result.attributeReports) {
828
- result.attributeReports = report.attributeReports;
829
- } else {
830
- result.attributeReports.push(...report.attributeReports);
831
- }
832
- }
833
- if (Array.isArray(report.eventReports)) {
834
- if (!result.eventReports) {
835
- result.eventReports = report.eventReports;
836
- } else {
837
- result.eventReports.push(...report.eventReports);
838
- }
839
- }
840
- }
926
+ report.attributeReports = report.attributeReports ?? [];
927
+ pendingAttributeReports = handleAttributeReportEntries(report.attributeReports, pendingAttributeReports);
928
+
929
+ result = await processDecodedReport(DecodedDataReport(report), result);
930
+ }
931
+
932
+ if (pendingAttributeReports?.length && result !== undefined) {
933
+ result = await processDecodedReport(
934
+ DecodedDataReport({
935
+ interactionModelRevision: result.interactionModelRevision,
936
+ attributeReports: pendingAttributeReports,
937
+ }),
938
+ result,
939
+ );
940
+ }
941
+
942
+ if (chunkListener !== undefined && currentClusterChunk.length > 0) {
943
+ await chunkListener(currentClusterChunk);
944
+ currentClusterChunk.length = 0;
841
945
  }
842
946
 
843
947
  if (result === undefined) {
@@ -1007,8 +1111,8 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
1007
1111
  await this.send(MessageType.SubscribeRequest, request);
1008
1112
  }
1009
1113
 
1010
- async readAggregateSubscribeResponse() {
1011
- const report = await this.readAggregateDataReport();
1114
+ async readAggregateSubscribeResponse(chunkListener?: (chunk: DecodedAttributeReportValue<any>[]) => Promise<void>) {
1115
+ const report = await this.readAggregateDataReport(chunkListener);
1012
1116
  const { subscriptionId } = report;
1013
1117
 
1014
1118
  if (subscriptionId === undefined) {
@@ -5,10 +5,11 @@
5
5
  */
6
6
 
7
7
  import { Environment, Environmental, Logger, MaybePromise, Time, Timer } from "#general";
8
+ import { DecodedDataReport } from "#interaction/DecodedDataReport.js";
8
9
  import { MessageExchange } from "#protocol/MessageExchange.js";
9
10
  import { ProtocolHandler } from "#protocol/ProtocolHandler.js";
10
11
  import { INTERACTION_PROTOCOL_ID } from "#types";
11
- import { DataReport, IncomingInteractionClientMessenger } from "./InteractionMessenger.js";
12
+ import { IncomingInteractionClientMessenger } from "./InteractionMessenger.js";
12
13
 
13
14
  const logger = Logger.get("SubscriptionClient");
14
15
 
@@ -16,7 +17,7 @@ export interface RegisteredSubscription {
16
17
  id: number;
17
18
  maximumPeerResponseTimeMs: number;
18
19
  maxIntervalS: number;
19
- onData: (dataReport: DataReport) => MaybePromise<void>;
20
+ onData: (dataReport: DecodedDataReport) => MaybePromise<void>;
20
21
  onTimeout?: () => void;
21
22
  }
22
23
 
@@ -28,7 +29,7 @@ export interface RegisteredSubscription {
28
29
  export class SubscriptionClient implements ProtocolHandler {
29
30
  readonly id = INTERACTION_PROTOCOL_ID;
30
31
  readonly requiresSecureSession = true;
31
- readonly #listeners = new Map<number, (dataReport: DataReport) => MaybePromise<void>>();
32
+ readonly #listeners = new Map<number, (dataReport: DecodedDataReport) => MaybePromise<void>>();
32
33
  readonly #timeouts = new Map<number, Timer>();
33
34
 
34
35
  constructor() {}
@@ -80,10 +81,10 @@ export class SubscriptionClient implements ProtocolHandler {
80
81
  async onNewExchange(exchange: MessageExchange) {
81
82
  const messenger = new IncomingInteractionClientMessenger(exchange);
82
83
 
83
- let dataReport: DataReport;
84
+ let dataReport: DecodedDataReport;
84
85
  try {
85
86
  // TODO Adjust this to getting packages as callback when received to handle error cases and checks outside
86
- dataReport = await messenger.readAggregateDataReport([...this.#listeners.keys()]);
87
+ dataReport = await messenger.readAggregateDataReport(undefined, [...this.#listeners.keys()]);
87
88
  } finally {
88
89
  messenger.close().catch(error => logger.info("Error closing client messenger", error));
89
90
  }
@@ -1042,8 +1042,7 @@ export class MdnsScanner implements Scanner {
1042
1042
  if (this.#closing) return;
1043
1043
  const message = DnsCodec.decode(messageBytes);
1044
1044
  if (message === undefined) return; // The message cannot be parsed
1045
- if (message.messageType !== DnsMessageType.Response && message.messageType !== DnsMessageType.TruncatedResponse)
1046
- return;
1045
+ if (!DnsMessageType.isResponse(message.messageType)) return;
1047
1046
 
1048
1047
  const answers = this.#structureAnswers([...message.answers, ...message.additionalRecords]);
1049
1048
 
@@ -100,8 +100,8 @@ export class MdnsServer {
100
100
  const message = DnsCodec.decode(messageBytes);
101
101
  if (message === undefined) return; // The message cannot be parsed
102
102
  const { transactionId, messageType, queries, answers: knownAnswers } = message;
103
- if (messageType !== DnsMessageType.Query && messageType !== DnsMessageType.TruncatedQuery) return;
104
- if (queries.length === 0) return; // No queries to answer, can happen in a TruncatedQuery, let's ignore for now
103
+ if (!DnsMessageType.isQuery(messageType)) return;
104
+ if (queries.length === 0) return; // TODO correctly handle TruncatedQueries by waiting and combining multiple queries
105
105
  for (const portRecords of records.values()) {
106
106
  let answers = queries.flatMap(query => this.#queryRecords(query, portRecords));
107
107
  if (answers.length === 0) continue;
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { ReadScope } from "#action/client/ReadScope.js";
7
8
  import { Construction, MaybePromise } from "#general";
8
9
  import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
9
10
  import { AttributeId, ClusterId, EndpointNumber, EventNumber } from "#types";
@@ -27,7 +28,7 @@ export abstract class PeerDataStore {
27
28
  abstract maxEventNumber: EventNumber;
28
29
  abstract updateLastEventNumber(eventNumber: EventNumber): MaybePromise<void>;
29
30
 
30
- abstract persistAttributes(attributes: DecodedAttributeReportValue<any>[]): MaybePromise<void>;
31
+ abstract persistAttributes(attributes: DecodedAttributeReportValue<any>[], scope: ReadScope): MaybePromise<void>;
31
32
 
32
33
  // TODO: Find a maybe better way to achieve this without functions
33
34
  abstract retrieveAttribute(
@@ -41,4 +42,5 @@ export abstract class PeerDataStore {
41
42
  filterEndpointId?: EndpointNumber,
42
43
  filterClusterId?: ClusterId,
43
44
  ): { endpointId: EndpointNumber; clusterId: ClusterId; dataVersion: number }[];
45
+ abstract cleanupAttributeData(endpointId: EndpointNumber, clusterIds?: ClusterId[]): MaybePromise<void>;
44
46
  }
@@ -21,6 +21,7 @@ import {
21
21
  ObserverGroup,
22
22
  StorageContext,
23
23
  StorageManager,
24
+ toHex,
24
25
  } from "#general";
25
26
  import { Subscription } from "#interaction/Subscription.js";
26
27
  import { Specification } from "#model";
@@ -76,6 +77,7 @@ type ResumptionStorageRecord = {
76
77
  sharedSecret: Uint8Array;
77
78
  resumptionId: Uint8Array;
78
79
  fabricId: FabricId;
80
+ fabricIndex: FabricIndex;
79
81
  peerNodeId: NodeId;
80
82
  sessionParameters: {
81
83
  idleIntervalMs: number;
@@ -545,21 +547,21 @@ export class SessionManager {
545
547
  ([
546
548
  address,
547
549
  { sharedSecret, resumptionId, peerNodeId, fabric, sessionParameters, caseAuthenticatedTags },
548
- ]) =>
549
- ({
550
- nodeId: address.nodeId,
551
- sharedSecret,
552
- resumptionId,
553
- fabricId: fabric.fabricId,
554
- peerNodeId: peerNodeId,
555
- sessionParameters: {
556
- ...sessionParameters,
557
- supportedTransports: sessionParameters.supportedTransports
558
- ? SupportedTransportsSchema.encode(sessionParameters.supportedTransports)
559
- : undefined,
560
- },
561
- caseAuthenticatedTags,
562
- }) as ResumptionStorageRecord,
550
+ ]): ResumptionStorageRecord => ({
551
+ nodeId: address.nodeId,
552
+ sharedSecret,
553
+ resumptionId,
554
+ fabricId: fabric.fabricId,
555
+ fabricIndex: fabric.fabricIndex,
556
+ peerNodeId: peerNodeId,
557
+ sessionParameters: {
558
+ ...sessionParameters,
559
+ supportedTransports: sessionParameters.supportedTransports
560
+ ? SupportedTransportsSchema.encode(sessionParameters.supportedTransports)
561
+ : undefined,
562
+ },
563
+ caseAuthenticatedTags,
564
+ }),
563
565
  ),
564
566
  );
565
567
  }
@@ -578,6 +580,7 @@ export class SessionManager {
578
580
  sharedSecret,
579
581
  resumptionId,
580
582
  fabricId,
583
+ fabricIndex,
581
584
  peerNodeId,
582
585
  sessionParameters: {
583
586
  idleIntervalMs,
@@ -592,19 +595,27 @@ export class SessionManager {
592
595
  } = {},
593
596
  caseAuthenticatedTags,
594
597
  }) => {
595
- const fabric = this.#context.fabrics.find(fabric => fabric.fabricId === fabricId);
596
- logger.info(
597
- "restoring resumption record for node",
598
- nodeId,
599
- "and peer node",
600
- peerNodeId,
601
- "for fabric index",
602
- fabric?.fabricIndex,
598
+ const fabric = this.#context.fabrics.find(
599
+ fabric =>
600
+ fabric.fabricId === fabricId &&
601
+ // Backward compatibility logic: fabricIndex was added later (0.15.5), so it might be undefined in older records
602
+ (fabricIndex === undefined || fabric.fabricIndex === fabricIndex),
603
603
  );
604
604
  if (!fabric) {
605
- logger.error("fabric not found for resumption record", fabricId);
605
+ logger.warn(
606
+ `Ignoring resumption record for fabric 0x${toHex(fabricId)} and index ${fabricIndex} because we cannot find a matching fabric`,
607
+ );
606
608
  return;
607
609
  }
610
+ logger.info(
611
+ "restoring resumption record for node",
612
+ fabric.addressOf(nodeId).toString(),
613
+ "and peer node",
614
+ fabric.addressOf(peerNodeId).toString(),
615
+ "for fabric id",
616
+ `0x${toHex(fabric.fabricId)}`,
617
+ `(0x${toHex(fabric.rootVendorId)}, "${fabric?.label}")`,
618
+ );
608
619
  this.#resumptionRecords.set(fabric.addressOf(nodeId), {
609
620
  sharedSecret,
610
621
  resumptionId,
@@ -68,7 +68,8 @@ export class PaseServer implements ProtocolHandler {
68
68
  // successfully established a session, the Commissionee SHALL NOT accept any more requests for new PASE
69
69
  // sessions until session establishment fails or the successfully established PASE session is terminated on
70
70
  // the commissioning channel.
71
- if (this.sessions.getPaseSession()) {
71
+ const paseSession = this.sessions.getPaseSession();
72
+ if (paseSession !== undefined && !paseSession.isClosing) {
72
73
  logger.info("Pase server: Pairing already in progress (PASE session exists), ignoring new exchange.");
73
74
  } else if (this.#pairingTimer?.isRunning) {
74
75
  logger.info(