@matter/protocol 0.17.2 → 0.17.3-alpha.0-20260617-ea3690abc

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 (159) hide show
  1. package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
  2. package/dist/cjs/action/client/ClientInteraction.js +16 -2
  3. package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
  4. package/dist/cjs/action/client/ClientRequest.d.ts +8 -1
  5. package/dist/cjs/action/client/ClientRequest.d.ts.map +1 -1
  6. package/dist/cjs/action/server/AttributeReadResponse.d.ts.map +1 -1
  7. package/dist/cjs/action/server/AttributeReadResponse.js +26 -12
  8. package/dist/cjs/action/server/AttributeReadResponse.js.map +1 -1
  9. package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
  10. package/dist/cjs/action/server/AttributeWriteResponse.js +27 -10
  11. package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
  12. package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
  13. package/dist/cjs/action/server/CommandInvokeResponse.js +27 -10
  14. package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
  15. package/dist/cjs/action/server/EventReadResponse.d.ts.map +1 -1
  16. package/dist/cjs/action/server/EventReadResponse.js +27 -10
  17. package/dist/cjs/action/server/EventReadResponse.js.map +1 -1
  18. package/dist/cjs/certificate/DeviceAttestationValidator.d.ts.map +1 -1
  19. package/dist/cjs/certificate/DeviceAttestationValidator.js +15 -12
  20. package/dist/cjs/certificate/DeviceAttestationValidator.js.map +1 -1
  21. package/dist/cjs/certificate/kinds/Certificate.d.ts +7 -0
  22. package/dist/cjs/certificate/kinds/Certificate.d.ts.map +1 -1
  23. package/dist/cjs/certificate/kinds/Certificate.js +30 -1
  24. package/dist/cjs/certificate/kinds/Certificate.js.map +1 -1
  25. package/dist/cjs/codec/MessagePrivacy.d.ts +1 -1
  26. package/dist/cjs/codec/MessagePrivacy.d.ts.map +1 -1
  27. package/dist/cjs/codec/MessagePrivacy.js +3 -2
  28. package/dist/cjs/codec/MessagePrivacy.js.map +1 -1
  29. package/dist/cjs/events/OccurrenceManager.d.ts +2 -2
  30. package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
  31. package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
  32. package/dist/cjs/interaction/AttributeDataEncoder.js.map +1 -1
  33. package/dist/cjs/peer/Peer.d.ts +5 -0
  34. package/dist/cjs/peer/Peer.d.ts.map +1 -1
  35. package/dist/cjs/peer/Peer.js +1 -0
  36. package/dist/cjs/peer/Peer.js.map +1 -1
  37. package/dist/cjs/peer/PeerConnection.d.ts +6 -1
  38. package/dist/cjs/peer/PeerConnection.d.ts.map +1 -1
  39. package/dist/cjs/peer/PeerConnection.js +23 -5
  40. package/dist/cjs/peer/PeerConnection.js.map +1 -1
  41. package/dist/cjs/peer/PeerExchangeProvider.d.ts.map +1 -1
  42. package/dist/cjs/peer/PeerExchangeProvider.js +3 -0
  43. package/dist/cjs/peer/PeerExchangeProvider.js.map +1 -1
  44. package/dist/cjs/peer/PeerTimingParameters.d.ts +9 -0
  45. package/dist/cjs/peer/PeerTimingParameters.d.ts.map +1 -1
  46. package/dist/cjs/peer/PeerTimingParameters.js +3 -1
  47. package/dist/cjs/peer/PeerTimingParameters.js.map +1 -1
  48. package/dist/cjs/protocol/DeviceCommissioner.d.ts.map +1 -1
  49. package/dist/cjs/protocol/DeviceCommissioner.js +1 -1
  50. package/dist/cjs/protocol/DeviceCommissioner.js.map +1 -1
  51. package/dist/cjs/protocol/ExchangeProvider.d.ts +6 -1
  52. package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
  53. package/dist/cjs/protocol/ExchangeProvider.js +4 -2
  54. package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
  55. package/dist/cjs/protocol/MRP.d.ts +1 -1
  56. package/dist/cjs/protocol/MRP.d.ts.map +1 -1
  57. package/dist/cjs/protocol/MRP.js +1 -2
  58. package/dist/cjs/protocol/MRP.js.map +1 -1
  59. package/dist/cjs/protocol/MessageExchange.d.ts +14 -1
  60. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  61. package/dist/cjs/protocol/MessageExchange.js +31 -5
  62. package/dist/cjs/protocol/MessageExchange.js.map +1 -1
  63. package/dist/cjs/session/pase/PaseClient.d.ts.map +1 -1
  64. package/dist/cjs/session/pase/PaseClient.js +1 -1
  65. package/dist/cjs/session/pase/PaseClient.js.map +1 -1
  66. package/dist/cjs/session/pase/PaseServer.d.ts.map +1 -1
  67. package/dist/cjs/session/pase/PaseServer.js +11 -2
  68. package/dist/cjs/session/pase/PaseServer.js.map +1 -1
  69. package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
  70. package/dist/esm/action/client/ClientInteraction.js +16 -2
  71. package/dist/esm/action/client/ClientInteraction.js.map +1 -1
  72. package/dist/esm/action/client/ClientRequest.d.ts +8 -1
  73. package/dist/esm/action/client/ClientRequest.d.ts.map +1 -1
  74. package/dist/esm/action/server/AttributeReadResponse.d.ts.map +1 -1
  75. package/dist/esm/action/server/AttributeReadResponse.js +27 -13
  76. package/dist/esm/action/server/AttributeReadResponse.js.map +1 -1
  77. package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
  78. package/dist/esm/action/server/AttributeWriteResponse.js +28 -11
  79. package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
  80. package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
  81. package/dist/esm/action/server/CommandInvokeResponse.js +28 -11
  82. package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
  83. package/dist/esm/action/server/EventReadResponse.d.ts.map +1 -1
  84. package/dist/esm/action/server/EventReadResponse.js +28 -11
  85. package/dist/esm/action/server/EventReadResponse.js.map +1 -1
  86. package/dist/esm/certificate/DeviceAttestationValidator.d.ts.map +1 -1
  87. package/dist/esm/certificate/DeviceAttestationValidator.js +16 -13
  88. package/dist/esm/certificate/DeviceAttestationValidator.js.map +1 -1
  89. package/dist/esm/certificate/kinds/Certificate.d.ts +7 -0
  90. package/dist/esm/certificate/kinds/Certificate.d.ts.map +1 -1
  91. package/dist/esm/certificate/kinds/Certificate.js +30 -1
  92. package/dist/esm/certificate/kinds/Certificate.js.map +1 -1
  93. package/dist/esm/codec/MessagePrivacy.d.ts +1 -1
  94. package/dist/esm/codec/MessagePrivacy.d.ts.map +1 -1
  95. package/dist/esm/codec/MessagePrivacy.js +4 -2
  96. package/dist/esm/codec/MessagePrivacy.js.map +1 -1
  97. package/dist/esm/events/OccurrenceManager.d.ts +2 -2
  98. package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
  99. package/dist/esm/events/OccurrenceManager.js.map +1 -1
  100. package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
  101. package/dist/esm/interaction/AttributeDataEncoder.js.map +1 -1
  102. package/dist/esm/peer/Peer.d.ts +5 -0
  103. package/dist/esm/peer/Peer.d.ts.map +1 -1
  104. package/dist/esm/peer/Peer.js +1 -0
  105. package/dist/esm/peer/Peer.js.map +1 -1
  106. package/dist/esm/peer/PeerConnection.d.ts +6 -1
  107. package/dist/esm/peer/PeerConnection.d.ts.map +1 -1
  108. package/dist/esm/peer/PeerConnection.js +23 -5
  109. package/dist/esm/peer/PeerConnection.js.map +1 -1
  110. package/dist/esm/peer/PeerExchangeProvider.d.ts.map +1 -1
  111. package/dist/esm/peer/PeerExchangeProvider.js +3 -0
  112. package/dist/esm/peer/PeerExchangeProvider.js.map +1 -1
  113. package/dist/esm/peer/PeerTimingParameters.d.ts +9 -0
  114. package/dist/esm/peer/PeerTimingParameters.d.ts.map +1 -1
  115. package/dist/esm/peer/PeerTimingParameters.js +4 -2
  116. package/dist/esm/peer/PeerTimingParameters.js.map +1 -1
  117. package/dist/esm/protocol/DeviceCommissioner.d.ts.map +1 -1
  118. package/dist/esm/protocol/DeviceCommissioner.js +2 -1
  119. package/dist/esm/protocol/DeviceCommissioner.js.map +1 -1
  120. package/dist/esm/protocol/ExchangeProvider.d.ts +6 -1
  121. package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
  122. package/dist/esm/protocol/ExchangeProvider.js +4 -2
  123. package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
  124. package/dist/esm/protocol/MRP.d.ts +1 -1
  125. package/dist/esm/protocol/MRP.d.ts.map +1 -1
  126. package/dist/esm/protocol/MRP.js +1 -2
  127. package/dist/esm/protocol/MRP.js.map +1 -1
  128. package/dist/esm/protocol/MessageExchange.d.ts +14 -1
  129. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  130. package/dist/esm/protocol/MessageExchange.js +31 -5
  131. package/dist/esm/protocol/MessageExchange.js.map +1 -1
  132. package/dist/esm/session/pase/PaseClient.d.ts.map +1 -1
  133. package/dist/esm/session/pase/PaseClient.js +2 -2
  134. package/dist/esm/session/pase/PaseClient.js.map +1 -1
  135. package/dist/esm/session/pase/PaseServer.d.ts.map +1 -1
  136. package/dist/esm/session/pase/PaseServer.js +12 -2
  137. package/dist/esm/session/pase/PaseServer.js.map +1 -1
  138. package/package.json +5 -5
  139. package/src/action/client/ClientInteraction.ts +19 -1
  140. package/src/action/client/ClientRequest.ts +9 -1
  141. package/src/action/server/AttributeReadResponse.ts +39 -18
  142. package/src/action/server/AttributeWriteResponse.ts +35 -19
  143. package/src/action/server/CommandInvokeResponse.ts +36 -15
  144. package/src/action/server/EventReadResponse.ts +42 -16
  145. package/src/certificate/DeviceAttestationValidator.ts +17 -13
  146. package/src/certificate/kinds/Certificate.ts +43 -0
  147. package/src/codec/MessagePrivacy.ts +6 -4
  148. package/src/events/OccurrenceManager.ts +2 -2
  149. package/src/interaction/AttributeDataEncoder.ts +3 -3
  150. package/src/peer/Peer.ts +7 -0
  151. package/src/peer/PeerConnection.ts +33 -6
  152. package/src/peer/PeerExchangeProvider.ts +4 -0
  153. package/src/peer/PeerTimingParameters.ts +15 -2
  154. package/src/protocol/DeviceCommissioner.ts +2 -1
  155. package/src/protocol/ExchangeProvider.ts +12 -2
  156. package/src/protocol/MRP.ts +5 -6
  157. package/src/protocol/MessageExchange.ts +44 -6
  158. package/src/session/pase/PaseClient.ts +2 -6
  159. package/src/session/pase/PaseServer.ts +12 -2
@@ -32,6 +32,12 @@ export interface NewExchangeOptions extends Omit<InteractionSettings, "transacti
32
32
  */
33
33
  network?: string;
34
34
 
35
+ /**
36
+ * Per-call override for the peer-medium MRP retransmission margin. When omitted the margin derives from the
37
+ * peer's network medium, independent of any {@link network} throttle override.
38
+ */
39
+ additionalMrpDelay?: Duration;
40
+
35
41
  /**
36
42
  * Optional address override for the exchange. When set, messages are sent to this address
37
43
  * instead of the session's default peer address.
@@ -100,8 +106,12 @@ export class DedicatedChannelExchangeProvider extends ExchangeProvider {
100
106
  return this.#session.parameters.maxPathsPerInvoke;
101
107
  }
102
108
 
103
- async initiateExchange(): Promise<MessageExchange> {
104
- return this.exchangeManager.initiateExchangeForSession(this.#session, INTERACTION_PROTOCOL_ID);
109
+ async initiateExchange(options?: NewExchangeOptions): Promise<MessageExchange> {
110
+ // This provider has no peer/medium context, so the medium-derived margin is unavailable; only an explicit
111
+ // per-call override can apply here.
112
+ return this.exchangeManager.initiateExchangeForSession(this.#session, INTERACTION_PROTOCOL_ID, {
113
+ peerAdditionalMrpDelay: options?.additionalMrpDelay,
114
+ });
105
115
  }
106
116
 
107
117
  get channelType() {
@@ -20,7 +20,7 @@ export namespace MRP {
20
20
  /** The scaler for random jitter in the backoff equation. */
21
21
  export const BACKOFF_JITTER = 0.25;
22
22
 
23
- /** The scaler margin increase to backoff over the peer sleepy interval. */
23
+ /** The scaler margin increase to backoff over the applicable (active/idle) interval. */
24
24
  export const BACKOFF_MARGIN = 1.1;
25
25
 
26
26
  /** The number of retransmissions before transitioning from linear to exponential backoff. */
@@ -128,11 +128,10 @@ export namespace MRP {
128
128
  ) {
129
129
  const { activeInterval, idleInterval } = sessionParameters;
130
130
 
131
- // The first message of an exchange SHALL use the idle interval; subsequent ones SHOULD use the active
132
- // interval "unless the sender has other means to determine whether the device is active or idle" —
133
- // isPeerActive is that means, so honor it per retransmission like CHIP does (ICD correctness)
134
- const peerActive = transmissionNumber > 0 && isPeerActive;
135
- let baseInterval = peerActive ? activeInterval : idleInterval;
131
+ // Every transmission (including the initial one) selects its interval by PeerActiveMode, re-evaluated
132
+ // per (re)transmission, matching CHIP GetMRPBaseTimeout(). isPeerActive already yields idle for a
133
+ // genuinely quiet peer, so no position-based first-message rule is needed.
134
+ let baseInterval = isPeerActive ? activeInterval : idleInterval;
136
135
  if (!calculateMaximum) {
137
136
  baseInterval += additionalDelay;
138
137
  }
@@ -199,7 +199,7 @@ export class MessageExchange {
199
199
  readonly #onSend?: MessageExchange.SendNotifier;
200
200
  readonly #onReceive?: MessageExchange.ReceiveNotifier;
201
201
  readonly #addressOverride?: ServerAddressUdp;
202
- readonly #network?: NetworkProfile;
202
+ readonly #peerAdditionalMrpDelay?: Duration;
203
203
  #receivedMessageToAck: Message | undefined;
204
204
  #receivedMessageAckTimer = Time.getTimer("ack receipt timeout", MRP.STANDALONE_ACK_TIMEOUT, () => {
205
205
  if (this.#receivedMessageToAck !== undefined) {
@@ -251,6 +251,7 @@ export class MessageExchange {
251
251
  onSend,
252
252
  onReceive,
253
253
  network,
254
+ peerAdditionalMrpDelay,
254
255
  addressOverride,
255
256
  } = config;
256
257
 
@@ -264,7 +265,7 @@ export class MessageExchange {
264
265
  this.#onSend = onSend;
265
266
  this.#onReceive = onReceive;
266
267
  this.#addressOverride = addressOverride;
267
- this.#network = network;
268
+ this.#peerAdditionalMrpDelay = peerAdditionalMrpDelay;
268
269
 
269
270
  const { activeThreshold, activeInterval, idleInterval } = this.session.parameters;
270
271
 
@@ -991,12 +992,22 @@ export class MessageExchange {
991
992
  }
992
993
 
993
994
  get #mrpResubmissionBackOffTime() {
995
+ return this.#backOffFor(this.#retransmissionCounter);
996
+ }
997
+
998
+ /**
999
+ * Scheduled MRP backoff for a given (re)transmission number, after the send-option overrides.
1000
+ *
1001
+ * The cap never drops below the peer's idle interval: a peer whose idle base backoff already exceeds
1002
+ * maxRetransmissionTime must not be retried faster than its own idle cadence.
1003
+ */
1004
+ #backOffFor(retransmissionCount: number) {
994
1005
  const additionalDelay = Duration.max(
995
1006
  this.#context.localAdditionalMrpDelay,
996
- this.#network?.additionalMrpDelay ?? Millis(0),
1007
+ this.#peerAdditionalMrpDelay ?? Millis(0),
997
1008
  );
998
1009
  let backOff = this.channel.getMrpResubmissionBackOffTime(
999
- this.#retransmissionCounter,
1010
+ retransmissionCount,
1000
1011
  undefined,
1001
1012
  false,
1002
1013
  additionalDelay,
@@ -1004,7 +1015,26 @@ export class MessageExchange {
1004
1015
  if (this.#sendOptions.initialRetransmissionTime !== undefined) {
1005
1016
  backOff = Millis(backOff + this.#sendOptions.initialRetransmissionTime);
1006
1017
  }
1007
- return Duration.min(backOff, this.#sendOptions.maxRetransmissionTime ?? Forever);
1018
+ const cap = Duration.max(
1019
+ this.#sendOptions.maxRetransmissionTime ?? Forever,
1020
+ this.session.parameters.idleInterval ?? Instant,
1021
+ );
1022
+ return Duration.min(backOff, cap);
1023
+ }
1024
+
1025
+ /**
1026
+ * How much restarting the exchange (resetting the retransmission counter to 0) would shorten the wait until
1027
+ * the next (re)transmission. Roughly zero near the base interval — e.g. an idle peer, whose fresh interval is
1028
+ * just as slow.
1029
+ */
1030
+ get retransmissionRestartSaving(): Duration {
1031
+ // No pending retransmit → nothing for a restart to shorten → report no saving so the kick is suppressed.
1032
+ const currentWait = this.#retransmissionTimer?.interval;
1033
+ if (currentWait === undefined) {
1034
+ return Instant;
1035
+ }
1036
+ // Read the live timer's real interval (margins/jitter/cap baked in), not a freshly recomputed random one.
1037
+ return Duration.max(Instant, Millis(currentWait - this.#backOffFor(0)));
1008
1038
  }
1009
1039
  }
1010
1040
 
@@ -1021,10 +1051,18 @@ export namespace MessageExchange {
1021
1051
  onReceive?: ReceiveNotifier;
1022
1052
 
1023
1053
  /**
1024
- * Network Profile used
1054
+ * Network profile governing exchange throttling. Retained for diagnostics; MRP backoff derives from
1055
+ * {@link peerAdditionalMrpDelay} instead, so an explicit throttle override (e.g. "unlimited") does not
1056
+ * affect retransmission timing.
1025
1057
  */
1026
1058
  network?: NetworkProfile;
1027
1059
 
1060
+ /**
1061
+ * Additive MRP retransmission margin for the peer's network medium. Sourced independently of
1062
+ * {@link network} so concurrency overrides cannot strip the medium-correct margin (e.g. thread's).
1063
+ */
1064
+ peerAdditionalMrpDelay?: Duration;
1065
+
1028
1066
  /**
1029
1067
  * Optional address override for this exchange. When set, messages are sent to this address
1030
1068
  * instead of the session's default peer address.
@@ -21,7 +21,7 @@ import {
21
21
  Spake2p,
22
22
  UnexpectedDataError,
23
23
  } from "@matter/general";
24
- import { CommissioningOptions, NodeId, SecureChannelStatusCode } from "@matter/types";
24
+ import { isValidPasscode, NodeId, SecureChannelStatusCode } from "@matter/types";
25
25
  import { TransientPeerCommunicationError } from "../../peer/PeerCommunicationError.js";
26
26
  import { MessageExchange } from "../../protocol/MessageExchange.js";
27
27
  import { RetransmissionLimitReachedError } from "../../protocol/errors.js";
@@ -47,11 +47,7 @@ export class PaseClient {
47
47
  // Generate 27-bit random candidates and reject invalid values to avoid modulo bias.
48
48
  for (let i = 0; i < MAX_PASSCODE_GENERATION_ATTEMPTS; i++) {
49
49
  const passcode = crypto.randomUint32 & 0x07ff_ffff;
50
- if (
51
- passcode >= 1 &&
52
- passcode <= 99_999_998 &&
53
- !CommissioningOptions.FORBIDDEN_PASSCODES.includes(passcode)
54
- ) {
50
+ if (isValidPasscode(passcode)) {
55
51
  return passcode;
56
52
  }
57
53
  }
@@ -7,6 +7,7 @@
7
7
  import { Mark } from "#common/Mark.js";
8
8
  import { SessionManager } from "#session/SessionManager.js";
9
9
  import {
10
+ asError,
10
11
  Bytes,
11
12
  causedBy,
12
13
  Channel,
@@ -124,7 +125,9 @@ export class PaseServer implements ProtocolHandler {
124
125
  logger.info("Received pairing request", Mark.INBOUND, Diagnostic.via(messenger.channelName));
125
126
 
126
127
  this.#pairingTimer = Time.getTimer("PASE pairing timeout", PASE_PAIRING_TIMEOUT, () =>
127
- this.cancelPairing(messenger),
128
+ this.cancelPairing(messenger).catch(error =>
129
+ logger.warn("Error cancelling PASE pairing after timeout:", Diagnostic.errorMessage(asError(error))),
130
+ ),
128
131
  ).start();
129
132
 
130
133
  // Read pbkdfRequest and send pbkdfResponse
@@ -203,7 +206,14 @@ export class PaseServer implements ProtocolHandler {
203
206
 
204
207
  async cancelPairing(messenger: PaseServerMessenger, sendError = true) {
205
208
  if (sendError) {
206
- await messenger.sendError(SecureChannelStatusCode.InvalidParam);
209
+ try {
210
+ await messenger.sendError(SecureChannelStatusCode.InvalidParam);
211
+ } catch (error) {
212
+ logger.info(
213
+ "Could not send pairing-cancellation status report to peer:",
214
+ Diagnostic.errorMessage(asError(error)),
215
+ );
216
+ }
207
217
  }
208
218
  await messenger.close();
209
219
  }