@matter/protocol 0.16.0-alpha.0-20251001-7eb06da95 → 0.16.0-alpha.0-20251004-92135c7df

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 (191) 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/ble/Ble.d.ts +3 -3
  6. package/dist/cjs/ble/Ble.d.ts.map +1 -1
  7. package/dist/cjs/ble/Ble.js.map +1 -1
  8. package/dist/cjs/common/Scanner.d.ts +2 -2
  9. package/dist/cjs/common/Scanner.d.ts.map +1 -1
  10. package/dist/cjs/interaction/AttributeDataDecoder.d.ts +9 -7
  11. package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
  12. package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
  13. package/dist/cjs/interaction/DecodedDataReport.d.ts +1 -0
  14. package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
  15. package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
  16. package/dist/cjs/interaction/InteractionClient.d.ts +13 -3
  17. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  18. package/dist/cjs/interaction/InteractionClient.js +94 -67
  19. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  20. package/dist/cjs/interaction/InteractionMessenger.d.ts +10 -90
  21. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  22. package/dist/cjs/interaction/InteractionMessenger.js +98 -22
  23. package/dist/cjs/interaction/InteractionMessenger.js.map +2 -2
  24. package/dist/cjs/interaction/SubscriptionClient.d.ts +2 -2
  25. package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -1
  26. package/dist/cjs/interaction/SubscriptionClient.js +1 -1
  27. package/dist/cjs/interaction/SubscriptionClient.js.map +1 -1
  28. package/dist/cjs/mdns/MdnsClient.d.ts +3 -3
  29. package/dist/cjs/mdns/MdnsClient.d.ts.map +1 -1
  30. package/dist/cjs/mdns/MdnsClient.js +28 -14
  31. package/dist/cjs/mdns/MdnsClient.js.map +1 -1
  32. package/dist/cjs/mdns/MdnsServer.d.ts.map +1 -1
  33. package/dist/cjs/mdns/MdnsServer.js +59 -5
  34. package/dist/cjs/mdns/MdnsServer.js.map +1 -1
  35. package/dist/cjs/mdns/MdnsSocket.d.ts.map +1 -1
  36. package/dist/cjs/mdns/MdnsSocket.js +10 -1
  37. package/dist/cjs/mdns/MdnsSocket.js.map +1 -1
  38. package/dist/cjs/peer/ControllerCommissioner.d.ts +2 -2
  39. package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
  40. package/dist/cjs/peer/ControllerCommissioner.js +7 -5
  41. package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
  42. package/dist/cjs/peer/OperationalPeer.d.ts +2 -2
  43. package/dist/cjs/peer/OperationalPeer.d.ts.map +1 -1
  44. package/dist/cjs/peer/PeerAddressStore.d.ts +3 -1
  45. package/dist/cjs/peer/PeerAddressStore.d.ts.map +1 -1
  46. package/dist/cjs/peer/PeerAddressStore.js.map +1 -1
  47. package/dist/cjs/peer/PeerSet.d.ts +3 -3
  48. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  49. package/dist/cjs/peer/PeerSet.js +14 -9
  50. package/dist/cjs/peer/PeerSet.js.map +1 -1
  51. package/dist/cjs/protocol/ExchangeManager.d.ts +2 -2
  52. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  53. package/dist/cjs/protocol/ExchangeManager.js +21 -17
  54. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  55. package/dist/cjs/protocol/MessageChannel.d.ts +1 -1
  56. package/dist/cjs/protocol/MessageChannel.d.ts.map +1 -1
  57. package/dist/cjs/protocol/MessageChannel.js +7 -5
  58. package/dist/cjs/protocol/MessageChannel.js.map +1 -1
  59. package/dist/cjs/protocol/MessageExchange.d.ts +0 -1
  60. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  61. package/dist/cjs/protocol/MessageExchange.js +6 -17
  62. package/dist/cjs/protocol/MessageExchange.js.map +1 -1
  63. package/dist/cjs/session/NodeSession.d.ts.map +1 -1
  64. package/dist/cjs/session/NodeSession.js +3 -3
  65. package/dist/cjs/session/NodeSession.js.map +1 -1
  66. package/dist/cjs/session/SessionIntervals.d.ts +1 -5
  67. package/dist/cjs/session/SessionIntervals.d.ts.map +1 -1
  68. package/dist/cjs/session/SessionIntervals.js.map +1 -1
  69. package/dist/cjs/session/case/CaseMessages.d.ts +18 -9
  70. package/dist/cjs/session/case/CaseMessages.d.ts.map +1 -1
  71. package/dist/cjs/session/case/CaseMessages.js.map +1 -1
  72. package/dist/cjs/session/case/CaseMessenger.d.ts +4 -62
  73. package/dist/cjs/session/case/CaseMessenger.d.ts.map +1 -1
  74. package/dist/cjs/session/case/CaseMessenger.js.map +1 -1
  75. package/dist/cjs/session/case/CaseServer.js.map +1 -1
  76. package/dist/cjs/session/pase/PaseMessages.d.ts +20 -9
  77. package/dist/cjs/session/pase/PaseMessages.d.ts.map +1 -1
  78. package/dist/cjs/session/pase/PaseMessages.js +3 -3
  79. package/dist/cjs/session/pase/PaseMessages.js.map +1 -1
  80. package/dist/cjs/session/pase/PaseMessenger.d.ts +3 -51
  81. package/dist/cjs/session/pase/PaseMessenger.d.ts.map +1 -1
  82. package/dist/cjs/session/pase/PaseMessenger.js.map +1 -1
  83. package/dist/esm/action/client/ReadScope.d.ts +4 -0
  84. package/dist/esm/action/client/ReadScope.d.ts.map +1 -1
  85. package/dist/esm/action/client/ReadScope.js +2 -1
  86. package/dist/esm/action/client/ReadScope.js.map +1 -1
  87. package/dist/esm/ble/Ble.d.ts +3 -3
  88. package/dist/esm/ble/Ble.d.ts.map +1 -1
  89. package/dist/esm/ble/Ble.js.map +1 -1
  90. package/dist/esm/common/Scanner.d.ts +2 -2
  91. package/dist/esm/common/Scanner.d.ts.map +1 -1
  92. package/dist/esm/interaction/AttributeDataDecoder.d.ts +9 -7
  93. package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
  94. package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
  95. package/dist/esm/interaction/DecodedDataReport.d.ts +1 -0
  96. package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
  97. package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
  98. package/dist/esm/interaction/InteractionClient.d.ts +13 -3
  99. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  100. package/dist/esm/interaction/InteractionClient.js +96 -68
  101. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  102. package/dist/esm/interaction/InteractionMessenger.d.ts +10 -90
  103. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  104. package/dist/esm/interaction/InteractionMessenger.js +98 -22
  105. package/dist/esm/interaction/InteractionMessenger.js.map +2 -2
  106. package/dist/esm/interaction/SubscriptionClient.d.ts +2 -2
  107. package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -1
  108. package/dist/esm/interaction/SubscriptionClient.js +1 -1
  109. package/dist/esm/interaction/SubscriptionClient.js.map +1 -1
  110. package/dist/esm/mdns/MdnsClient.d.ts +3 -3
  111. package/dist/esm/mdns/MdnsClient.d.ts.map +1 -1
  112. package/dist/esm/mdns/MdnsClient.js +28 -14
  113. package/dist/esm/mdns/MdnsClient.js.map +1 -1
  114. package/dist/esm/mdns/MdnsServer.d.ts.map +1 -1
  115. package/dist/esm/mdns/MdnsServer.js +60 -5
  116. package/dist/esm/mdns/MdnsServer.js.map +1 -1
  117. package/dist/esm/mdns/MdnsSocket.d.ts.map +1 -1
  118. package/dist/esm/mdns/MdnsSocket.js +12 -1
  119. package/dist/esm/mdns/MdnsSocket.js.map +1 -1
  120. package/dist/esm/peer/ControllerCommissioner.d.ts +2 -2
  121. package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
  122. package/dist/esm/peer/ControllerCommissioner.js +9 -6
  123. package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
  124. package/dist/esm/peer/OperationalPeer.d.ts +2 -2
  125. package/dist/esm/peer/OperationalPeer.d.ts.map +1 -1
  126. package/dist/esm/peer/PeerAddressStore.d.ts +3 -1
  127. package/dist/esm/peer/PeerAddressStore.d.ts.map +1 -1
  128. package/dist/esm/peer/PeerAddressStore.js.map +1 -1
  129. package/dist/esm/peer/PeerSet.d.ts +3 -3
  130. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  131. package/dist/esm/peer/PeerSet.js +15 -10
  132. package/dist/esm/peer/PeerSet.js.map +1 -1
  133. package/dist/esm/protocol/ExchangeManager.d.ts +2 -2
  134. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  135. package/dist/esm/protocol/ExchangeManager.js +22 -18
  136. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  137. package/dist/esm/protocol/MessageChannel.d.ts +1 -1
  138. package/dist/esm/protocol/MessageChannel.d.ts.map +1 -1
  139. package/dist/esm/protocol/MessageChannel.js +7 -5
  140. package/dist/esm/protocol/MessageChannel.js.map +1 -1
  141. package/dist/esm/protocol/MessageExchange.d.ts +0 -1
  142. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  143. package/dist/esm/protocol/MessageExchange.js +6 -17
  144. package/dist/esm/protocol/MessageExchange.js.map +1 -1
  145. package/dist/esm/session/NodeSession.d.ts.map +1 -1
  146. package/dist/esm/session/NodeSession.js +4 -3
  147. package/dist/esm/session/NodeSession.js.map +1 -1
  148. package/dist/esm/session/SessionIntervals.d.ts +1 -5
  149. package/dist/esm/session/SessionIntervals.d.ts.map +1 -1
  150. package/dist/esm/session/SessionIntervals.js.map +1 -1
  151. package/dist/esm/session/case/CaseMessages.d.ts +18 -9
  152. package/dist/esm/session/case/CaseMessages.d.ts.map +1 -1
  153. package/dist/esm/session/case/CaseMessages.js.map +1 -1
  154. package/dist/esm/session/case/CaseMessenger.d.ts +4 -62
  155. package/dist/esm/session/case/CaseMessenger.d.ts.map +1 -1
  156. package/dist/esm/session/case/CaseMessenger.js +6 -1
  157. package/dist/esm/session/case/CaseMessenger.js.map +1 -1
  158. package/dist/esm/session/case/CaseServer.js.map +1 -1
  159. package/dist/esm/session/pase/PaseMessages.d.ts +20 -9
  160. package/dist/esm/session/pase/PaseMessages.d.ts.map +1 -1
  161. package/dist/esm/session/pase/PaseMessages.js +3 -3
  162. package/dist/esm/session/pase/PaseMessages.js.map +1 -1
  163. package/dist/esm/session/pase/PaseMessenger.d.ts +3 -51
  164. package/dist/esm/session/pase/PaseMessenger.d.ts.map +1 -1
  165. package/dist/esm/session/pase/PaseMessenger.js.map +1 -1
  166. package/package.json +6 -6
  167. package/src/action/client/ReadScope.ts +7 -0
  168. package/src/ble/Ble.ts +3 -3
  169. package/src/common/Scanner.ts +2 -2
  170. package/src/interaction/AttributeDataDecoder.ts +4 -1
  171. package/src/interaction/DecodedDataReport.ts +1 -0
  172. package/src/interaction/InteractionClient.ts +154 -79
  173. package/src/interaction/InteractionMessenger.ts +126 -22
  174. package/src/interaction/SubscriptionClient.ts +6 -5
  175. package/src/mdns/MdnsClient.ts +33 -23
  176. package/src/mdns/MdnsServer.ts +75 -5
  177. package/src/mdns/MdnsSocket.ts +16 -1
  178. package/src/peer/ControllerCommissioner.ts +10 -7
  179. package/src/peer/OperationalPeer.ts +2 -2
  180. package/src/peer/PeerAddressStore.ts +3 -1
  181. package/src/peer/PeerSet.ts +23 -18
  182. package/src/protocol/ExchangeManager.ts +29 -21
  183. package/src/protocol/MessageChannel.ts +13 -11
  184. package/src/protocol/MessageExchange.ts +6 -18
  185. package/src/session/NodeSession.ts +4 -3
  186. package/src/session/SessionIntervals.ts +1 -1
  187. package/src/session/case/CaseMessages.ts +12 -2
  188. package/src/session/case/CaseMessenger.ts +12 -4
  189. package/src/session/case/CaseServer.ts +5 -5
  190. package/src/session/pase/PaseMessages.ts +27 -3
  191. package/src/session/pase/PaseMessenger.ts +8 -9
@@ -10,6 +10,7 @@ import {
10
10
  AsyncObservable,
11
11
  BasicSet,
12
12
  ChannelType,
13
+ ConnectionlessTransportSet,
13
14
  Construction,
14
15
  createPromise,
15
16
  Duration,
@@ -22,12 +23,11 @@ import {
22
23
  Logger,
23
24
  MatterError,
24
25
  Minutes,
25
- NetInterfaceSet,
26
26
  NoResponseTimeoutError,
27
27
  ObservableSet,
28
28
  Seconds,
29
29
  ServerAddress,
30
- ServerAddressIp,
30
+ ServerAddressUdp,
31
31
  STANDARD_MATTER_PORT,
32
32
  Time,
33
33
  Timer,
@@ -109,7 +109,7 @@ export interface PeerSetContext {
109
109
  exchanges: ExchangeManager;
110
110
  subscriptionClient: SubscriptionClient;
111
111
  scanners: ScannerSet;
112
- netInterfaces: NetInterfaceSet;
112
+ transports: ConnectionlessTransportSet;
113
113
  store: PeerAddressStore;
114
114
  }
115
115
 
@@ -122,7 +122,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
122
122
  readonly #exchanges: ExchangeManager;
123
123
  readonly #subscriptionClient: SubscriptionClient;
124
124
  readonly #scanners: ScannerSet;
125
- readonly #netInterfaces: NetInterfaceSet;
125
+ readonly #transports: ConnectionlessTransportSet;
126
126
  readonly #caseClient: CaseClient;
127
127
  readonly #peers = new BasicSet<OperationalPeer>();
128
128
  readonly #peersByAddress = new PeerAddressMap<OperationalPeer>();
@@ -138,14 +138,22 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
138
138
  readonly #disconnected = AsyncObservable<[address: PeerAddress]>();
139
139
 
140
140
  constructor(context: PeerSetContext) {
141
- const { sessions, channels, exchanges, subscriptionClient, scanners, netInterfaces, store } = context;
141
+ const {
142
+ sessions,
143
+ channels,
144
+ exchanges,
145
+ subscriptionClient,
146
+ scanners,
147
+ transports: netInterfaces,
148
+ store,
149
+ } = context;
142
150
 
143
151
  this.#sessions = sessions;
144
152
  this.#channels = channels;
145
153
  this.#exchanges = exchanges;
146
154
  this.#subscriptionClient = subscriptionClient;
147
155
  this.#scanners = scanners;
148
- this.#netInterfaces = netInterfaces;
156
+ this.#transports = netInterfaces;
149
157
  this.#store = store;
150
158
  this.#caseClient = new CaseClient(this.#sessions);
151
159
 
@@ -231,7 +239,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
231
239
  exchanges: env.get(ExchangeManager),
232
240
  subscriptionClient: env.get(SubscriptionClient),
233
241
  scanners: env.get(ScannerSet),
234
- netInterfaces: env.get(NetInterfaceSet),
242
+ transports: env.get(ConnectionlessTransportSet),
235
243
  store: env.get(PeerAddressStore),
236
244
  });
237
245
  env.set(PeerSet, instance);
@@ -257,7 +265,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
257
265
  address: PeerAddress,
258
266
  options: PeerConnectionOptions & {
259
267
  allowUnknownPeer?: boolean;
260
- operationalAddress?: ServerAddressIp;
268
+ operationalAddress?: ServerAddressUdp;
261
269
  },
262
270
  ) {
263
271
  address = PeerAddress(address);
@@ -422,7 +430,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
422
430
  * device is discovered again using its operational instance details.
423
431
  * It returns the operational MessageChannel on success.
424
432
  */
425
- async #resume(address: PeerAddress, options: PeerConnectionOptions, tryOperationalAddress?: ServerAddressIp) {
433
+ async #resume(address: PeerAddress, options: PeerConnectionOptions, tryOperationalAddress?: ServerAddressUdp) {
426
434
  const { discoveryOptions: { discoveryType } = {} } = options;
427
435
 
428
436
  const operationalAddress =
@@ -449,7 +457,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
449
457
 
450
458
  async #connectOrDiscoverNode(
451
459
  address: PeerAddress,
452
- operationalAddress?: ServerAddressIp,
460
+ operationalAddress?: ServerAddressUdp,
453
461
  options?: PeerConnectionOptions,
454
462
  ) {
455
463
  address = PeerAddress(address);
@@ -630,7 +638,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
630
638
 
631
639
  async #reconnectKnownAddress(
632
640
  address: PeerAddress,
633
- operationalAddress: ServerAddressIp,
641
+ operationalAddress: ServerAddressUdp,
634
642
  discoveryData?: DiscoveryData,
635
643
  options?: CaseClient.PairOptions,
636
644
  ): Promise<MessageChannel | undefined> {
@@ -670,7 +678,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
670
678
  GroupId.assertGroupId(groupId);
671
679
  const multicastAddress = this.#sessions.fabricFor(address).groups.multicastAddressFor(groupId);
672
680
 
673
- const operationalInterface = this.#netInterfaces.interfaceFor(ChannelType.UDP, multicastAddress);
681
+ const operationalInterface = this.#transports.interfaceFor(ChannelType.UDP, multicastAddress);
674
682
  if (operationalInterface === undefined) {
675
683
  throw new PairRetransmissionLimitReachedError(`IPv6 interface not initialized`);
676
684
  }
@@ -689,7 +697,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
689
697
  /** Pair with an operational device (already commissioned) and establish a CASE session. */
690
698
  async #pair(
691
699
  address: PeerAddress,
692
- operationalServerAddress: ServerAddressIp,
700
+ operationalServerAddress: ServerAddressUdp,
693
701
  discoveryData?: DiscoveryData,
694
702
  options?: CaseClient.PairOptions,
695
703
  ) {
@@ -697,10 +705,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
697
705
  const { ip, port } = operationalServerAddress;
698
706
  // Do CASE pairing
699
707
  const isIpv6Address = isIPv6(ip);
700
- const operationalInterface = this.#netInterfaces.interfaceFor(
701
- ChannelType.UDP,
702
- isIpv6Address ? "::" : "0.0.0.0",
703
- );
708
+ const operationalInterface = this.#transports.interfaceFor(ChannelType.UDP, isIpv6Address ? "::" : "0.0.0.0");
704
709
 
705
710
  if (operationalInterface === undefined) {
706
711
  throw new PairRetransmissionLimitReachedError(
@@ -812,7 +817,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
812
817
 
813
818
  async #addOrUpdatePeer(
814
819
  address: PeerAddress,
815
- operationalServerAddress: ServerAddressIp,
820
+ operationalServerAddress: ServerAddressUdp,
816
821
  discoveryData?: DiscoveryData,
817
822
  ) {
818
823
  let peer = this.#peersByAddress.get(address);
@@ -8,6 +8,8 @@ import { DecodedMessage, MessageCodec, SessionType } from "#codec/MessageCodec.j
8
8
  import {
9
9
  Bytes,
10
10
  Channel,
11
+ ConnectionlessTransport,
12
+ ConnectionlessTransportSet,
11
13
  Crypto,
12
14
  Diagnostic,
13
15
  Environment,
@@ -18,8 +20,6 @@ import {
18
20
  MatterError,
19
21
  MatterFlowError,
20
22
  ObserverGroup,
21
- TransportInterface,
22
- TransportInterfaceSet,
23
23
  UdpInterface,
24
24
  UnexpectedDataError,
25
25
  } from "#general";
@@ -49,35 +49,35 @@ const MAXIMUM_CONCURRENT_EXCHANGES_PER_SESSION = 5;
49
49
  */
50
50
  export interface ExchangeManagerContext {
51
51
  crypto: Crypto;
52
- transportInterfaces: TransportInterfaceSet;
52
+ netInterface: ConnectionlessTransportSet;
53
53
  sessionManager: SessionManager;
54
54
  channelManager: ChannelManager;
55
55
  }
56
56
 
57
57
  export class ExchangeManager {
58
- readonly #transportInterfaces: TransportInterfaceSet;
58
+ readonly #transports: ConnectionlessTransportSet;
59
59
  readonly #sessionManager: SessionManager;
60
60
  readonly #channelManager: ChannelManager;
61
61
  readonly #exchangeCounter: ExchangeCounter;
62
62
  readonly #exchanges = new Map<number, MessageExchange>();
63
63
  readonly #protocols = new Map<number, ProtocolHandler>();
64
- readonly #listeners = new Map<TransportInterface, TransportInterface.Listener>();
64
+ readonly #listeners = new Map<ConnectionlessTransport, ConnectionlessTransport.Listener>();
65
65
  readonly #closers = new Set<Promise<void>>();
66
66
  readonly #observers = new ObserverGroup(this);
67
67
  #closing = false;
68
68
 
69
69
  constructor(context: ExchangeManagerContext) {
70
- this.#transportInterfaces = context.transportInterfaces;
70
+ this.#transports = context.netInterface;
71
71
  this.#sessionManager = context.sessionManager;
72
72
  this.#channelManager = context.channelManager;
73
73
  this.#exchangeCounter = new ExchangeCounter(context.crypto);
74
74
 
75
- for (const transportInterface of this.#transportInterfaces) {
76
- this.#addListener(transportInterface);
75
+ for (const netInterface of this.#transports) {
76
+ this.#addListener(netInterface);
77
77
  }
78
78
 
79
- this.#observers.on(this.#transportInterfaces.added, this.#addListener);
80
- this.#observers.on(this.#transportInterfaces.deleted, this.#deleteListener);
79
+ this.#observers.on(this.#transports.added, this.#addListener);
80
+ this.#observers.on(this.#transports.deleted, this.#deleteListener);
81
81
 
82
82
  this.#observers.on(this.#sessionManager.sessions.deleted, session => {
83
83
  if (!session.closingAfterExchangeFinished) {
@@ -90,7 +90,7 @@ export class ExchangeManager {
90
90
  static [Environmental.create](env: Environment) {
91
91
  const instance = new ExchangeManager({
92
92
  crypto: env.get(Crypto),
93
- transportInterfaces: env.get(TransportInterfaceSet),
93
+ netInterface: env.get(ConnectionlessTransportSet),
94
94
  sessionManager: env.get(SessionManager),
95
95
  channelManager: env.get(ChannelManager),
96
96
  });
@@ -261,7 +261,11 @@ export class ExchangeManager {
261
261
 
262
262
  // Having a "Secure Session" means it is encrypted in our internal working
263
263
  // TODO When adding Group sessions, we need to check how to adjust that handling
264
- if (protocolHandler !== undefined && protocolHandler.requiresSecureSession !== session.isSecure) {
264
+ if (
265
+ protocolHandler !== undefined &&
266
+ protocolHandler.requiresSecureSession !== session.isSecure &&
267
+ !isStandaloneAck
268
+ ) {
265
269
  logger.debug(
266
270
  `Ignoring message ${messageId} for protocol ${message.payloadHeader.protocolId} and exchange id ${message.payloadHeader.exchangeId} on channel ${channel.name} because not matching the security requirements.`,
267
271
  );
@@ -313,7 +317,7 @@ export class ExchangeManager {
313
317
  );
314
318
  }
315
319
  return;
316
- } else {
320
+ } else if (!isStandaloneAck) {
317
321
  logger.info(
318
322
  `Discarding unexpected message ${messageId} for protocol ${
319
323
  message.payloadHeader.protocolId
@@ -416,7 +420,11 @@ export class ExchangeManager {
416
420
  channel: MessageChannel,
417
421
  expectedProcessingTime = DEFAULT_EXPECTED_PROCESSING_TIME,
418
422
  ) {
419
- return channel.calculateMaximumPeerResponseTime(this.#sessionManager.sessionParameters, expectedProcessingTime);
423
+ return channel.calculateMaximumPeerResponseTime(
424
+ channel.session.parameters,
425
+ this.#sessionManager.sessionParameters,
426
+ expectedProcessingTime,
427
+ );
420
428
  }
421
429
 
422
430
  #messageExchangeContextFor(channel: MessageChannel): MessageExchangeContext {
@@ -427,11 +435,11 @@ export class ExchangeManager {
427
435
  };
428
436
  }
429
437
 
430
- #addListener(transportInterface: TransportInterface) {
431
- const udpInterface = transportInterface instanceof UdpInterface;
438
+ #addListener(netInterface: ConnectionlessTransport) {
439
+ const udpInterface = netInterface instanceof UdpInterface;
432
440
  this.#listeners.set(
433
- transportInterface,
434
- transportInterface.onData((socket, data) => {
441
+ netInterface,
442
+ netInterface.onData((socket, data) => {
435
443
  if (udpInterface && data.byteLength > socket.maxPayloadSize) {
436
444
  logger.warn(
437
445
  `Ignoring UDP message on channel ${socket.name} with size ${data.byteLength} from ${socket.name}, which is larger than the maximum allowed size of ${socket.maxPayloadSize}.`,
@@ -456,12 +464,12 @@ export class ExchangeManager {
456
464
  );
457
465
  }
458
466
 
459
- #deleteListener(transportInterface: TransportInterface) {
460
- const listener = this.#listeners.get(transportInterface);
467
+ #deleteListener(netInterface: ConnectionlessTransport) {
468
+ const listener = this.#listeners.get(netInterface);
461
469
  if (listener === undefined) {
462
470
  return;
463
471
  }
464
- this.#listeners.delete(transportInterface);
472
+ this.#listeners.delete(netInterface);
465
473
 
466
474
  const closer = listener
467
475
  .close()
@@ -114,7 +114,8 @@ export class MessageChannel implements Channel<Message> {
114
114
  }
115
115
 
116
116
  calculateMaximumPeerResponseTime(
117
- sessionParameters: SessionParameters,
117
+ peerSessionParameters: SessionParameters,
118
+ localSessionParameters: SessionParameters,
118
119
  expectedProcessingTime = DEFAULT_EXPECTED_PROCESSING_TIME,
119
120
  ): Duration {
120
121
  switch (this.channel.type) {
@@ -127,8 +128,11 @@ export class MessageChannel implements Channel<Message> {
127
128
  if (!this.usesMrp) {
128
129
  throw new MatterFlowError("No response expected for this message exchange because UDP and no MRP.");
129
130
  }
131
+ // Calculate the maximum time till the peer got our last retry and worst case for the way back
130
132
  return Millis(
131
- this.#calculateMrpMaximumPeerResponseTime(sessionParameters, expectedProcessingTime) +
133
+ this.#calculateMrpMaximumPeerResponseTime(peerSessionParameters) +
134
+ this.#calculateMrpMaximumPeerResponseTime(localSessionParameters) +
135
+ expectedProcessingTime +
132
136
  PEER_RESPONSE_TIME_BUFFER,
133
137
  );
134
138
 
@@ -153,8 +157,10 @@ export class MessageChannel implements Channel<Message> {
153
157
  */
154
158
  getMrpResubmissionBackOffTime(retransmissionCount: number, sessionParameters?: SessionParameters) {
155
159
  const { activeInterval, idleInterval } = sessionParameters ?? this.session.parameters;
156
- const baseInterval =
157
- sessionParameters !== undefined || this.session.isPeerActive() ? activeInterval : idleInterval;
160
+ // For the first message of a new exchange ... SHALL be set according to the idle state of the peer node.
161
+ // For all subsequent messages of the exchange, ... SHOULD be set according to the active state of the peer node
162
+ const peerActive = retransmissionCount > 0 && (sessionParameters !== undefined || this.session.isPeerActive());
163
+ const baseInterval = peerActive ? activeInterval : idleInterval;
158
164
  return Millis.floor(
159
165
  Millis(
160
166
  baseInterval *
@@ -165,19 +171,15 @@ export class MessageChannel implements Channel<Message> {
165
171
  );
166
172
  }
167
173
 
168
- #calculateMrpMaximumPeerResponseTime(
169
- sessionParameters: SessionParameters,
170
- expectedProcessingTime = DEFAULT_EXPECTED_PROCESSING_TIME,
171
- ) {
172
- // We use the expected processing time and deduct the time we already waited since last resubmission
173
- let finalWaitTime = expectedProcessingTime;
174
+ /** Calculates the maximum time the peer might take to respond when using MRP for one direction. */
175
+ #calculateMrpMaximumPeerResponseTime(sessionParameters: SessionParameters) {
176
+ let finalWaitTime = 0;
174
177
 
175
178
  // and then add the time the other side needs for a full resubmission cycle under the assumption we are active
176
179
  for (let i = 0; i < MRP.MAX_TRANSMISSIONS; i++) {
177
180
  finalWaitTime = Millis(finalWaitTime + this.getMrpResubmissionBackOffTime(i, sessionParameters));
178
181
  }
179
182
 
180
- // TODO: Also add any network latency buffer, for now lets consider it's included in the processing time already
181
183
  return finalWaitTime;
182
184
  }
183
185
  }
@@ -31,7 +31,6 @@ import {
31
31
  } from "#protocol/MessageChannel.js";
32
32
  import { GroupSession } from "#session/GroupSession.js";
33
33
  import { SessionParameters } from "#session/Session.js";
34
- import { SessionIntervals } from "#session/SessionIntervals.js";
35
34
  import {
36
35
  GroupId,
37
36
  NodeId,
@@ -145,9 +144,6 @@ export class MessageExchange {
145
144
  );
146
145
  }
147
146
 
148
- readonly #activeInterval: Duration;
149
- readonly #idleInterval: Duration;
150
- readonly #activeThreshold: Duration;
151
147
  readonly #messagesQueue = new DataReadQueue<Message>();
152
148
  #receivedMessageToAck: Message | undefined;
153
149
  #receivedMessageAckTimer = Time.getTimer("Ack receipt timeout", MRP.STANDALONE_ACK_TIMEOUT, () => {
@@ -196,10 +192,7 @@ export class MessageExchange {
196
192
  this.#exchangeId = exchangeId;
197
193
  this.#protocolId = protocolId;
198
194
 
199
- const { activeInterval, idleInterval, activeThreshold } = SessionIntervals(session.parameters);
200
- this.#activeInterval = activeInterval;
201
- this.#idleInterval = idleInterval;
202
- this.#activeThreshold = activeThreshold;
195
+ const { activeThreshold, activeInterval, idleInterval } = this.session.parameters;
203
196
 
204
197
  this.#used = !isInitiator; // If we are the initiator then exchange was not used yet, so track it
205
198
 
@@ -211,9 +204,9 @@ export class MessageExchange {
211
204
  exId: this.#exchangeId,
212
205
  sess: session.name,
213
206
  peerSess: this.#peerSessionId,
214
- SAT: this.#activeThreshold,
215
- SAI: this.#activeInterval,
216
- SII: this.#idleInterval,
207
+ SAT: Duration.format(activeThreshold),
208
+ SAI: Duration.format(activeInterval),
209
+ SII: Duration.format(idleInterval),
217
210
  maxTrans: MRP.MAX_TRANSMISSIONS,
218
211
  exchangeFlags: Diagnostic.asFlags({
219
212
  MRP: this.channel.usesMrp,
@@ -489,6 +482,7 @@ export class MessageExchange {
489
482
  timeout = Instant; // If we have messages in the queue, we can return them immediately
490
483
  } else {
491
484
  timeout = this.channel.calculateMaximumPeerResponseTime(
485
+ this.session.parameters,
492
486
  this.context.localSessionParameters,
493
487
  options?.expectedProcessingTime,
494
488
  );
@@ -496,13 +490,6 @@ export class MessageExchange {
496
490
  return this.#messagesQueue.read(timeout);
497
491
  }
498
492
 
499
- calculateMaximumPeerResponseTimeMs(expectedProcessingTimeMs = DEFAULT_EXPECTED_PROCESSING_TIME) {
500
- return this.channel.calculateMaximumPeerResponseTime(
501
- this.context.localSessionParameters,
502
- expectedProcessingTimeMs,
503
- );
504
- }
505
-
506
493
  #retransmitMessage(message: Message, expectedProcessingTime?: Duration) {
507
494
  this.#retransmissionCounter++;
508
495
  if (this.#retransmissionCounter >= MRP.MAX_TRANSMISSIONS) {
@@ -512,6 +499,7 @@ export class MessageExchange {
512
499
  // We already have waited after the last message was sent, so deduct this time from the final wait time
513
500
  const finalWaitTime = Millis(
514
501
  this.channel.calculateMaximumPeerResponseTime(
502
+ this.session.parameters,
515
503
  this.context.localSessionParameters,
516
504
  expectedProcessingTime,
517
505
  ) - (this.#retransmissionTimer?.interval ?? Instant),
@@ -13,6 +13,7 @@ import {
13
13
  CRYPTO_SYMMETRIC_KEY_LENGTH,
14
14
  Crypto,
15
15
  Diagnostic,
16
+ Duration,
16
17
  Logger,
17
18
  MatterError,
18
19
  MatterFlowError,
@@ -176,9 +177,9 @@ export class NodeSession extends SecureSession {
176
177
  get parameterDiagnostics() {
177
178
  return Diagnostic.dict(
178
179
  {
179
- SII: this.idleInterval,
180
- SAI: this.activeInterval,
181
- SAT: this.activeThreshold,
180
+ SII: Duration.format(this.idleInterval),
181
+ SAI: Duration.format(this.activeInterval),
182
+ SAT: Duration.format(this.activeThreshold),
182
183
  DMRev: this.dataModelRevision,
183
184
  IMRev: this.interactionModelRevision,
184
185
  spec: Diagnostic.hex(this.specificationVersion),
@@ -49,7 +49,7 @@ export function SessionIntervals(intervals?: Partial<SessionIntervals>): Session
49
49
  }
50
50
 
51
51
  export namespace SessionIntervals {
52
- export const defaults = {
52
+ export const defaults: SessionIntervals = {
53
53
  idleInterval: Millis(500),
54
54
  activeInterval: Millis(300),
55
55
  activeThreshold: Seconds(4),
@@ -10,8 +10,8 @@ import {
10
10
  CRYPTO_HASH_LEN_BYTES,
11
11
  CRYPTO_PUBLIC_KEY_SIZE_BYTES,
12
12
  } from "#general";
13
- import { TlvByteString, TlvField, TlvObject, TlvOptionalField, TlvUInt16 } from "#types";
14
- import { TlvSessionParameters } from "../pase/PaseMessages.js";
13
+ import { TlvByteString, TlvField, TlvObject, TlvOptionalField, TlvUInt16, TypeFromSchema } from "#types";
14
+ import { TlvSessionParameters, WithDurationSessionParameters } from "../pase/PaseMessages.js";
15
15
 
16
16
  const CASE_SIGNATURE_LENGTH = CRYPTO_GROUP_SIZE_BYTES * 2;
17
17
 
@@ -34,6 +34,7 @@ export const TlvCaseSigma1 = TlvObject({
34
34
  resumptionId: TlvOptionalField(6, TlvByteString.bound({ length: 16 })),
35
35
  initiatorResumeMic: TlvOptionalField(7, TlvByteString.bound({ length: CRYPTO_AEAD_MIC_LENGTH_BYTES })),
36
36
  });
37
+ export type CaseSigma1 = WithDurationSessionParameters<TypeFromSchema<typeof TlvCaseSigma1>, "initiatorSessionParams">;
37
38
 
38
39
  /** @see {@link MatterSpecification.v13.Core} § 4.14.2.3 */
39
40
  export const TlvCaseSigma2 = TlvObject({
@@ -43,6 +44,7 @@ export const TlvCaseSigma2 = TlvObject({
43
44
  encrypted: TlvField(4, TlvByteString),
44
45
  responderSessionParams: TlvOptionalField(5, TlvSessionParameters),
45
46
  });
47
+ export type CaseSigma2 = WithDurationSessionParameters<TypeFromSchema<typeof TlvCaseSigma2>, "responderSessionParams">;
46
48
 
47
49
  /** @see {@link MatterSpecification.v13.Core} § 4.14.2.3 */
48
50
  export const TlvCaseSigma2Resume = TlvObject({
@@ -51,11 +53,16 @@ export const TlvCaseSigma2Resume = TlvObject({
51
53
  responderSessionId: TlvField(3, TlvUInt16),
52
54
  responderSessionParams: TlvOptionalField(4, TlvSessionParameters),
53
55
  });
56
+ export type CaseSigma2Resume = WithDurationSessionParameters<
57
+ TypeFromSchema<typeof TlvCaseSigma2Resume>,
58
+ "responderSessionParams"
59
+ >;
54
60
 
55
61
  /** @see {@link MatterSpecification.v13.Core} § 4.14.2.3 */
56
62
  export const TlvCaseSigma3 = TlvObject({
57
63
  encrypted: TlvField(1, TlvByteString),
58
64
  });
65
+ export type CaseSigma3 = TypeFromSchema<typeof TlvCaseSigma3>;
59
66
 
60
67
  /** @see {@link MatterSpecification.v10.Core} § 4.13.2.3 */
61
68
  export const TlvSignedData = TlvObject({
@@ -64,6 +71,7 @@ export const TlvSignedData = TlvObject({
64
71
  responderPublicKey: TlvField(3, TlvByteString.bound({ length: CRYPTO_PUBLIC_KEY_SIZE_BYTES })),
65
72
  initiatorPublicKey: TlvField(4, TlvByteString.bound({ length: CRYPTO_PUBLIC_KEY_SIZE_BYTES })),
66
73
  });
74
+ export type SignedData = TypeFromSchema<typeof TlvSignedData>;
67
75
 
68
76
  /** @see {@link MatterSpecification.v10.Core} § 4.13.2.3 */
69
77
  export const TlvEncryptedDataSigma2 = TlvObject({
@@ -72,6 +80,7 @@ export const TlvEncryptedDataSigma2 = TlvObject({
72
80
  signature: TlvField(3, TlvByteString.bound({ length: CASE_SIGNATURE_LENGTH })),
73
81
  resumptionId: TlvField(4, TlvByteString.bound({ length: 16 })),
74
82
  });
83
+ export type EncryptedDataSigma2 = TypeFromSchema<typeof TlvEncryptedDataSigma2>;
75
84
 
76
85
  /** @see {@link MatterSpecification.v10.Core} § 4.13.2.3 */
77
86
  export const TlvEncryptedDataSigma3 = TlvObject({
@@ -79,3 +88,4 @@ export const TlvEncryptedDataSigma3 = TlvObject({
79
88
  responderIcac: TlvOptionalField(2, TlvByteString),
80
89
  signature: TlvField(3, TlvByteString.bound({ length: CASE_SIGNATURE_LENGTH })),
81
90
  });
91
+ export type EncryptedDataSigma3 = TypeFromSchema<typeof TlvEncryptedDataSigma3>;
@@ -7,12 +7,20 @@
7
7
  import { MatterFlowError } from "#general";
8
8
  import { SecureMessageType, TypeFromSchema } from "#types";
9
9
  import { SecureChannelMessenger } from "../../securechannel/SecureChannelMessenger.js";
10
- import { TlvCaseSigma1, TlvCaseSigma2, TlvCaseSigma2Resume, TlvCaseSigma3 } from "./CaseMessages.js";
10
+ import {
11
+ CaseSigma1,
12
+ CaseSigma2,
13
+ CaseSigma2Resume,
14
+ TlvCaseSigma1,
15
+ TlvCaseSigma2,
16
+ TlvCaseSigma2Resume,
17
+ TlvCaseSigma3,
18
+ } from "./CaseMessages.js";
11
19
 
12
20
  export class CaseServerMessenger extends SecureChannelMessenger {
13
21
  async readSigma1() {
14
22
  const { payload } = await this.nextMessage(SecureMessageType.Sigma1);
15
- return { sigma1Bytes: payload, sigma1: TlvCaseSigma1.decode(payload) };
23
+ return { sigma1Bytes: payload, sigma1: TlvCaseSigma1.decode(payload) as CaseSigma1 };
16
24
  }
17
25
 
18
26
  sendSigma2(sigma2: TypeFromSchema<typeof TlvCaseSigma2>) {
@@ -41,9 +49,9 @@ export class CaseClientMessenger extends SecureChannelMessenger {
41
49
  } = await this.anyNextMessage("Sigma2(Resume)");
42
50
  switch (messageType) {
43
51
  case SecureMessageType.Sigma2:
44
- return { sigma2Bytes: payload, sigma2: TlvCaseSigma2.decode(payload) };
52
+ return { sigma2Bytes: payload, sigma2: TlvCaseSigma2.decode(payload) as CaseSigma2 };
45
53
  case SecureMessageType.Sigma2Resume:
46
- return { sigma2Resume: TlvCaseSigma2Resume.decode(payload) };
54
+ return { sigma2Resume: TlvCaseSigma2Resume.decode(payload) as CaseSigma2Resume };
47
55
  default:
48
56
  throw new MatterFlowError(
49
57
  `Received unexpected message type while expecting CASE Sigma2(Resume): ${messageType}, expected: ${SecureMessageType.Sigma2} or ${SecureMessageType.Sigma2Resume}`,
@@ -6,14 +6,15 @@
6
6
 
7
7
  import { Noc } from "#certificate/kinds/Noc.js";
8
8
  import { Bytes, Crypto, CryptoDecryptError, Logger, PublicKey, UnexpectedDataError } from "#general";
9
- import { TlvSessionParameters } from "#session/pase/PaseMessages.js";
9
+ import { SessionParametersWithDurations } from "#session/pase/PaseMessages.js";
10
10
  import { ResumptionRecord, SessionManager } from "#session/SessionManager.js";
11
- import { NodeId, SECURE_CHANNEL_PROTOCOL_ID, SecureChannelStatusCode, TypeFromSchema } from "#types";
11
+ import { NodeId, SECURE_CHANNEL_PROTOCOL_ID, SecureChannelStatusCode } from "#types";
12
12
  import { FabricManager, FabricNotFoundError } from "../../fabric/FabricManager.js";
13
13
  import { MessageExchange } from "../../protocol/MessageExchange.js";
14
14
  import { ProtocolHandler } from "../../protocol/ProtocolHandler.js";
15
15
  import { ChannelStatusResponseError } from "../../securechannel/SecureChannelMessenger.js";
16
16
  import {
17
+ CaseSigma1,
17
18
  KDFSR1_KEY_INFO,
18
19
  KDFSR2_INFO,
19
20
  KDFSR2_KEY_INFO,
@@ -22,7 +23,6 @@ import {
22
23
  RESUME2_MIC_NONCE,
23
24
  TBE_DATA2_NONCE,
24
25
  TBE_DATA3_NONCE,
25
- TlvCaseSigma1,
26
26
  TlvEncryptedDataSigma2,
27
27
  TlvEncryptedDataSigma3,
28
28
  TlvSignedData,
@@ -313,7 +313,7 @@ class Sigma1Context {
313
313
  destinationId: Bytes;
314
314
  peerRandom: Bytes;
315
315
  peerEcdhPublicKey: Bytes;
316
- peerSessionParams?: TypeFromSchema<typeof TlvSessionParameters>;
316
+ peerSessionParams?: SessionParametersWithDurations;
317
317
  resumptionRecord?: ResumptionRecord;
318
318
 
319
319
  #localResumptionId?: Bytes;
@@ -322,7 +322,7 @@ class Sigma1Context {
322
322
  crypto: Crypto,
323
323
  messenger: CaseServerMessenger,
324
324
  bytes: Bytes,
325
- sigma1: TypeFromSchema<typeof TlvCaseSigma1>,
325
+ sigma1: CaseSigma1,
326
326
  resumptionRecord?: ResumptionRecord,
327
327
  ) {
328
328
  this.crypto = crypto;