@matter/protocol 0.14.1-alpha.0-20250605-9fc134af0 → 0.14.1-alpha.0-20250607-a93593303

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 (312) hide show
  1. package/dist/cjs/action/server/AccessControl.d.ts +5 -7
  2. package/dist/cjs/action/server/AccessControl.d.ts.map +1 -1
  3. package/dist/cjs/action/server/AccessControl.js.map +1 -1
  4. package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
  5. package/dist/cjs/action/server/AttributeWriteResponse.js +23 -0
  6. package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
  7. package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
  8. package/dist/cjs/action/server/CommandInvokeResponse.js +24 -1
  9. package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
  10. package/dist/cjs/action/server/DataResponse.d.ts +1 -1
  11. package/dist/cjs/action/server/DataResponse.d.ts.map +1 -1
  12. package/dist/cjs/action/server/Subject.d.ts +25 -0
  13. package/dist/cjs/action/server/Subject.d.ts.map +1 -0
  14. package/dist/cjs/action/server/Subject.js +54 -0
  15. package/dist/cjs/action/server/Subject.js.map +6 -0
  16. package/dist/cjs/action/server/index.d.ts +1 -0
  17. package/dist/cjs/action/server/index.d.ts.map +1 -1
  18. package/dist/cjs/action/server/index.js +1 -0
  19. package/dist/cjs/action/server/index.js.map +1 -1
  20. package/dist/cjs/certificate/DeviceCertification.d.ts +2 -2
  21. package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
  22. package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
  23. package/dist/cjs/cluster/client/AttributeClient.d.ts +3 -3
  24. package/dist/cjs/cluster/client/AttributeClient.d.ts.map +1 -1
  25. package/dist/cjs/cluster/client/AttributeClient.js +14 -2
  26. package/dist/cjs/cluster/client/AttributeClient.js.map +1 -1
  27. package/dist/cjs/cluster/client/ClusterClient.d.ts +3 -2
  28. package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
  29. package/dist/cjs/cluster/client/ClusterClient.js +66 -1
  30. package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
  31. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +36 -8
  32. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  33. package/dist/cjs/cluster/client/EventClient.d.ts +3 -3
  34. package/dist/cjs/cluster/client/EventClient.d.ts.map +1 -1
  35. package/dist/cjs/cluster/client/EventClient.js +7 -0
  36. package/dist/cjs/cluster/client/EventClient.js.map +1 -1
  37. package/dist/cjs/codec/MessageCodec.d.ts.map +1 -1
  38. package/dist/cjs/codec/MessageCodec.js +31 -6
  39. package/dist/cjs/codec/MessageCodec.js.map +1 -1
  40. package/dist/cjs/fabric/Fabric.d.ts +20 -30
  41. package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
  42. package/dist/cjs/fabric/Fabric.js +38 -62
  43. package/dist/cjs/fabric/Fabric.js.map +2 -2
  44. package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
  45. package/dist/cjs/fabric/FabricManager.js +10 -4
  46. package/dist/cjs/fabric/FabricManager.js.map +1 -1
  47. package/dist/cjs/groups/FabricGroupsManager.d.ts +46 -0
  48. package/dist/cjs/groups/FabricGroupsManager.d.ts.map +1 -0
  49. package/dist/cjs/groups/FabricGroupsManager.js +155 -0
  50. package/dist/cjs/groups/FabricGroupsManager.js.map +6 -0
  51. package/dist/cjs/groups/Groups.d.ts +34 -0
  52. package/dist/cjs/groups/Groups.d.ts.map +1 -0
  53. package/dist/cjs/groups/Groups.js +89 -0
  54. package/dist/cjs/groups/Groups.js.map +6 -0
  55. package/dist/cjs/groups/KeySets.d.ts +64 -0
  56. package/dist/cjs/groups/KeySets.d.ts.map +1 -0
  57. package/dist/cjs/groups/KeySets.js +179 -0
  58. package/dist/cjs/groups/KeySets.js.map +6 -0
  59. package/dist/cjs/groups/MessagingState.d.ts +24 -0
  60. package/dist/cjs/groups/MessagingState.d.ts.map +1 -0
  61. package/dist/cjs/groups/MessagingState.js +91 -0
  62. package/dist/cjs/groups/MessagingState.js.map +6 -0
  63. package/dist/cjs/groups/index.d.ts +8 -0
  64. package/dist/cjs/groups/index.d.ts.map +1 -0
  65. package/dist/cjs/groups/index.js +25 -0
  66. package/dist/cjs/groups/index.js.map +6 -0
  67. package/dist/cjs/index.d.ts +1 -0
  68. package/dist/cjs/index.d.ts.map +1 -1
  69. package/dist/cjs/index.js +1 -0
  70. package/dist/cjs/index.js.map +1 -1
  71. package/dist/cjs/interaction/AccessControlManager.d.ts +4 -13
  72. package/dist/cjs/interaction/AccessControlManager.d.ts.map +1 -1
  73. package/dist/cjs/interaction/AccessControlManager.js +38 -47
  74. package/dist/cjs/interaction/AccessControlManager.js.map +1 -1
  75. package/dist/cjs/interaction/InteractionClient.d.ts +5 -4
  76. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  77. package/dist/cjs/interaction/InteractionClient.js +53 -3
  78. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  79. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  80. package/dist/cjs/interaction/InteractionMessenger.js +15 -0
  81. package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
  82. package/dist/cjs/interaction/Subscription.d.ts +3 -3
  83. package/dist/cjs/interaction/Subscription.d.ts.map +1 -1
  84. package/dist/cjs/interaction/Subscription.js.map +1 -1
  85. package/dist/cjs/peer/PeerAddress.d.ts +1 -0
  86. package/dist/cjs/peer/PeerAddress.d.ts.map +1 -1
  87. package/dist/cjs/peer/PeerAddress.js +5 -0
  88. package/dist/cjs/peer/PeerAddress.js.map +1 -1
  89. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  90. package/dist/cjs/peer/PeerSet.js +31 -2
  91. package/dist/cjs/peer/PeerSet.js.map +1 -1
  92. package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
  93. package/dist/cjs/protocol/ChannelManager.js +7 -8
  94. package/dist/cjs/protocol/ChannelManager.js.map +1 -1
  95. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  96. package/dist/cjs/protocol/ExchangeManager.js +39 -25
  97. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  98. package/dist/cjs/protocol/MessageExchange.d.ts +1 -1
  99. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  100. package/dist/cjs/protocol/MessageExchange.js +32 -4
  101. package/dist/cjs/protocol/MessageExchange.js.map +1 -1
  102. package/dist/cjs/protocol/MessageReceptionState.d.ts +1 -1
  103. package/dist/cjs/securechannel/SecureChannelProtocol.js +1 -1
  104. package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
  105. package/dist/cjs/session/GroupSession.d.ts +56 -0
  106. package/dist/cjs/session/GroupSession.d.ts.map +1 -0
  107. package/dist/cjs/session/GroupSession.js +188 -0
  108. package/dist/cjs/session/GroupSession.js.map +6 -0
  109. package/dist/cjs/session/InsecureSession.d.ts +2 -1
  110. package/dist/cjs/session/InsecureSession.d.ts.map +1 -1
  111. package/dist/cjs/session/InsecureSession.js +3 -2
  112. package/dist/cjs/session/InsecureSession.js.map +1 -1
  113. package/dist/cjs/session/NodeSession.d.ts +88 -0
  114. package/dist/cjs/session/NodeSession.d.ts.map +1 -0
  115. package/dist/cjs/session/NodeSession.js +318 -0
  116. package/dist/cjs/session/NodeSession.js.map +6 -0
  117. package/dist/cjs/session/SecureSession.d.ts +10 -75
  118. package/dist/cjs/session/SecureSession.d.ts.map +1 -1
  119. package/dist/cjs/session/SecureSession.js +9 -280
  120. package/dist/cjs/session/SecureSession.js.map +2 -2
  121. package/dist/cjs/session/Session.d.ts +6 -5
  122. package/dist/cjs/session/Session.d.ts.map +1 -1
  123. package/dist/cjs/session/Session.js +11 -1
  124. package/dist/cjs/session/Session.js.map +1 -1
  125. package/dist/cjs/session/SessionManager.d.ts +27 -9
  126. package/dist/cjs/session/SessionManager.d.ts.map +1 -1
  127. package/dist/cjs/session/SessionManager.js +83 -5
  128. package/dist/cjs/session/SessionManager.js.map +2 -2
  129. package/dist/cjs/session/case/CaseClient.d.ts +1 -1
  130. package/dist/cjs/session/case/CaseClient.js +2 -2
  131. package/dist/cjs/session/case/CaseClient.js.map +1 -1
  132. package/dist/cjs/session/index.d.ts +2 -0
  133. package/dist/cjs/session/index.d.ts.map +1 -1
  134. package/dist/cjs/session/index.js +2 -0
  135. package/dist/cjs/session/index.js.map +1 -1
  136. package/dist/cjs/session/pase/PaseClient.d.ts +1 -1
  137. package/dist/esm/action/server/AccessControl.d.ts +5 -7
  138. package/dist/esm/action/server/AccessControl.d.ts.map +1 -1
  139. package/dist/esm/action/server/AccessControl.js.map +1 -1
  140. package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
  141. package/dist/esm/action/server/AttributeWriteResponse.js +23 -0
  142. package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
  143. package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
  144. package/dist/esm/action/server/CommandInvokeResponse.js +24 -1
  145. package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
  146. package/dist/esm/action/server/DataResponse.d.ts +1 -1
  147. package/dist/esm/action/server/DataResponse.d.ts.map +1 -1
  148. package/dist/esm/action/server/Subject.d.ts +25 -0
  149. package/dist/esm/action/server/Subject.d.ts.map +1 -0
  150. package/dist/esm/action/server/Subject.js +34 -0
  151. package/dist/esm/action/server/Subject.js.map +6 -0
  152. package/dist/esm/action/server/index.d.ts +1 -0
  153. package/dist/esm/action/server/index.d.ts.map +1 -1
  154. package/dist/esm/action/server/index.js +1 -0
  155. package/dist/esm/action/server/index.js.map +1 -1
  156. package/dist/esm/certificate/DeviceCertification.d.ts +2 -2
  157. package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
  158. package/dist/esm/certificate/DeviceCertification.js.map +1 -1
  159. package/dist/esm/cluster/client/AttributeClient.d.ts +3 -3
  160. package/dist/esm/cluster/client/AttributeClient.d.ts.map +1 -1
  161. package/dist/esm/cluster/client/AttributeClient.js +13 -1
  162. package/dist/esm/cluster/client/AttributeClient.js.map +1 -1
  163. package/dist/esm/cluster/client/ClusterClient.d.ts +3 -2
  164. package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
  165. package/dist/esm/cluster/client/ClusterClient.js +67 -2
  166. package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
  167. package/dist/esm/cluster/client/ClusterClientTypes.d.ts +36 -8
  168. package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  169. package/dist/esm/cluster/client/EventClient.d.ts +3 -3
  170. package/dist/esm/cluster/client/EventClient.d.ts.map +1 -1
  171. package/dist/esm/cluster/client/EventClient.js +7 -0
  172. package/dist/esm/cluster/client/EventClient.js.map +1 -1
  173. package/dist/esm/codec/MessageCodec.d.ts.map +1 -1
  174. package/dist/esm/codec/MessageCodec.js +41 -7
  175. package/dist/esm/codec/MessageCodec.js.map +1 -1
  176. package/dist/esm/fabric/Fabric.d.ts +20 -30
  177. package/dist/esm/fabric/Fabric.d.ts.map +1 -1
  178. package/dist/esm/fabric/Fabric.js +38 -62
  179. package/dist/esm/fabric/Fabric.js.map +2 -2
  180. package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
  181. package/dist/esm/fabric/FabricManager.js +10 -4
  182. package/dist/esm/fabric/FabricManager.js.map +1 -1
  183. package/dist/esm/groups/FabricGroupsManager.d.ts +46 -0
  184. package/dist/esm/groups/FabricGroupsManager.d.ts.map +1 -0
  185. package/dist/esm/groups/FabricGroupsManager.js +135 -0
  186. package/dist/esm/groups/FabricGroupsManager.js.map +6 -0
  187. package/dist/esm/groups/Groups.d.ts +34 -0
  188. package/dist/esm/groups/Groups.d.ts.map +1 -0
  189. package/dist/esm/groups/Groups.js +69 -0
  190. package/dist/esm/groups/Groups.js.map +6 -0
  191. package/dist/esm/groups/KeySets.d.ts +64 -0
  192. package/dist/esm/groups/KeySets.d.ts.map +1 -0
  193. package/dist/esm/groups/KeySets.js +159 -0
  194. package/dist/esm/groups/KeySets.js.map +6 -0
  195. package/dist/esm/groups/MessagingState.d.ts +24 -0
  196. package/dist/esm/groups/MessagingState.d.ts.map +1 -0
  197. package/dist/esm/groups/MessagingState.js +71 -0
  198. package/dist/esm/groups/MessagingState.js.map +6 -0
  199. package/dist/esm/groups/index.d.ts +8 -0
  200. package/dist/esm/groups/index.d.ts.map +1 -0
  201. package/dist/esm/groups/index.js +8 -0
  202. package/dist/esm/groups/index.js.map +6 -0
  203. package/dist/esm/index.d.ts +1 -0
  204. package/dist/esm/index.d.ts.map +1 -1
  205. package/dist/esm/index.js +1 -0
  206. package/dist/esm/index.js.map +1 -1
  207. package/dist/esm/interaction/AccessControlManager.d.ts +4 -13
  208. package/dist/esm/interaction/AccessControlManager.d.ts.map +1 -1
  209. package/dist/esm/interaction/AccessControlManager.js +39 -48
  210. package/dist/esm/interaction/AccessControlManager.js.map +1 -1
  211. package/dist/esm/interaction/InteractionClient.d.ts +5 -4
  212. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  213. package/dist/esm/interaction/InteractionClient.js +54 -4
  214. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  215. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  216. package/dist/esm/interaction/InteractionMessenger.js +15 -0
  217. package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
  218. package/dist/esm/interaction/Subscription.d.ts +3 -3
  219. package/dist/esm/interaction/Subscription.d.ts.map +1 -1
  220. package/dist/esm/interaction/Subscription.js.map +1 -1
  221. package/dist/esm/peer/PeerAddress.d.ts +1 -0
  222. package/dist/esm/peer/PeerAddress.d.ts.map +1 -1
  223. package/dist/esm/peer/PeerAddress.js +5 -0
  224. package/dist/esm/peer/PeerAddress.js.map +1 -1
  225. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  226. package/dist/esm/peer/PeerSet.js +33 -3
  227. package/dist/esm/peer/PeerSet.js.map +1 -1
  228. package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
  229. package/dist/esm/protocol/ChannelManager.js +7 -8
  230. package/dist/esm/protocol/ChannelManager.js.map +1 -1
  231. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  232. package/dist/esm/protocol/ExchangeManager.js +41 -27
  233. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  234. package/dist/esm/protocol/MessageExchange.d.ts +1 -1
  235. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  236. package/dist/esm/protocol/MessageExchange.js +39 -5
  237. package/dist/esm/protocol/MessageExchange.js.map +1 -1
  238. package/dist/esm/protocol/MessageReceptionState.d.ts +1 -1
  239. package/dist/esm/securechannel/SecureChannelProtocol.js +2 -2
  240. package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
  241. package/dist/esm/session/GroupSession.d.ts +56 -0
  242. package/dist/esm/session/GroupSession.d.ts.map +1 -0
  243. package/dist/esm/session/GroupSession.js +177 -0
  244. package/dist/esm/session/GroupSession.js.map +6 -0
  245. package/dist/esm/session/InsecureSession.d.ts +2 -1
  246. package/dist/esm/session/InsecureSession.d.ts.map +1 -1
  247. package/dist/esm/session/InsecureSession.js +3 -2
  248. package/dist/esm/session/InsecureSession.js.map +1 -1
  249. package/dist/esm/session/NodeSession.d.ts +88 -0
  250. package/dist/esm/session/NodeSession.d.ts.map +1 -0
  251. package/dist/esm/session/NodeSession.js +298 -0
  252. package/dist/esm/session/NodeSession.js.map +6 -0
  253. package/dist/esm/session/SecureSession.d.ts +10 -75
  254. package/dist/esm/session/SecureSession.d.ts.map +1 -1
  255. package/dist/esm/session/SecureSession.js +10 -291
  256. package/dist/esm/session/SecureSession.js.map +2 -2
  257. package/dist/esm/session/Session.d.ts +6 -5
  258. package/dist/esm/session/Session.d.ts.map +1 -1
  259. package/dist/esm/session/Session.js +12 -2
  260. package/dist/esm/session/Session.js.map +1 -1
  261. package/dist/esm/session/SessionManager.d.ts +27 -9
  262. package/dist/esm/session/SessionManager.d.ts.map +1 -1
  263. package/dist/esm/session/SessionManager.js +84 -6
  264. package/dist/esm/session/SessionManager.js.map +1 -1
  265. package/dist/esm/session/case/CaseClient.d.ts +1 -1
  266. package/dist/esm/session/case/CaseClient.js +2 -2
  267. package/dist/esm/session/case/CaseClient.js.map +1 -1
  268. package/dist/esm/session/index.d.ts +2 -0
  269. package/dist/esm/session/index.d.ts.map +1 -1
  270. package/dist/esm/session/index.js +2 -0
  271. package/dist/esm/session/index.js.map +1 -1
  272. package/dist/esm/session/pase/PaseClient.d.ts +1 -1
  273. package/package.json +6 -6
  274. package/src/action/server/AccessControl.ts +4 -7
  275. package/src/action/server/AttributeWriteResponse.ts +29 -7
  276. package/src/action/server/CommandInvokeResponse.ts +28 -7
  277. package/src/action/server/DataResponse.ts +1 -1
  278. package/src/action/server/Subject.ts +45 -0
  279. package/src/action/server/index.ts +1 -0
  280. package/src/certificate/DeviceCertification.ts +2 -2
  281. package/src/cluster/client/AttributeClient.ts +15 -3
  282. package/src/cluster/client/ClusterClient.ts +97 -4
  283. package/src/cluster/client/ClusterClientTypes.ts +45 -9
  284. package/src/cluster/client/EventClient.ts +9 -2
  285. package/src/codec/MessageCodec.ts +49 -8
  286. package/src/fabric/Fabric.ts +51 -85
  287. package/src/fabric/FabricManager.ts +11 -4
  288. package/src/groups/FabricGroupsManager.ts +164 -0
  289. package/src/groups/Groups.ts +81 -0
  290. package/src/groups/KeySets.ts +194 -0
  291. package/src/groups/MessagingState.ts +76 -0
  292. package/src/groups/index.ts +8 -0
  293. package/src/index.ts +1 -0
  294. package/src/interaction/AccessControlManager.ts +49 -81
  295. package/src/interaction/InteractionClient.ts +66 -6
  296. package/src/interaction/InteractionMessenger.ts +15 -0
  297. package/src/interaction/Subscription.ts +3 -3
  298. package/src/peer/PeerAddress.ts +4 -0
  299. package/src/peer/PeerSet.ts +39 -4
  300. package/src/protocol/ChannelManager.ts +7 -9
  301. package/src/protocol/ExchangeManager.ts +51 -35
  302. package/src/protocol/MessageExchange.ts +42 -7
  303. package/src/protocol/MessageReceptionState.ts +2 -2
  304. package/src/securechannel/SecureChannelProtocol.ts +2 -2
  305. package/src/session/GroupSession.ts +223 -0
  306. package/src/session/InsecureSession.ts +3 -2
  307. package/src/session/NodeSession.ts +367 -0
  308. package/src/session/SecureSession.ts +14 -363
  309. package/src/session/Session.ts +17 -6
  310. package/src/session/SessionManager.ts +94 -14
  311. package/src/session/case/CaseClient.ts +2 -2
  312. package/src/session/index.ts +2 -3
@@ -134,7 +134,8 @@ export class InteractionClientProvider {
134
134
  return client;
135
135
  }
136
136
 
137
- const nodeStore = this.#peers.get(address)?.dataStore;
137
+ const isGroupAddress = PeerAddress.isGroup(address);
138
+ const nodeStore = isGroupAddress ? undefined : this.#peers.get(address)?.dataStore;
138
139
  await nodeStore?.construction; // Lazy initialize the data if not already done
139
140
 
140
141
  const exchangeProvider = await this.#peers.exchangeProviderFor(address, discoveryOptions);
@@ -167,6 +168,7 @@ export class InteractionClient {
167
168
  readonly #subscriptionClient: SubscriptionClient;
168
169
  readonly #queue?: PromiseQueue;
169
170
  readonly #address?: PeerAddress;
171
+ readonly isGroupAddress: boolean;
170
172
 
171
173
  constructor(
172
174
  exchangeProvider: ExchangeProvider,
@@ -180,6 +182,7 @@ export class InteractionClient {
180
182
  this.#subscriptionClient = subscriptionClient;
181
183
  this.#queue = queue;
182
184
  this.#address = address;
185
+ this.isGroupAddress = address !== undefined ? PeerAddress.isGroup(address) : false;
183
186
  }
184
187
 
185
188
  get address() {
@@ -321,6 +324,10 @@ export class InteractionClient {
321
324
  executeQueued?: boolean;
322
325
  } = {},
323
326
  ): Promise<DecodedDataReport> {
327
+ if (this.isGroupAddress) {
328
+ throw new ImplementationError("Reading data from group addresses is not supported.");
329
+ }
330
+
324
331
  const {
325
332
  attributes: attributeRequests,
326
333
  dataVersionFilters,
@@ -411,6 +418,10 @@ export class InteractionClient {
411
418
  clusterId: ClusterId;
412
419
  attribute: A;
413
420
  }): { value: AttributeJsType<A>; version: number } | undefined {
421
+ if (this.isGroupAddress) {
422
+ throw new ImplementationError("Reading data from group addresses is not supported.");
423
+ }
424
+
414
425
  const { endpointId, clusterId, attribute } = options;
415
426
  const { id: attributeId } = attribute;
416
427
  if (this.#nodeStore !== undefined) {
@@ -430,6 +441,10 @@ export class InteractionClient {
430
441
  requestFromRemote?: boolean;
431
442
  executeQueued?: boolean;
432
443
  }): Promise<{ value: AttributeJsType<A>; version: number } | undefined> {
444
+ if (this.isGroupAddress) {
445
+ throw new ImplementationError("Reading data from group addresses is not supported.");
446
+ }
447
+
433
448
  const { endpointId, clusterId, attribute, requestFromRemote, isFabricFiltered, executeQueued } = options;
434
449
  const { id: attributeId } = attribute;
435
450
  if (this.#nodeStore !== undefined) {
@@ -516,7 +531,7 @@ export class InteractionClient {
516
531
 
517
532
  async setAttribute<T>(options: {
518
533
  attributeData: {
519
- endpointId: EndpointNumber;
534
+ endpointId?: EndpointNumber;
520
535
  clusterId: ClusterId;
521
536
  attribute: Attribute<T, any>;
522
537
  value: T;
@@ -557,7 +572,7 @@ export class InteractionClient {
557
572
 
558
573
  async setMultipleAttributes(options: {
559
574
  attributes: {
560
- endpointId: EndpointNumber;
575
+ endpointId?: EndpointNumber;
561
576
  clusterId: ClusterId;
562
577
  attribute: Attribute<any, any>;
563
578
  value: any;
@@ -575,9 +590,22 @@ export class InteractionClient {
575
590
  attributes,
576
591
  asTimedRequest,
577
592
  timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT_MS,
578
- suppressResponse = false, // TODO needs to be TRUE for Group writes
593
+ suppressResponse = this.isGroupAddress,
579
594
  chunkLists = true, // Should be true currently to stay in sync with chip sdk
580
595
  } = options;
596
+ if (this.isGroupAddress) {
597
+ if (!suppressResponse) {
598
+ throw new ImplementationError("Writing attributes on a group address can not return a response.");
599
+ }
600
+ if (
601
+ attributes.some(
602
+ ({ endpointId, clusterId, attribute }) =>
603
+ endpointId !== undefined || clusterId === undefined || attribute.id === undefined,
604
+ )
605
+ ) {
606
+ throw new ImplementationError("Not all attribute write paths are valid for group address writes.");
607
+ }
608
+ }
581
609
  logger.debug(
582
610
  `Sending write request: ${attributes
583
611
  .map(
@@ -621,6 +649,9 @@ export class InteractionClient {
621
649
  attributes.some(({ attribute: { timed } }) => timed) ||
622
650
  asTimedRequest === true ||
623
651
  options.timedRequestTimeoutMs !== undefined;
652
+ if (this.isGroupAddress && timedRequest) {
653
+ throw new ImplementationError("Timed requests are not supported for group address writes.");
654
+ }
624
655
 
625
656
  const response = await this.withMessenger<TypeFromSchema<typeof TlvWriteResponse> | undefined>(
626
657
  async messenger => {
@@ -671,6 +702,9 @@ export class InteractionClient {
671
702
  }): Promise<{
672
703
  maxInterval: number;
673
704
  }> {
705
+ if (this.isGroupAddress) {
706
+ throw new ImplementationError("Subscribing to attributes on a group address is not supported.");
707
+ }
674
708
  const {
675
709
  endpointId,
676
710
  clusterId,
@@ -792,6 +826,9 @@ export class InteractionClient {
792
826
  }): Promise<{
793
827
  maxInterval: number;
794
828
  }> {
829
+ if (this.isGroupAddress) {
830
+ throw new ImplementationError("Subscribing to events on a group address is not supported.");
831
+ }
795
832
  const {
796
833
  endpointId,
797
834
  clusterId,
@@ -923,6 +960,9 @@ export class InteractionClient {
923
960
  eventReports?: DecodedEventReportValue<any>[];
924
961
  maxInterval: number;
925
962
  }> {
963
+ if (this.isGroupAddress) {
964
+ throw new ImplementationError("Subscribing to attributes or events on a group address is not supported.");
965
+ }
926
966
  const {
927
967
  attributes: attributeRequests = [],
928
968
  events: eventRequests = [],
@@ -1097,7 +1137,7 @@ export class InteractionClient {
1097
1137
  }
1098
1138
 
1099
1139
  async invoke<C extends Command<any, any, any>>(options: {
1100
- endpointId: EndpointNumber;
1140
+ endpointId?: EndpointNumber;
1101
1141
  clusterId: ClusterId;
1102
1142
  request: RequestType<C>;
1103
1143
  command: C;
@@ -1132,6 +1172,15 @@ export class InteractionClient {
1132
1172
  const timedRequest =
1133
1173
  (timed && !skipValidation) || asTimedRequest === true || options.timedRequestTimeoutMs !== undefined;
1134
1174
 
1175
+ if (this.isGroupAddress) {
1176
+ if (endpointId !== undefined) {
1177
+ throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
1178
+ }
1179
+ if (timedRequest) {
1180
+ throw new ImplementationError("Timed requests are not supported for group address invokes.");
1181
+ }
1182
+ }
1183
+
1135
1184
  if (requestSchema instanceof ObjectSchema) {
1136
1185
  if (request === undefined) {
1137
1186
  // If developer did not provide a request object, create an empty one if it needs to be an object
@@ -1228,8 +1277,9 @@ export class InteractionClient {
1228
1277
  }
1229
1278
 
1230
1279
  // TODO Add to ClusterClient when needed/when Group communication is implemented
1280
+ // TODO Additionally support it without endpoint
1231
1281
  async invokeWithSuppressedResponse<C extends Command<any, any, any>>(options: {
1232
- endpointId: EndpointNumber;
1282
+ endpointId?: EndpointNumber;
1233
1283
  clusterId: ClusterId;
1234
1284
  request: RequestType<C>;
1235
1285
  command: C;
@@ -1248,6 +1298,16 @@ export class InteractionClient {
1248
1298
  timedRequestTimeoutMs = DEFAULT_TIMED_REQUEST_TIMEOUT_MS,
1249
1299
  } = options;
1250
1300
  const timedRequest = timed || asTimedRequest === true || options.timedRequestTimeoutMs !== undefined;
1301
+
1302
+ if (this.isGroupAddress) {
1303
+ if (timed) {
1304
+ throw new ImplementationError("Timed requests are not supported for group address invokes.");
1305
+ }
1306
+ if (endpointId !== undefined) {
1307
+ throw new ImplementationError("Invoking a concrete command on a group address is not supported.");
1308
+ }
1309
+ }
1310
+
1251
1311
  logger.debug(
1252
1312
  `Invoking command with suppressedResponse: ${resolveCommandName({
1253
1313
  endpointId,
@@ -262,6 +262,12 @@ export class InteractionServerMessenger extends InteractionMessenger {
262
262
  break;
263
263
  }
264
264
  case MessageType.SubscribeRequest: {
265
+ if (isGroupSession) {
266
+ throw new StatusResponseError(
267
+ `SubscribeRequest is not supported in group sessions`,
268
+ Status.InvalidAction,
269
+ );
270
+ }
265
271
  const subscribeRequest = TlvSubscribeRequest.decode(message.payload);
266
272
  await recipient.handleSubscribeRequest(this.exchange, subscribeRequest, this, message);
267
273
  // response is sent by handler
@@ -274,6 +280,12 @@ export class InteractionServerMessenger extends InteractionMessenger {
274
280
  break;
275
281
  }
276
282
  case MessageType.TimedRequest: {
283
+ if (isGroupSession) {
284
+ throw new StatusResponseError(
285
+ `TimedRequest is not supported in group sessions`,
286
+ Status.InvalidAction,
287
+ );
288
+ }
277
289
  const timedRequest = TlvTimedRequest.decode(message.payload);
278
290
  recipient.handleTimedRequest(this.exchange, timedRequest, message);
279
291
  await this.sendStatus(StatusCode.Success, {
@@ -288,6 +300,9 @@ export class InteractionServerMessenger extends InteractionMessenger {
288
300
  Status.InvalidAction,
289
301
  );
290
302
  }
303
+ if (isGroupSession) {
304
+ break; // We do not support multiple messages in group sessions
305
+ }
291
306
  }
292
307
  } catch (error: any) {
293
308
  let errorStatusCode = StatusCode.Failure;
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { AsyncObservable, InternalError, Logger } from "#general";
8
- import { type SecureSession } from "#session/SecureSession.js";
8
+ import { NodeSession } from "#session/NodeSession.js";
9
9
  import { TlvAttributePath, TlvDataVersionFilter, TlvEventFilter, TlvEventPath, TypeFromSchema } from "#types";
10
10
 
11
11
  const logger = Logger.get("Subscription");
@@ -24,7 +24,7 @@ export interface SubscriptionCriteria {
24
24
  * A single active subscription.
25
25
  */
26
26
  export abstract class Subscription {
27
- #session: SecureSession;
27
+ #session: NodeSession;
28
28
  #id: SubscriptionId;
29
29
  #isClosed?: boolean;
30
30
  #isCanceledByPeer?: boolean;
@@ -32,7 +32,7 @@ export abstract class Subscription {
32
32
  #cancelled = AsyncObservable<[subscription: Subscription]>();
33
33
  #maxIntervalMs?: number;
34
34
 
35
- constructor(session: SecureSession, id: SubscriptionId, criteria: SubscriptionCriteria) {
35
+ constructor(session: NodeSession, id: SubscriptionId, criteria: SubscriptionCriteria) {
36
36
  this.#session = session;
37
37
  this.#id = id;
38
38
  this.#criteria = criteria;
@@ -64,6 +64,10 @@ export namespace PeerAddress {
64
64
 
65
65
  return addr1.fabricIndex === addr2.fabricIndex && addr1.nodeId === addr2.nodeId;
66
66
  }
67
+
68
+ export function isGroup(address: PeerAddress): boolean {
69
+ return NodeId.isGroupNodeId(address.nodeId);
70
+ }
67
71
  }
68
72
 
69
73
  /**
@@ -25,6 +25,7 @@ import {
25
25
  ObservableSet,
26
26
  ServerAddressIp,
27
27
  serverAddressToString,
28
+ STANDARD_MATTER_PORT,
28
29
  Time,
29
30
  Timer,
30
31
  } from "#general";
@@ -34,7 +35,7 @@ import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
34
35
  import { ChannelStatusResponseError } from "#securechannel/index.js";
35
36
  import { CaseClient, SecureSession, Session } from "#session/index.js";
36
37
  import { SessionManager } from "#session/SessionManager.js";
37
- import { NodeId, ProtocolStatusCode, SECURE_CHANNEL_PROTOCOL_ID } from "#types";
38
+ import { GroupId, NodeId, ProtocolStatusCode, SECURE_CHANNEL_PROTOCOL_ID } from "#types";
38
39
  import { ChannelManager } from "../protocol/ChannelManager.js";
39
40
  import { ChannelNotConnectedError, ExchangeManager, MessageChannel } from "../protocol/ExchangeManager.js";
40
41
  import { DedicatedChannelExchangeProvider, ReconnectableExchangeProvider } from "../protocol/ExchangeProvider.js";
@@ -240,14 +241,20 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
240
241
  operationalAddress?: ServerAddressIp;
241
242
  },
242
243
  ) {
244
+ address = PeerAddress(address);
245
+
246
+ const isGroupNode = PeerAddress.isGroup(address);
243
247
  const { discoveryOptions, allowUnknownPeer, operationalAddress } = options;
244
- if (!this.#peersByAddress.has(address) && !allowUnknownPeer) {
248
+ if (!this.#peersByAddress.has(address) && !allowUnknownPeer && !isGroupNode) {
245
249
  throw new UnknownNodeError(`Cannot connect to unknown device ${PeerAddress(address)}`);
246
250
  }
247
251
 
248
- address = PeerAddress(address);
249
-
250
252
  if (!this.#channels.hasChannel(address)) {
253
+ if (isGroupNode) {
254
+ await this.#createGroupChannel(address);
255
+ return;
256
+ }
257
+
251
258
  const { promise: existingReconnectPromise } = this.#runningPeerReconnections.get(address) ?? {};
252
259
  if (existingReconnectPromise !== undefined) {
253
260
  return existingReconnectPromise;
@@ -278,6 +285,13 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
278
285
  return new DedicatedChannelExchangeProvider(this.#exchanges, addressOrChannel);
279
286
  }
280
287
  const address: PeerAddress = addressOrChannel;
288
+ if (PeerAddress.isGroup(address)) {
289
+ if (!this.#channels.hasChannel(address)) {
290
+ // Ensure that we have a group channel
291
+ await this.#createGroupChannel(address);
292
+ }
293
+ return new DedicatedChannelExchangeProvider(this.#exchanges, this.#channels.getChannel(address));
294
+ }
281
295
  let initiallyConnected = this.#channels.hasChannel(address);
282
296
  return new ReconnectableExchangeProvider(this.#exchanges, this.#channels, address, async () => {
283
297
  if (!initiallyConnected && !this.#channels.hasChannel(address)) {
@@ -620,6 +634,27 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
620
634
  }
621
635
  }
622
636
 
637
+ async #createGroupChannel(address: PeerAddress) {
638
+ const groupId = GroupId.fromNodeId(address.nodeId);
639
+ GroupId.assertGroupId(groupId);
640
+ const multicastAddress = this.#sessions.fabricFor(address).groups.multicastAddressFor(groupId);
641
+
642
+ const operationalInterface = this.#netInterfaces.interfaceFor(ChannelType.UDP, multicastAddress);
643
+ if (operationalInterface === undefined) {
644
+ throw new PairRetransmissionLimitReachedError(`IPv6 interface not initialized`);
645
+ }
646
+ const operationalChannel = await operationalInterface.openChannel({
647
+ type: ChannelType.UDP,
648
+ ip: multicastAddress,
649
+ port: STANDARD_MATTER_PORT,
650
+ });
651
+
652
+ const session = this.#sessions.groupSessionForAddress(address);
653
+ const channel = new MessageChannel(operationalChannel, session);
654
+ await this.#channels.setChannel(address, channel);
655
+ return channel;
656
+ }
657
+
623
658
  /** Pair with an operational device (already commissioned) and establish a CASE session. */
624
659
  async #pair(
625
660
  address: PeerAddress,
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { AsyncObservable, Channel, Environment, Environmental, Logger, MatterError } from "#general";
8
8
  import { PeerAddress, PeerAddressMap } from "#peer/PeerAddress.js";
9
- import { SecureSession } from "../session/SecureSession.js";
9
+ import { NodeSession } from "../session/NodeSession.js";
10
10
  import { Session } from "../session/Session.js";
11
11
  import { MessageChannel } from "./ExchangeManager.js";
12
12
 
@@ -91,10 +91,9 @@ export class ChannelManager {
91
91
  * Returns the last established session for a Fabric and Node
92
92
  */
93
93
  getChannelForSession(session: Session) {
94
- if (session.isSecure && !session.isPase) {
95
- const secureSession = session as SecureSession;
96
- const fabric = secureSession.fabric;
97
- const nodeId = secureSession.peerNodeId;
94
+ if (NodeSession.is(session) && !session.isPase) {
95
+ const fabric = session.fabric;
96
+ const nodeId = session.peerNodeId;
98
97
  if (fabric === undefined) {
99
98
  return this.#paseChannels.get(session);
100
99
  }
@@ -142,12 +141,11 @@ export class ChannelManager {
142
141
  }
143
142
 
144
143
  async getOrCreateChannel(byteArrayChannel: Channel<Uint8Array>, session: Session) {
145
- if (!session.isSecure) {
144
+ if (!NodeSession.is(session)) {
146
145
  return this.getOrCreateAsPaseChannel(byteArrayChannel, session);
147
146
  }
148
- const secureSession = session as SecureSession;
149
- const fabric = secureSession.fabric;
150
- const nodeId = secureSession.peerNodeId;
147
+ const fabric = session.fabric;
148
+ const nodeId = session.peerNodeId;
151
149
  if (fabric === undefined) {
152
150
  return this.getOrCreateAsPaseChannel(byteArrayChannel, session);
153
151
  }
@@ -15,18 +15,18 @@ import {
15
15
  MatterAggregateError,
16
16
  MatterError,
17
17
  MatterFlowError,
18
- NotImplementedError,
19
18
  ObserverGroup,
20
19
  TransportInterface,
21
20
  TransportInterfaceSet,
22
21
  UdpInterface,
22
+ UnexpectedDataError,
23
23
  } from "#general";
24
24
  import { PeerAddress } from "#peer/PeerAddress.js";
25
25
  import { NodeId, SECURE_CHANNEL_PROTOCOL_ID, SecureMessageType } from "#types";
26
- import { Message, MessageCodec, SessionType } from "../codec/MessageCodec.js";
26
+ import { DecodedMessage, Message, MessageCodec, SessionType } from "../codec/MessageCodec.js";
27
27
  import { SecureChannelMessenger } from "../securechannel/SecureChannelMessenger.js";
28
28
  import { SecureChannelProtocol } from "../securechannel/SecureChannelProtocol.js";
29
- import { SecureSession } from "../session/SecureSession.js";
29
+ import { NodeSession } from "../session/NodeSession.js";
30
30
  import { Session } from "../session/Session.js";
31
31
  import { SessionManager, UNICAST_UNSECURE_SESSION_ID } from "../session/SessionManager.js";
32
32
  import { ChannelManager } from "./ChannelManager.js";
@@ -73,7 +73,7 @@ export class MessageChannel implements Channel<Message> {
73
73
  return this.channel.maxPayloadSize;
74
74
  }
75
75
 
76
- send(message: Message, logContext?: ExchangeLogContext): Promise<void> {
76
+ async send(message: Message, logContext?: ExchangeLogContext) {
77
77
  logger.debug("Message »", MessageCodec.messageDiagnostics(message, logContext));
78
78
  const packet = this.session.encode(message);
79
79
  const bytes = MessageCodec.encodePacket(packet);
@@ -83,7 +83,7 @@ export class MessageChannel implements Channel<Message> {
83
83
  );
84
84
  }
85
85
 
86
- return this.channel.send(bytes);
86
+ return await this.channel.send(bytes);
87
87
  }
88
88
 
89
89
  get name() {
@@ -202,11 +202,13 @@ export class ExchangeManager {
202
202
 
203
203
  private async onMessage(channel: Channel<Uint8Array>, messageBytes: Uint8Array) {
204
204
  const packet = MessageCodec.decodePacket(messageBytes);
205
+ const aad = messageBytes.slice(0, messageBytes.length - packet.applicationPayload.length); // Header+Extensions
205
206
 
206
- if (packet.header.sessionType === SessionType.Group)
207
- throw new NotImplementedError("Group messages are not supported");
207
+ const messageId = packet.header.messageId;
208
208
 
209
+ let isDuplicate: boolean;
209
210
  let session: Session | undefined;
211
+ let message: DecodedMessage | undefined;
210
212
  if (packet.header.sessionType === SessionType.Unicast) {
211
213
  if (packet.header.sessionId === UNICAST_UNSECURE_SESSION_ID) {
212
214
  if (this.#closing) return;
@@ -219,35 +221,46 @@ export class ExchangeManager {
219
221
  } else {
220
222
  session = this.#sessionManager.getSession(packet.header.sessionId);
221
223
  }
224
+
225
+ if (session === undefined) {
226
+ throw new MatterFlowError(
227
+ `Cannot find a session for ID ${packet.header.sessionId}${
228
+ packet.header.sourceNodeId !== undefined
229
+ ? ` and source NodeId ${packet.header.sourceNodeId}`
230
+ : ""
231
+ }`,
232
+ );
233
+ }
234
+
235
+ message = session.decode(packet, aad);
236
+
237
+ try {
238
+ session.updateMessageCounter(messageId);
239
+ isDuplicate = false;
240
+ } catch (e) {
241
+ DuplicateMessageError.accept(e);
242
+ isDuplicate = true;
243
+ }
222
244
  } else if (packet.header.sessionType === SessionType.Group) {
223
245
  if (this.#closing) return;
224
- if (packet.header.sourceNodeId !== undefined) {
225
- //session = this.sessionManager.findGroupSession(packet.header.destGroupId, packet.header.sessionId);
246
+ if (packet.header.sourceNodeId === undefined) {
247
+ throw new UnexpectedDataError("Group session message must include a source NodeId");
226
248
  }
227
- // if (packet.header.destGroupId !== undefined) { ???
228
- }
229
249
 
230
- if (session === undefined) {
231
- throw new MatterFlowError(
232
- `Cannot find a session for ID ${packet.header.sessionId}${
233
- packet.header.sourceNodeId !== undefined ? ` and source NodeId ${packet.header.sourceNodeId}` : ""
234
- }`,
235
- );
236
- }
237
-
238
- const messageId = packet.header.messageId;
250
+ let key: Uint8Array;
251
+ ({ session, message, key } = this.#sessionManager.groupSessionFromPacket(packet, aad));
239
252
 
240
- let isDuplicate;
241
- try {
242
- session.updateMessageCounter(packet.header.messageId, packet.header.sourceNodeId);
243
- isDuplicate = false;
244
- } catch (e) {
245
- DuplicateMessageError.accept(e);
246
- isDuplicate = true;
253
+ try {
254
+ session.updateMessageCounter(messageId, packet.header.sourceNodeId, key);
255
+ isDuplicate = false;
256
+ } catch (e) {
257
+ DuplicateMessageError.accept(e);
258
+ isDuplicate = true;
259
+ }
260
+ } else {
261
+ throw new MatterFlowError(`Unsupported session type: ${packet.header.sessionType}`);
247
262
  }
248
263
 
249
- const aad = messageBytes.slice(0, messageBytes.length - packet.applicationPayload.length); // Header+Extensions
250
- const message = session.decode(packet, aad);
251
264
  const exchangeIndex = message.payloadHeader.isInitiatorMessage
252
265
  ? message.payloadHeader.exchangeId
253
266
  : message.payloadHeader.exchangeId | 0x10000;
@@ -343,9 +356,12 @@ export class ExchangeManager {
343
356
  throw new MatterFlowError(`Unsupported protocol ${message.payloadHeader.protocolId}`);
344
357
  }
345
358
  if (isDuplicate) {
346
- logger.info(
347
- `Ignoring duplicate message ${messageId} (requires no ack) for protocol ${message.payloadHeader.protocolId} on channel ${channel.name}`,
348
- );
359
+ if (message.packetHeader.destGroupId === undefined) {
360
+ // Duplicate Non-Group messages are still interesting to log to know them
361
+ logger.info(
362
+ `Ignoring duplicate message ${messageId} (requires no ack) for protocol ${message.payloadHeader.protocolId} on channel ${channel.name}`,
363
+ );
364
+ }
349
365
  return;
350
366
  } else {
351
367
  logger.info(
@@ -365,12 +381,12 @@ export class ExchangeManager {
365
381
  return;
366
382
  }
367
383
  const { session } = exchange;
368
- if (session.isSecure && session.closingAfterExchangeFinished) {
384
+ if (NodeSession.is(session) && session.closingAfterExchangeFinished) {
369
385
  logger.debug(
370
386
  `Exchange index ${exchangeIndex} Session ${session.name} is already marked for closure. Close session now.`,
371
387
  );
372
388
  try {
373
- await this.#closeSession(session as SecureSession);
389
+ await this.#closeSession(session);
374
390
  } catch (error) {
375
391
  logger.error(`Error closing session ${session.name}. Ignoring.`, error);
376
392
  }
@@ -378,7 +394,7 @@ export class ExchangeManager {
378
394
  this.#exchanges.delete(exchangeIndex);
379
395
  }
380
396
 
381
- async #closeSession(session: SecureSession) {
397
+ async #closeSession(session: NodeSession) {
382
398
  const sessionId = session.id;
383
399
  const sessionName = session.name;
384
400
 
@@ -18,8 +18,16 @@ import {
18
18
  Timer,
19
19
  createPromise,
20
20
  } from "#general";
21
- import { NodeId, SECURE_CHANNEL_PROTOCOL_ID, SecureMessageType, StatusCode, StatusResponseError } from "#types";
22
- import { Message, MessageCodec, SessionType } from "../codec/MessageCodec.js";
21
+ import { GroupSession } from "#session/index.js";
22
+ import {
23
+ GroupId,
24
+ NodeId,
25
+ SECURE_CHANNEL_PROTOCOL_ID,
26
+ SecureMessageType,
27
+ StatusCode,
28
+ StatusResponseError,
29
+ } from "#types";
30
+ import { Message, MessageCodec, PacketHeader, SessionType } from "../codec/MessageCodec.js";
23
31
  import { SecureChannelProtocol } from "../securechannel/SecureChannelProtocol.js";
24
32
  import {
25
33
  SESSION_ACTIVE_INTERVAL_MS,
@@ -404,18 +412,43 @@ export class MessageExchange {
404
412
  }
405
413
  }
406
414
 
407
- // TODO Add support to also send controlMessages for Group messages, use different messagecounter!
408
- const message: Message = {
409
- packetHeader: {
415
+ let packetHeader: PacketHeader;
416
+ if (this.session.type === SessionType.Unicast) {
417
+ packetHeader = {
410
418
  sessionId: this.#peerSessionId,
411
- sessionType: SessionType.Unicast, // TODO: support multicast/groups
419
+ sessionType: SessionType.Unicast,
412
420
  messageId: await this.session.getIncrementedMessageCounter(),
413
421
  destNodeId: this.#peerNodeId,
414
422
  sourceNodeId: this.#nodeId,
415
423
  hasPrivacyEnhancements: false,
416
424
  isControlMessage: false,
417
425
  hasMessageExtensions: false,
418
- },
426
+ };
427
+ } else if (this.session.type === SessionType.Group) {
428
+ const session = this.session;
429
+ if (!GroupSession.is(session)) {
430
+ throw new InternalError("Session is not a GroupSession, but session type is Group.");
431
+ }
432
+ const destGroupId = GroupId.fromNodeId(this.#peerNodeId!); // TODO !!! Where get from?
433
+ if (destGroupId === 0) {
434
+ throw new InternalError(`Invalid GroupId extracted from NodeId ${this.#peerNodeId}`);
435
+ }
436
+ packetHeader = {
437
+ sessionId: this.#peerSessionId,
438
+ sessionType: SessionType.Group,
439
+ messageId: await session.getIncrementedMessageCounter(),
440
+ destGroupId,
441
+ sourceNodeId: this.#nodeId, // We are the source node, so use our NodeId
442
+ hasPrivacyEnhancements: false,
443
+ isControlMessage: false,
444
+ hasMessageExtensions: false,
445
+ };
446
+ } else {
447
+ throw new InternalError(`Unknown session type: ${this.session.type}`);
448
+ }
449
+
450
+ const message: Message = {
451
+ packetHeader,
419
452
  payloadHeader: {
420
453
  exchangeId: this.#exchangeId,
421
454
  protocolId:
@@ -466,6 +499,8 @@ export class MessageExchange {
466
499
  let timeout: number;
467
500
  if (options?.timeoutMs !== undefined) {
468
501
  timeout = options.timeoutMs;
502
+ } else if (this.#messagesQueue.size > 0) {
503
+ timeout = 0; // If we have messages in the queue, we can return them immediately
469
504
  } else {
470
505
  switch (this.channel.type) {
471
506
  case "tcp":
@@ -21,7 +21,7 @@ export abstract class MessageReceptionState {
21
21
 
22
22
  /**
23
23
  * Implements a message reception state for encrypted messages without rollover.
24
- * A counter in the range [(max_message_counter + 1) to (232 - 1)] SHALL be considered new, and cause the
24
+ * A counter in the range [(max_message_counter + 1) to (2^31 - 1)] SHALL be considered new, and cause the
25
25
  * max_message_counter value to be updated.
26
26
  * Message counters within the range of the bitmap SHALL be considered duplicate if the corresponding bit
27
27
  * offset is set to true. All other message counters SHALL be considered duplicate.
@@ -121,7 +121,7 @@ export class MessageReceptionStateEncryptedWithoutRollover extends MessageRecept
121
121
  }
122
122
 
123
123
  const diff = this.calculateDiff(messageCounter);
124
- // A counter in the range [(max_message_counter + 1) to (232 - 1)] SHALL be considered new, and cause the
124
+ // A counter in the range [(max_message_counter + 1) to (2^31 - 1)] SHALL be considered new, and cause the
125
125
  // max_message_counter value to be updated.
126
126
  // Message counters within the range of the bitmap SHALL be considered duplicate if the corresponding bit
127
127
  // offset is set to true. All other message counters SHALL be considered duplicate.
@@ -19,7 +19,7 @@ import {
19
19
  import { Message } from "../codec/MessageCodec.js";
20
20
  import { MessageExchange } from "../protocol/MessageExchange.js";
21
21
  import { ProtocolHandler } from "../protocol/ProtocolHandler.js";
22
- import { assertSecureSession } from "../session/SecureSession.js";
22
+ import { SecureSession } from "../session/SecureSession.js";
23
23
  import { CaseServer } from "../session/case/CaseServer.js";
24
24
  import { MaximumPasePairingErrorsReachedError, PaseServer } from "../session/pase/PaseServer.js";
25
25
  import { ChannelStatusResponseError, SecureChannelMessenger } from "./SecureChannelMessenger.js";
@@ -79,7 +79,7 @@ export class StatusReportOnlySecureChannelProtocol implements ProtocolHandler {
79
79
  }
80
80
 
81
81
  const { session } = exchange;
82
- assertSecureSession(session);
82
+ SecureSession.assert(session);
83
83
  logger.debug(`Peer requested to close session ${session.name}. Remove session now.`);
84
84
  // TODO: and do more - see Core Specs 5.5
85
85
  await session.destroy(false, false);