@matter/protocol 0.16.8-alpha.0-20260125-38e62bc3e → 0.16.8-alpha.0-20260127-de48449ad

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 (143) hide show
  1. package/dist/cjs/dcl/DclCertificateService.d.ts.map +1 -1
  2. package/dist/cjs/dcl/DclCertificateService.js +3 -0
  3. package/dist/cjs/dcl/DclCertificateService.js.map +1 -1
  4. package/dist/cjs/dcl/DclOtaUpdateService.d.ts.map +1 -1
  5. package/dist/cjs/dcl/DclOtaUpdateService.js +6 -4
  6. package/dist/cjs/dcl/DclOtaUpdateService.js.map +1 -1
  7. package/dist/cjs/mdns/MdnsClient.d.ts.map +1 -1
  8. package/dist/cjs/mdns/MdnsClient.js +6 -2
  9. package/dist/cjs/mdns/MdnsClient.js.map +1 -1
  10. package/dist/cjs/peer/Peer.d.ts +2 -1
  11. package/dist/cjs/peer/Peer.d.ts.map +1 -1
  12. package/dist/cjs/peer/Peer.js +27 -3
  13. package/dist/cjs/peer/Peer.js.map +1 -1
  14. package/dist/cjs/peer/PeerAddressStore.d.ts +1 -11
  15. package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
  16. package/dist/cjs/peer/PeerAddressStore.js +1 -4
  17. package/dist/cjs/peer/PeerAddressStore.js.map +1 -1
  18. package/dist/cjs/peer/PeerDescriptor.d.ts +1 -9
  19. package/dist/cjs/peer/PeerDescriptor.d.ts.map +1 -1
  20. package/dist/cjs/peer/PeerDescriptor.js +1 -6
  21. package/dist/cjs/peer/PeerDescriptor.js.map +1 -1
  22. package/dist/cjs/peer/PeerSet.d.ts +1 -1
  23. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  24. package/dist/cjs/peer/PeerSet.js +55 -22
  25. package/dist/cjs/peer/PeerSet.js.map +2 -2
  26. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  27. package/dist/cjs/protocol/ExchangeManager.js +5 -2
  28. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  29. package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
  30. package/dist/cjs/protocol/ExchangeProvider.js +3 -3
  31. package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
  32. package/dist/cjs/protocol/MRP.d.ts +54 -0
  33. package/dist/cjs/protocol/MRP.d.ts.map +1 -0
  34. package/dist/cjs/protocol/MRP.js +96 -0
  35. package/dist/cjs/protocol/MRP.js.map +6 -0
  36. package/dist/cjs/protocol/MessageChannel.d.ts +11 -26
  37. package/dist/cjs/protocol/MessageChannel.d.ts.map +1 -1
  38. package/dist/cjs/protocol/MessageChannel.js +52 -55
  39. package/dist/cjs/protocol/MessageChannel.js.map +2 -2
  40. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  41. package/dist/cjs/protocol/MessageExchange.js +7 -7
  42. package/dist/cjs/protocol/MessageExchange.js.map +1 -1
  43. package/dist/cjs/protocol/ProtocolMocks.d.ts +2 -1
  44. package/dist/cjs/protocol/ProtocolMocks.d.ts.map +1 -1
  45. package/dist/cjs/protocol/ProtocolMocks.js +1 -0
  46. package/dist/cjs/protocol/ProtocolMocks.js.map +1 -1
  47. package/dist/cjs/protocol/index.d.ts +1 -0
  48. package/dist/cjs/protocol/index.d.ts.map +1 -1
  49. package/dist/cjs/protocol/index.js +1 -0
  50. package/dist/cjs/protocol/index.js.map +1 -1
  51. package/dist/cjs/session/NodeSession.js +2 -2
  52. package/dist/cjs/session/NodeSession.js.map +1 -1
  53. package/dist/cjs/session/Session.d.ts +2 -4
  54. package/dist/cjs/session/Session.d.ts.map +1 -1
  55. package/dist/cjs/session/Session.js +1 -4
  56. package/dist/cjs/session/Session.js.map +1 -1
  57. package/dist/cjs/session/case/CaseClient.d.ts.map +1 -1
  58. package/dist/cjs/session/case/CaseClient.js +1 -1
  59. package/dist/cjs/session/case/CaseClient.js.map +1 -1
  60. package/dist/cjs/session/case/CaseServer.d.ts.map +1 -1
  61. package/dist/cjs/session/case/CaseServer.js +4 -1
  62. package/dist/cjs/session/case/CaseServer.js.map +1 -1
  63. package/dist/esm/dcl/DclCertificateService.d.ts.map +1 -1
  64. package/dist/esm/dcl/DclCertificateService.js +3 -0
  65. package/dist/esm/dcl/DclCertificateService.js.map +1 -1
  66. package/dist/esm/dcl/DclOtaUpdateService.d.ts.map +1 -1
  67. package/dist/esm/dcl/DclOtaUpdateService.js +6 -4
  68. package/dist/esm/dcl/DclOtaUpdateService.js.map +1 -1
  69. package/dist/esm/mdns/MdnsClient.d.ts.map +1 -1
  70. package/dist/esm/mdns/MdnsClient.js +6 -2
  71. package/dist/esm/mdns/MdnsClient.js.map +1 -1
  72. package/dist/esm/peer/Peer.d.ts +2 -1
  73. package/dist/esm/peer/Peer.d.ts.map +1 -1
  74. package/dist/esm/peer/Peer.js +27 -3
  75. package/dist/esm/peer/Peer.js.map +1 -1
  76. package/dist/esm/peer/PeerAddressStore.d.ts +1 -11
  77. package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
  78. package/dist/esm/peer/PeerAddressStore.js +1 -4
  79. package/dist/esm/peer/PeerAddressStore.js.map +1 -1
  80. package/dist/esm/peer/PeerDescriptor.d.ts +1 -9
  81. package/dist/esm/peer/PeerDescriptor.d.ts.map +1 -1
  82. package/dist/esm/peer/PeerDescriptor.js +1 -6
  83. package/dist/esm/peer/PeerDescriptor.js.map +1 -1
  84. package/dist/esm/peer/PeerSet.d.ts +1 -1
  85. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  86. package/dist/esm/peer/PeerSet.js +60 -24
  87. package/dist/esm/peer/PeerSet.js.map +2 -2
  88. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  89. package/dist/esm/protocol/ExchangeManager.js +6 -3
  90. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  91. package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
  92. package/dist/esm/protocol/ExchangeProvider.js +3 -3
  93. package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
  94. package/dist/esm/protocol/MRP.d.ts +54 -0
  95. package/dist/esm/protocol/MRP.d.ts.map +1 -0
  96. package/dist/esm/protocol/MRP.js +76 -0
  97. package/dist/esm/protocol/MRP.js.map +6 -0
  98. package/dist/esm/protocol/MessageChannel.d.ts +11 -26
  99. package/dist/esm/protocol/MessageChannel.d.ts.map +1 -1
  100. package/dist/esm/protocol/MessageChannel.js +55 -58
  101. package/dist/esm/protocol/MessageChannel.js.map +2 -2
  102. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  103. package/dist/esm/protocol/MessageExchange.js +3 -3
  104. package/dist/esm/protocol/MessageExchange.js.map +1 -1
  105. package/dist/esm/protocol/ProtocolMocks.d.ts +2 -1
  106. package/dist/esm/protocol/ProtocolMocks.d.ts.map +1 -1
  107. package/dist/esm/protocol/ProtocolMocks.js +1 -0
  108. package/dist/esm/protocol/ProtocolMocks.js.map +1 -1
  109. package/dist/esm/protocol/index.d.ts +1 -0
  110. package/dist/esm/protocol/index.d.ts.map +1 -1
  111. package/dist/esm/protocol/index.js +1 -0
  112. package/dist/esm/protocol/index.js.map +1 -1
  113. package/dist/esm/session/NodeSession.js +2 -2
  114. package/dist/esm/session/NodeSession.js.map +1 -1
  115. package/dist/esm/session/Session.d.ts +2 -4
  116. package/dist/esm/session/Session.d.ts.map +1 -1
  117. package/dist/esm/session/Session.js +1 -4
  118. package/dist/esm/session/Session.js.map +1 -1
  119. package/dist/esm/session/case/CaseClient.d.ts.map +1 -1
  120. package/dist/esm/session/case/CaseClient.js +2 -2
  121. package/dist/esm/session/case/CaseClient.js.map +1 -1
  122. package/dist/esm/session/case/CaseServer.d.ts.map +1 -1
  123. package/dist/esm/session/case/CaseServer.js +4 -1
  124. package/dist/esm/session/case/CaseServer.js.map +1 -1
  125. package/package.json +6 -6
  126. package/src/dcl/DclCertificateService.ts +3 -0
  127. package/src/dcl/DclOtaUpdateService.ts +11 -5
  128. package/src/mdns/MdnsClient.ts +9 -2
  129. package/src/peer/Peer.ts +37 -5
  130. package/src/peer/PeerAddressStore.ts +1 -19
  131. package/src/peer/PeerDescriptor.ts +1 -15
  132. package/src/peer/PeerSet.ts +82 -35
  133. package/src/protocol/ExchangeManager.ts +15 -3
  134. package/src/protocol/ExchangeProvider.ts +3 -3
  135. package/src/protocol/MRP.ts +146 -0
  136. package/src/protocol/MessageChannel.ts +66 -100
  137. package/src/protocol/MessageExchange.ts +4 -3
  138. package/src/protocol/ProtocolMocks.ts +1 -0
  139. package/src/protocol/index.ts +1 -0
  140. package/src/session/NodeSession.ts +3 -3
  141. package/src/session/Session.ts +2 -4
  142. package/src/session/case/CaseClient.ts +8 -2
  143. package/src/session/case/CaseServer.ts +4 -0
@@ -12,64 +12,38 @@ import {
12
12
  Diagnostic,
13
13
  Duration,
14
14
  IpNetworkChannel,
15
+ isIpNetworkChannel,
15
16
  Logger,
16
- MatterFlowError,
17
17
  MaybePromise,
18
- Millis,
19
- Seconds,
18
+ ObservableValue,
19
+ sameIpNetworkChannel,
20
+ ServerAddressUdp,
20
21
  } from "#general";
21
22
  import type { ExchangeLogContext } from "#protocol/MessageExchange.js";
22
23
  import type { Session } from "#session/Session.js";
23
24
  import type { SessionParameters } from "#session/SessionParameters.js";
25
+ import { MRP } from "./MRP.js";
24
26
 
25
27
  const logger = new Logger("MessageChannel");
26
28
 
27
- /**
28
- * Default expected processing time for a messages in milliseconds. The value is derived from kExpectedIMProcessingTime
29
- * from chip implementation. This is basically the default used with different names, also kExpectedLowProcessingTime or
30
- * kExpectedSigma1ProcessingTime.
31
- */
32
- export const DEFAULT_EXPECTED_PROCESSING_TIME = Seconds(2);
33
-
34
- /**
35
- * The buffer time in milliseconds to add to the peer response time to also consider network delays and other factors.
36
- * TODO: This is a pure guess and should be adjusted in the future.
37
- */
38
- const PEER_RESPONSE_TIME_BUFFER = Seconds(5);
39
-
40
- export namespace MRP {
41
- /**
42
- * The maximum number of transmission attempts for a given reliable message. The sender MAY choose this value as it
43
- * sees fit.
44
- */
45
- export const MAX_TRANSMISSIONS = 5;
46
-
47
- /** The base number for the exponential backoff equation. */
48
- export const BACKOFF_BASE = 1.6;
49
-
50
- /** The scaler for random jitter in the backoff equation. */
51
- export const BACKOFF_JITTER = 0.25;
52
-
53
- /** The scaler margin increase to backoff over the peer sleepy interval. */
54
- export const BACKOFF_MARGIN = 1.1;
55
-
56
- /** The number of retransmissions before transitioning from linear to exponential backoff. */
57
- export const BACKOFF_THRESHOLD = 1;
58
-
59
- /** @see {@link MatterSpecification.v12.Core}, section 4.11.8 */
60
- export const STANDALONE_ACK_TIMEOUT = Millis(200);
61
- }
62
-
63
29
  export class MessageChannel implements Channel<Message> {
30
+ #channel: Channel<Bytes>;
31
+ #networkAddress = ObservableValue<[ServerAddressUdp]>();
32
+ #isIpNetworkChannel = false;
64
33
  public closed = false;
65
34
  #onClose?: () => MaybePromise<void>;
66
35
  // When the session is supporting MRP and the channel is not reliable, use MRP handling
67
36
 
68
37
  constructor(
69
- readonly channel: Channel<Bytes>,
38
+ channel: Channel<Bytes>,
70
39
  readonly session: Session,
71
40
  onClose?: () => MaybePromise<void>,
72
41
  ) {
42
+ this.#channel = channel;
43
+ if (isIpNetworkChannel(channel)) {
44
+ this.#isIpNetworkChannel = true;
45
+ this.#networkAddress.emit(channel.networkAddress);
46
+ }
73
47
  this.#onClose = onClose;
74
48
  }
75
49
 
@@ -79,7 +53,7 @@ export class MessageChannel implements Channel<Message> {
79
53
 
80
54
  /** Is the underlying transport reliable? */
81
55
  get isReliable() {
82
- return this.channel.isReliable;
56
+ return this.#channel.isReliable;
83
57
  }
84
58
 
85
59
  /**
@@ -91,7 +65,7 @@ export class MessageChannel implements Channel<Message> {
91
65
  }
92
66
 
93
67
  get type() {
94
- return this.channel.type;
68
+ return this.#channel.type;
95
69
  }
96
70
 
97
71
  /**
@@ -99,7 +73,7 @@ export class MessageChannel implements Channel<Message> {
99
73
  * message payload sent here can be as huge as allowed by the channel.
100
74
  */
101
75
  get maxPayloadSize() {
102
- return this.channel.maxPayloadSize;
76
+ return this.#channel.maxPayloadSize;
103
77
  }
104
78
 
105
79
  async send(message: Message, logContext?: ExchangeLogContext) {
@@ -112,21 +86,52 @@ export class MessageChannel implements Channel<Message> {
112
86
  );
113
87
  }
114
88
 
115
- return await this.channel.send(bytes);
89
+ return await this.#channel.send(bytes);
116
90
  }
117
91
 
118
92
  get name() {
119
- return Diagnostic.via(`${this.session.via}@${this.channel.name}`);
93
+ return Diagnostic.via(`${this.session.via}@${this.#channel.name}`);
120
94
  }
121
95
 
122
96
  get networkAddress() {
123
- return (this.channel as IpNetworkChannel<Bytes> | undefined)?.networkAddress;
97
+ return this.#networkAddress.value;
98
+ }
99
+
100
+ get networkAddressChanged() {
101
+ return this.#networkAddress;
102
+ }
103
+
104
+ get channel() {
105
+ return this.#channel;
106
+ }
107
+
108
+ /**
109
+ * Sync the addresses for IP network channels and replace channel if the IPs change
110
+ * If the channel is on a non ip network then the call is basically ignored
111
+ * We already use a new naming here which will be more used in future, so yes inconsistency in naming is ok for now
112
+ * TODO refactor this out again and remove the address from the channel
113
+ */
114
+ set socket(channel: Channel<Bytes>) {
115
+ if (
116
+ this.closed ||
117
+ !this.#isIpNetworkChannel ||
118
+ !isIpNetworkChannel(channel) ||
119
+ channel.type !== "udp" ||
120
+ this.#channel.type !== "udp"
121
+ ) {
122
+ return;
123
+ }
124
+ if (!sameIpNetworkChannel(channel, this.#channel as IpNetworkChannel<Bytes>)) {
125
+ logger.debug(`Updated address to`, this.name);
126
+ this.#channel = channel;
127
+ this.#networkAddress.emit(channel.networkAddress);
128
+ }
124
129
  }
125
130
 
126
131
  async close() {
127
132
  const wasAlreadyClosed = this.closed;
128
133
  this.closed = true;
129
- await this.channel.close();
134
+ await this.#channel.close();
130
135
  if (!wasAlreadyClosed) {
131
136
  await this.#onClose?.();
132
137
  }
@@ -135,35 +140,16 @@ export class MessageChannel implements Channel<Message> {
135
140
  calculateMaximumPeerResponseTime(
136
141
  peerSessionParameters: SessionParameters,
137
142
  localSessionParameters: SessionParameters,
138
- expectedProcessingTime = DEFAULT_EXPECTED_PROCESSING_TIME,
143
+ expectedProcessingTime?: Duration,
139
144
  ): Duration {
140
- switch (this.channel.type) {
141
- case "tcp":
142
- // TCP uses 30s timeout according to chip sdk implementation, so do the same
143
- return Millis(Seconds(30) + PEER_RESPONSE_TIME_BUFFER);
144
-
145
- case "udp":
146
- // UDP normally uses MRP, if not we have Group communication, which normally have no responses
147
- if (!this.session.usesMrp) {
148
- throw new MatterFlowError("No response expected for this message exchange because UDP and no MRP.");
149
- }
150
- // Calculate the maximum time till the peer got our last retry and worst case for the way back
151
- return Millis(
152
- this.#calculateMrpMaximumPeerResponseTime(peerSessionParameters) +
153
- this.#calculateMrpMaximumPeerResponseTime(localSessionParameters) +
154
- expectedProcessingTime +
155
- PEER_RESPONSE_TIME_BUFFER,
156
- );
157
-
158
- case "ble":
159
- // chip sdk uses BTP_ACK_TIMEOUT_MS which is wrong in my eyes, so we use static 30s as like TCP here
160
- return Millis(Seconds(30) + PEER_RESPONSE_TIME_BUFFER);
161
-
162
- default:
163
- throw new MatterFlowError(
164
- `Can not calculate expected timeout for unknown channel type: ${this.channel.type}`,
165
- );
166
- }
145
+ return MRP.maxPeerResponseTimeOf({
146
+ peerSessionParameters,
147
+ localSessionParameters,
148
+ channelType: this.#channel.type,
149
+ isPeerActive: this.session.isPeerActive,
150
+ usesMrp: this.session.usesMrp,
151
+ expectedProcessingTime,
152
+ });
167
153
  }
168
154
 
169
155
  /**
@@ -175,30 +161,10 @@ export class MessageChannel implements Channel<Message> {
175
161
  * @see {@link MatterSpecification.v10.Core}, section 4.11.2.1
176
162
  */
177
163
  getMrpResubmissionBackOffTime(retransmissionCount: number, sessionParameters?: SessionParameters) {
178
- const { activeInterval, idleInterval } = sessionParameters ?? this.session.parameters;
179
- // For the first message of a new exchange ... SHALL be set according to the idle state of the peer node.
180
- // For all subsequent messages of the exchange, ... SHOULD be set according to the active state of the peer node
181
- const peerActive = retransmissionCount > 0 && (sessionParameters !== undefined || this.session.isPeerActive);
182
- const baseInterval = peerActive ? activeInterval : idleInterval;
183
- return Millis.floor(
184
- Millis(
185
- baseInterval *
186
- MRP.BACKOFF_MARGIN *
187
- Math.pow(MRP.BACKOFF_BASE, Math.max(0, retransmissionCount - MRP.BACKOFF_THRESHOLD)) *
188
- (1 + (sessionParameters !== undefined ? 1 : Math.random()) * MRP.BACKOFF_JITTER),
189
- ),
190
- );
191
- }
192
-
193
- /** Calculates the maximum time the peer might take to respond when using MRP for one direction. */
194
- #calculateMrpMaximumPeerResponseTime(sessionParameters: SessionParameters) {
195
- let finalWaitTime = 0;
196
-
197
- // and then add the time the other side needs for a full resubmission cycle under the assumption we are active
198
- for (let i = 0; i < MRP.MAX_TRANSMISSIONS; i++) {
199
- finalWaitTime = Millis(finalWaitTime + this.getMrpResubmissionBackOffTime(i, sessionParameters));
200
- }
201
-
202
- return finalWaitTime;
164
+ return MRP.maxRetransmissionIntervalOf({
165
+ transmissionNumber: retransmissionCount,
166
+ sessionParameters: sessionParameters ?? this.session.parameters,
167
+ isPeerActive: this.session.isPeerActive,
168
+ });
203
169
  }
204
170
  }
@@ -37,7 +37,8 @@ import {
37
37
  StatusResponseError,
38
38
  } from "#types";
39
39
  import { RetransmissionLimitReachedError, SessionClosedError, UnexpectedMessageError } from "./errors.js";
40
- import { DEFAULT_EXPECTED_PROCESSING_TIME, MessageChannel, MRP } from "./MessageChannel.js";
40
+ import { MessageChannel } from "./MessageChannel.js";
41
+ import { MRP } from "./MRP.js";
41
42
 
42
43
  const logger = Logger.get("MessageExchange");
43
44
 
@@ -311,7 +312,7 @@ export class MessageExchange {
311
312
  // Ignore if this is a standalone ack, probably this was a retransmission.
312
313
  } else {
313
314
  throw new MatterFlowError(
314
- `Incorrect ack received. Expected ${sentMessageIdToAck}, received: ${ackedMessageId}`,
315
+ `Incorrect ack received. Expected ${hex.fixed(sentMessageIdToAck, 8)}, received: ${hex.fixed(ackedMessageId, 8)}`,
315
316
  );
316
317
  }
317
318
  } else {
@@ -349,7 +350,7 @@ export class MessageExchange {
349
350
  const {
350
351
  expectAckOnly = false,
351
352
  disableMrpLogic,
352
- expectedProcessingTime = DEFAULT_EXPECTED_PROCESSING_TIME,
353
+ expectedProcessingTime = MRP.DEFAULT_EXPECTED_PROCESSING_TIME,
353
354
  includeAcknowledgeMessageId,
354
355
  logContext,
355
356
  protocolId = this.#protocolId,
@@ -162,6 +162,7 @@ export namespace ProtocolMocks {
162
162
  name = "mock-byte-channel";
163
163
  type = ChannelType.UDP;
164
164
  networkAddress: ServerAddressUdp;
165
+ networkAddressChanged = new Observable<[ServerAddressUdp]>();
165
166
 
166
167
  constructor(config: MockNetworkConfig) {
167
168
  const index = config.index ?? 1;
@@ -13,6 +13,7 @@ export * from "./MessageChannel.js";
13
13
  export * from "./MessageCounter.js";
14
14
  export * from "./MessageExchange.js";
15
15
  export * from "./MessageReceptionState.js";
16
+ export * from "./MRP.js";
16
17
  export * from "./ProtocolHandler.js";
17
18
  export * from "./ProtocolMocks.js";
18
19
  export * from "./ProtocolStatusMessage.js";
@@ -125,14 +125,14 @@ export class NodeSession extends SecureSession {
125
125
  this.#caseAuthenticatedTags = caseAuthenticatedTags ?? [];
126
126
  this.#isInitiator = isInitiator;
127
127
 
128
- manager?.sessions.add(this);
129
- fabric?.addSession(this);
130
-
131
128
  logger.debug(
132
129
  `Created secure ${this.isPase ? "PASE" : "CASE"} session for fabric index ${fabric?.fabricIndex}`,
133
130
  this.via,
134
131
  this.parameterDiagnostics,
135
132
  );
133
+
134
+ manager?.sessions.add(this);
135
+ fabric?.addSession(this);
136
136
  }
137
137
 
138
138
  get parameterDiagnostics() {
@@ -338,9 +338,6 @@ export abstract class Session {
338
338
  return this.#manager;
339
339
  }
340
340
 
341
- /**
342
- * This is primarily intended for testing.
343
- */
344
341
  protected set channel(channel: MessageChannel) {
345
342
  if (this.#channel !== undefined) {
346
343
  throw new ImplementationError("Cannot replace active channel");
@@ -353,7 +350,7 @@ export abstract class Session {
353
350
  }
354
351
 
355
352
  /**
356
- * Invoked by manager when the session is "live".
353
+ * Invoked by the manager when the session is "live".
357
354
  *
358
355
  * This is separate from construction because we sometimes discard sessions without installing in a manager or
359
356
  * closing.
@@ -374,6 +371,7 @@ export abstract class Session {
374
371
  export namespace Session {
375
372
  export interface CommonConfig {
376
373
  manager?: SessionManager;
374
+ delayManagerRegistration?: true;
377
375
  channel?: Channel<Bytes>;
378
376
  }
379
377
 
@@ -7,7 +7,7 @@
7
7
  import { Icac } from "#certificate/kinds/Icac.js";
8
8
  import { Noc } from "#certificate/kinds/Noc.js";
9
9
  import { Fabric } from "#fabric/Fabric.js";
10
- import { Bytes, Duration, EcdsaSignature, Logger, PublicKey, UnexpectedDataError } from "#general";
10
+ import { AbortedError, Bytes, Duration, EcdsaSignature, Logger, PublicKey, UnexpectedDataError } from "#general";
11
11
  import { MessageExchange } from "#protocol/MessageExchange.js";
12
12
  import { RetransmissionLimitReachedError } from "#protocol/errors.js";
13
13
  import { ChannelStatusResponseError } from "#securechannel/SecureChannelMessenger.js";
@@ -45,7 +45,13 @@ export class CaseClient {
45
45
  try {
46
46
  return await this.#doPair(messenger, exchange, fabric, peerNodeId, caseAuthenticatedTags);
47
47
  } catch (error) {
48
- if (!(error instanceof ChannelStatusResponseError || error instanceof RetransmissionLimitReachedError)) {
48
+ if (
49
+ !(
50
+ error instanceof ChannelStatusResponseError ||
51
+ error instanceof RetransmissionLimitReachedError ||
52
+ error instanceof AbortedError
53
+ )
54
+ ) {
49
55
  await messenger.sendError(SecureChannelStatusCode.InvalidParam);
50
56
  }
51
57
  throw error;
@@ -153,6 +153,7 @@ export class CaseServer implements ProtocolHandler {
153
153
  isResumption: true,
154
154
  peerSessionParameters: cx.peerSessionParams,
155
155
  caseAuthenticatedTags,
156
+ delayManagerRegistration: true, // Session establishment could still fail, so add session ourselves to the manager
156
157
  });
157
158
 
158
159
  // Generate sigma 2 resume
@@ -173,8 +174,11 @@ export class CaseServer implements ProtocolHandler {
173
174
  throw error;
174
175
  }
175
176
 
177
+ // Now we are sure, add the session to the manager
176
178
  NodeSession.logNew(logger, "Resumed", secureSession, cx.messenger, fabric, peerNodeId);
177
179
 
180
+ this.#sessions.sessions.add(secureSession);
181
+
178
182
  cx.resumptionRecord.resumptionId = cx.localResumptionId; /* Update the ID */
179
183
 
180
184
  // Wait for success on the peer side