@matter/node 0.14.0 → 0.14.1-alpha.0-20250606-a9bcd03f9

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 (178) hide show
  1. package/dist/cjs/behavior/Behavior.d.ts +2 -1
  2. package/dist/cjs/behavior/Behavior.d.ts.map +1 -1
  3. package/dist/cjs/behavior/Behavior.js +1 -1
  4. package/dist/cjs/behavior/Behavior.js.map +1 -1
  5. package/dist/cjs/behavior/Transitions.js +2 -2
  6. package/dist/cjs/behavior/Transitions.js.map +1 -1
  7. package/dist/cjs/behavior/context/server/OnlineContext.d.ts +3 -3
  8. package/dist/cjs/behavior/context/server/OnlineContext.d.ts.map +1 -1
  9. package/dist/cjs/behavior/context/server/OnlineContext.js +12 -9
  10. package/dist/cjs/behavior/context/server/OnlineContext.js.map +1 -1
  11. package/dist/cjs/behavior/internal/ClientBehaviorBacking.d.ts +2 -1
  12. package/dist/cjs/behavior/internal/ClientBehaviorBacking.d.ts.map +1 -1
  13. package/dist/cjs/behavior/internal/ClientBehaviorBacking.js.map +1 -1
  14. package/dist/cjs/behavior/system/network/NetworkBehavior.d.ts.map +1 -1
  15. package/dist/cjs/behavior/system/network/NetworkBehavior.js +2 -1
  16. package/dist/cjs/behavior/system/network/NetworkBehavior.js.map +1 -1
  17. package/dist/cjs/behavior/system/network/ServerGroupNetworking.d.ts +18 -0
  18. package/dist/cjs/behavior/system/network/ServerGroupNetworking.d.ts.map +1 -0
  19. package/dist/cjs/behavior/system/network/ServerGroupNetworking.js +150 -0
  20. package/dist/cjs/behavior/system/network/ServerGroupNetworking.js.map +6 -0
  21. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.d.ts.map +1 -1
  22. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.js +25 -7
  23. package/dist/cjs/behavior/system/network/ServerNetworkRuntime.js.map +1 -1
  24. package/dist/cjs/behavior/system/sessions/SessionsBehavior.d.ts.map +1 -1
  25. package/dist/cjs/behavior/system/sessions/SessionsBehavior.js.map +1 -1
  26. package/dist/cjs/behaviors/access-control/AccessControlServer.d.ts.map +1 -1
  27. package/dist/cjs/behaviors/access-control/AccessControlServer.js +18 -12
  28. package/dist/cjs/behaviors/access-control/AccessControlServer.js.map +1 -1
  29. package/dist/cjs/behaviors/color-control/ColorControlServer.d.ts +4 -4
  30. package/dist/cjs/behaviors/color-control/ColorControlServer.d.ts.map +1 -1
  31. package/dist/cjs/behaviors/color-control/ColorControlServer.js +3 -3
  32. package/dist/cjs/behaviors/color-control/ColorControlServer.js.map +1 -1
  33. package/dist/cjs/behaviors/general-commissioning/GeneralCommissioningServer.d.ts.map +1 -1
  34. package/dist/cjs/behaviors/general-commissioning/GeneralCommissioningServer.js +5 -4
  35. package/dist/cjs/behaviors/general-commissioning/GeneralCommissioningServer.js.map +1 -1
  36. package/dist/cjs/behaviors/general-commissioning/ServerNodeFailsafeContext.d.ts +1 -1
  37. package/dist/cjs/behaviors/general-commissioning/ServerNodeFailsafeContext.d.ts.map +1 -1
  38. package/dist/cjs/behaviors/group-key-management/GroupKeyManagementServer.d.ts +27 -4
  39. package/dist/cjs/behaviors/group-key-management/GroupKeyManagementServer.d.ts.map +1 -1
  40. package/dist/cjs/behaviors/group-key-management/GroupKeyManagementServer.js +340 -21
  41. package/dist/cjs/behaviors/group-key-management/GroupKeyManagementServer.js.map +2 -2
  42. package/dist/cjs/behaviors/groups/GroupsServer.d.ts +19 -3
  43. package/dist/cjs/behaviors/groups/GroupsServer.d.ts.map +1 -1
  44. package/dist/cjs/behaviors/groups/GroupsServer.js +138 -1
  45. package/dist/cjs/behaviors/groups/GroupsServer.js.map +2 -2
  46. package/dist/cjs/behaviors/level-control/LevelControlServer.d.ts +5 -5
  47. package/dist/cjs/behaviors/level-control/LevelControlServer.d.ts.map +1 -1
  48. package/dist/cjs/behaviors/level-control/LevelControlServer.js +3 -3
  49. package/dist/cjs/behaviors/level-control/LevelControlServer.js.map +1 -1
  50. package/dist/cjs/behaviors/mode-select/ModeSelectServer.d.ts.map +1 -1
  51. package/dist/cjs/behaviors/mode-select/ModeSelectServer.js +3 -3
  52. package/dist/cjs/behaviors/mode-select/ModeSelectServer.js.map +1 -1
  53. package/dist/cjs/behaviors/on-off/OnOffServer.d.ts.map +1 -1
  54. package/dist/cjs/behaviors/on-off/OnOffServer.js +3 -3
  55. package/dist/cjs/behaviors/on-off/OnOffServer.js.map +1 -1
  56. package/dist/cjs/behaviors/operational-credentials/OperationalCredentialsServer.d.ts.map +1 -1
  57. package/dist/cjs/behaviors/operational-credentials/OperationalCredentialsServer.js +14 -8
  58. package/dist/cjs/behaviors/operational-credentials/OperationalCredentialsServer.js.map +1 -1
  59. package/dist/cjs/endpoint/Endpoint.js +1 -1
  60. package/dist/cjs/endpoint/Endpoint.js.map +1 -1
  61. package/dist/cjs/node/Node.d.ts +1 -1
  62. package/dist/cjs/node/Node.d.ts.map +1 -1
  63. package/dist/cjs/node/Node.js +2 -2
  64. package/dist/cjs/node/Node.js.map +1 -1
  65. package/dist/cjs/node/ServerNode.d.ts +1 -1
  66. package/dist/cjs/node/ServerNode.d.ts.map +1 -1
  67. package/dist/cjs/node/ServerNode.js +2 -2
  68. package/dist/cjs/node/ServerNode.js.map +1 -1
  69. package/dist/cjs/node/client/NodePeerAddressStore.d.ts +1 -1
  70. package/dist/cjs/node/client/NodePeerAddressStore.d.ts.map +1 -1
  71. package/dist/cjs/node/server/InteractionServer.d.ts +2 -2
  72. package/dist/cjs/node/server/InteractionServer.d.ts.map +1 -1
  73. package/dist/cjs/node/server/InteractionServer.js +1 -1
  74. package/dist/cjs/node/server/InteractionServer.js.map +1 -1
  75. package/dist/cjs/node/server/ServerSubscription.d.ts +4 -4
  76. package/dist/cjs/node/server/ServerSubscription.d.ts.map +1 -1
  77. package/dist/cjs/node/server/ServerSubscription.js.map +1 -1
  78. package/dist/esm/behavior/Behavior.d.ts +2 -1
  79. package/dist/esm/behavior/Behavior.d.ts.map +1 -1
  80. package/dist/esm/behavior/Behavior.js +2 -2
  81. package/dist/esm/behavior/Behavior.js.map +1 -1
  82. package/dist/esm/behavior/Transitions.js +1 -1
  83. package/dist/esm/behavior/context/server/OnlineContext.d.ts +3 -3
  84. package/dist/esm/behavior/context/server/OnlineContext.d.ts.map +1 -1
  85. package/dist/esm/behavior/context/server/OnlineContext.js +13 -10
  86. package/dist/esm/behavior/context/server/OnlineContext.js.map +1 -1
  87. package/dist/esm/behavior/internal/ClientBehaviorBacking.d.ts +2 -1
  88. package/dist/esm/behavior/internal/ClientBehaviorBacking.d.ts.map +1 -1
  89. package/dist/esm/behavior/internal/ClientBehaviorBacking.js.map +1 -1
  90. package/dist/esm/behavior/system/network/NetworkBehavior.d.ts.map +1 -1
  91. package/dist/esm/behavior/system/network/NetworkBehavior.js +2 -1
  92. package/dist/esm/behavior/system/network/NetworkBehavior.js.map +1 -1
  93. package/dist/esm/behavior/system/network/ServerGroupNetworking.d.ts +18 -0
  94. package/dist/esm/behavior/system/network/ServerGroupNetworking.d.ts.map +1 -0
  95. package/dist/esm/behavior/system/network/ServerGroupNetworking.js +130 -0
  96. package/dist/esm/behavior/system/network/ServerGroupNetworking.js.map +6 -0
  97. package/dist/esm/behavior/system/network/ServerNetworkRuntime.d.ts.map +1 -1
  98. package/dist/esm/behavior/system/network/ServerNetworkRuntime.js +23 -5
  99. package/dist/esm/behavior/system/network/ServerNetworkRuntime.js.map +1 -1
  100. package/dist/esm/behavior/system/sessions/SessionsBehavior.d.ts.map +1 -1
  101. package/dist/esm/behavior/system/sessions/SessionsBehavior.js.map +1 -1
  102. package/dist/esm/behaviors/access-control/AccessControlServer.d.ts.map +1 -1
  103. package/dist/esm/behaviors/access-control/AccessControlServer.js +20 -13
  104. package/dist/esm/behaviors/access-control/AccessControlServer.js.map +1 -1
  105. package/dist/esm/behaviors/color-control/ColorControlServer.d.ts +4 -4
  106. package/dist/esm/behaviors/color-control/ColorControlServer.d.ts.map +1 -1
  107. package/dist/esm/behaviors/color-control/ColorControlServer.js +3 -3
  108. package/dist/esm/behaviors/color-control/ColorControlServer.js.map +1 -1
  109. package/dist/esm/behaviors/general-commissioning/GeneralCommissioningServer.d.ts.map +1 -1
  110. package/dist/esm/behaviors/general-commissioning/GeneralCommissioningServer.js +6 -5
  111. package/dist/esm/behaviors/general-commissioning/GeneralCommissioningServer.js.map +1 -1
  112. package/dist/esm/behaviors/general-commissioning/ServerNodeFailsafeContext.d.ts +1 -1
  113. package/dist/esm/behaviors/general-commissioning/ServerNodeFailsafeContext.d.ts.map +1 -1
  114. package/dist/esm/behaviors/group-key-management/GroupKeyManagementServer.d.ts +27 -4
  115. package/dist/esm/behaviors/group-key-management/GroupKeyManagementServer.d.ts.map +1 -1
  116. package/dist/esm/behaviors/group-key-management/GroupKeyManagementServer.js +342 -23
  117. package/dist/esm/behaviors/group-key-management/GroupKeyManagementServer.js.map +2 -2
  118. package/dist/esm/behaviors/groups/GroupsServer.d.ts +19 -3
  119. package/dist/esm/behaviors/groups/GroupsServer.d.ts.map +1 -1
  120. package/dist/esm/behaviors/groups/GroupsServer.js +147 -1
  121. package/dist/esm/behaviors/groups/GroupsServer.js.map +1 -1
  122. package/dist/esm/behaviors/level-control/LevelControlServer.d.ts +5 -5
  123. package/dist/esm/behaviors/level-control/LevelControlServer.d.ts.map +1 -1
  124. package/dist/esm/behaviors/level-control/LevelControlServer.js +3 -3
  125. package/dist/esm/behaviors/level-control/LevelControlServer.js.map +1 -1
  126. package/dist/esm/behaviors/mode-select/ModeSelectServer.d.ts.map +1 -1
  127. package/dist/esm/behaviors/mode-select/ModeSelectServer.js +3 -3
  128. package/dist/esm/behaviors/mode-select/ModeSelectServer.js.map +1 -1
  129. package/dist/esm/behaviors/on-off/OnOffServer.d.ts.map +1 -1
  130. package/dist/esm/behaviors/on-off/OnOffServer.js +3 -3
  131. package/dist/esm/behaviors/on-off/OnOffServer.js.map +1 -1
  132. package/dist/esm/behaviors/operational-credentials/OperationalCredentialsServer.d.ts.map +1 -1
  133. package/dist/esm/behaviors/operational-credentials/OperationalCredentialsServer.js +15 -9
  134. package/dist/esm/behaviors/operational-credentials/OperationalCredentialsServer.js.map +1 -1
  135. package/dist/esm/endpoint/Endpoint.js +1 -1
  136. package/dist/esm/endpoint/Endpoint.js.map +1 -1
  137. package/dist/esm/node/Node.d.ts +1 -1
  138. package/dist/esm/node/Node.d.ts.map +1 -1
  139. package/dist/esm/node/Node.js +1 -1
  140. package/dist/esm/node/Node.js.map +1 -1
  141. package/dist/esm/node/ServerNode.d.ts +1 -1
  142. package/dist/esm/node/ServerNode.d.ts.map +1 -1
  143. package/dist/esm/node/ServerNode.js +1 -1
  144. package/dist/esm/node/client/NodePeerAddressStore.d.ts +1 -1
  145. package/dist/esm/node/client/NodePeerAddressStore.d.ts.map +1 -1
  146. package/dist/esm/node/server/InteractionServer.d.ts +2 -2
  147. package/dist/esm/node/server/InteractionServer.d.ts.map +1 -1
  148. package/dist/esm/node/server/InteractionServer.js +2 -2
  149. package/dist/esm/node/server/InteractionServer.js.map +1 -1
  150. package/dist/esm/node/server/ServerSubscription.d.ts +4 -4
  151. package/dist/esm/node/server/ServerSubscription.d.ts.map +1 -1
  152. package/dist/esm/node/server/ServerSubscription.js.map +1 -1
  153. package/package.json +7 -7
  154. package/src/behavior/Behavior.ts +2 -2
  155. package/src/behavior/Transitions.ts +1 -1
  156. package/src/behavior/context/server/OnlineContext.ts +21 -19
  157. package/src/behavior/internal/ClientBehaviorBacking.ts +2 -1
  158. package/src/behavior/system/commissioning/CommissioningClient.ts +1 -1
  159. package/src/behavior/system/network/NetworkBehavior.ts +2 -1
  160. package/src/behavior/system/network/ServerGroupNetworking.ts +150 -0
  161. package/src/behavior/system/network/ServerNetworkRuntime.ts +27 -5
  162. package/src/behavior/system/sessions/SessionsBehavior.ts +5 -5
  163. package/src/behaviors/access-control/AccessControlServer.ts +21 -14
  164. package/src/behaviors/color-control/ColorControlServer.ts +4 -4
  165. package/src/behaviors/general-commissioning/GeneralCommissioningServer.ts +8 -7
  166. package/src/behaviors/general-commissioning/ServerNodeFailsafeContext.ts +1 -1
  167. package/src/behaviors/group-key-management/GroupKeyManagementServer.ts +441 -26
  168. package/src/behaviors/groups/GroupsServer.ts +181 -3
  169. package/src/behaviors/level-control/LevelControlServer.ts +5 -5
  170. package/src/behaviors/mode-select/ModeSelectServer.ts +3 -3
  171. package/src/behaviors/on-off/OnOffServer.ts +3 -3
  172. package/src/behaviors/operational-credentials/OperationalCredentialsServer.ts +17 -9
  173. package/src/endpoint/Endpoint.ts +1 -1
  174. package/src/node/Node.ts +1 -1
  175. package/src/node/ServerNode.ts +1 -1
  176. package/src/node/client/NodePeerAddressStore.ts +1 -1
  177. package/src/node/server/InteractionServer.ts +5 -6
  178. package/src/node/server/ServerSubscription.ts +3 -4
@@ -0,0 +1,150 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Construction, Environment, InternalError, Logger, ObserverGroup, UdpInterface } from "#general";
7
+ import { Fabric, FabricManager } from "#protocol";
8
+ import { FabricIndex, GroupId } from "#types";
9
+
10
+ const logger = Logger.get("ServerGroupNetworking");
11
+
12
+ export class ServerGroupNetworking {
13
+ #construction: Construction<ServerGroupNetworking>;
14
+ #udpInterface: UdpInterface;
15
+ #activeGroupMemberships = new Map<FabricIndex, Map<GroupId, string>>();
16
+ #fabricObservers = new Map<FabricIndex, ObserverGroup>();
17
+ #observers = new ObserverGroup(this);
18
+
19
+ get construction() {
20
+ return this.#construction;
21
+ }
22
+
23
+ /**
24
+ * The server group networking is not implemented in the Node.js environment.
25
+ * This class is a placeholder to maintain compatibility with the Matter.js architecture.
26
+ */
27
+ constructor(env: Environment, udpInterface: UdpInterface) {
28
+ this.#udpInterface = udpInterface;
29
+ this.#construction = Construction(this);
30
+ this.#construction.start(env);
31
+ }
32
+
33
+ async [Construction.construct](env: Environment) {
34
+ const fabrics = env.get(FabricManager);
35
+
36
+ for (const fabric of fabrics) {
37
+ if (this.#activeGroupMemberships.has(fabric.fabricIndex)) {
38
+ throw new InternalError("Group transport interfaces already initialized for this fabric.");
39
+ }
40
+ for (const groupId of fabric.groups.groupKeyIdMap.keys()) {
41
+ await this.#addGroupMembership(groupId, fabric);
42
+ }
43
+
44
+ this.#registerFabricGroupObserver(fabric);
45
+ }
46
+
47
+ // When new fabric is added we register for group changes - new fabrics cannot have groups already configured
48
+ this.#observers.on(fabrics.events.added, async fabric => this.#registerFabricGroupObserver(fabric));
49
+
50
+ // When fabric is deleted, we remove the group memberships
51
+ this.#observers.on(fabrics.events.deleted, async fabric => {
52
+ const fabricIndex = fabric.fabricIndex;
53
+ this.#observersForFabric(fabricIndex).close();
54
+ this.#fabricObservers.delete(fabricIndex);
55
+
56
+ const memberships = this.#activeGroupMemberships.get(fabricIndex);
57
+ if (memberships === undefined || memberships.size === 0) {
58
+ this.#activeGroupMemberships.delete(fabricIndex);
59
+ return;
60
+ }
61
+ for (const groupId of memberships.keys()) {
62
+ await this.#dropGroupMembership(groupId, fabric);
63
+ }
64
+ this.#activeGroupMemberships.delete(fabricIndex);
65
+ });
66
+
67
+ this.#observers.on(fabrics.events.updated, async fabric => {
68
+ const fabricIndex = fabric.fabricIndex;
69
+
70
+ this.#observersForFabric(fabricIndex).close();
71
+ this.#fabricObservers.delete(fabricIndex);
72
+ this.#registerFabricGroupObserver(fabric);
73
+
74
+ // Sync (add or remove as needed) by new group configuration
75
+ const { groupKeyIdMap } = fabric.groups;
76
+ for (const groupId of groupKeyIdMap.keys()) {
77
+ await this.#addGroupMembership(groupId, fabric);
78
+ }
79
+ const memberships = this.#activeGroupMemberships.get(fabricIndex) ?? new Map<GroupId, string>();
80
+ if (memberships.size !== 0) {
81
+ for (const groupId of memberships.keys()) {
82
+ if (!groupKeyIdMap.has(groupId)) {
83
+ await this.#dropGroupMembership(groupId, fabric);
84
+ }
85
+ }
86
+ }
87
+ });
88
+ }
89
+
90
+ async #addGroupMembership(groupId: GroupId, fabric: Fabric) {
91
+ const fabricIndex = fabric.fabricIndex;
92
+ const memberships = this.#activeGroupMemberships.get(fabricIndex) ?? new Map<GroupId, string>();
93
+ if (memberships.has(groupId)) {
94
+ return;
95
+ }
96
+ const address = fabric.groups.multicastAddressFor(groupId);
97
+ logger.debug(
98
+ `Adding membership for group ${groupId} on fabric ${fabric.fabricId} (index ${fabricIndex}) with address ${address}`,
99
+ );
100
+ await this.#udpInterface.addMembership(address);
101
+ memberships.set(groupId, address);
102
+ this.#activeGroupMemberships.set(fabricIndex, memberships);
103
+ }
104
+
105
+ async #dropGroupMembership(groupId: GroupId, fabric: Fabric) {
106
+ const fabricIndex = fabric.fabricIndex;
107
+ const memberships = this.#activeGroupMemberships.get(fabricIndex);
108
+ if (memberships === undefined || memberships.size === 0) {
109
+ return;
110
+ }
111
+ const address = fabric.groups.multicastAddressFor(groupId);
112
+ logger.debug(
113
+ `Dropping membership for group ${groupId} on fabric ${fabric.fabricId} (index ${fabricIndex}) with address ${address}`,
114
+ );
115
+ await this.#udpInterface.dropMembership(address);
116
+ memberships.delete(groupId);
117
+ if (!memberships.size) {
118
+ this.#activeGroupMemberships.delete(fabricIndex);
119
+ }
120
+ }
121
+
122
+ #observersForFabric(fabricIndex: FabricIndex) {
123
+ let observers = this.#fabricObservers.get(fabricIndex);
124
+ if (observers === undefined) {
125
+ observers = new ObserverGroup(this);
126
+ this.#fabricObservers.set(fabricIndex, observers);
127
+ }
128
+ return observers;
129
+ }
130
+
131
+ #registerFabricGroupObserver(fabric: Fabric) {
132
+ const fabricIndex = fabric.fabricIndex;
133
+
134
+ const observers = this.#observersForFabric(fabricIndex);
135
+ observers.on(
136
+ fabric.groups.groupKeyIdMap.added,
137
+ async groupId => await this.#addGroupMembership(groupId, fabric),
138
+ );
139
+
140
+ observers.on(fabric.groups.groupKeyIdMap.deleted, async groupId => this.#dropGroupMembership(groupId, fabric));
141
+ }
142
+
143
+ close() {
144
+ this.#construction.close();
145
+ this.#observers.close();
146
+ this.#fabricObservers.forEach(observer => observer.close());
147
+ this.#activeGroupMemberships.clear();
148
+ this.#fabricObservers.clear();
149
+ }
150
+ }
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { SubscriptionBehavior } from "#behavior/system/subscription/index.js";
7
+ import { SubscriptionBehavior } from "#behavior/system/subscription/SubscriptionBehavior.js";
8
8
  import {
9
9
  Construction,
10
10
  InterfaceType,
@@ -20,7 +20,7 @@ import {
20
20
  UdpInterface,
21
21
  } from "#general";
22
22
  import type { ServerNode } from "#node/ServerNode.js";
23
- import { NodePeerAddressStore } from "#node/index.js";
23
+ import { NodePeerAddressStore } from "#node/client/NodePeerAddressStore.js";
24
24
  import { InteractionServer } from "#node/server/InteractionServer.js";
25
25
  import {
26
26
  Ble,
@@ -43,6 +43,7 @@ import { CommissioningServer } from "../commissioning/CommissioningServer.js";
43
43
  import { ProductDescriptionServer } from "../product-description/ProductDescriptionServer.js";
44
44
  import { SessionsBehavior } from "../sessions/SessionsBehavior.js";
45
45
  import { NetworkRuntime } from "./NetworkRuntime.js";
46
+ import { ServerGroupNetworking } from "./ServerGroupNetworking.js";
46
47
 
47
48
  const logger = Logger.get("ServerNetworkRuntime");
48
49
 
@@ -62,8 +63,10 @@ export class ServerNetworkRuntime extends NetworkRuntime {
62
63
  #mdnsBroadcaster?: MdnsInstanceBroadcaster;
63
64
  #bleBroadcaster?: InstanceBroadcaster;
64
65
  #bleTransport?: TransportInterface;
66
+ #ipv6UdpInterface?: UdpInterface;
65
67
  #observers = new ObserverGroup(this);
66
68
  #formerSubscriptionsHandled = false;
69
+ #groupNetworking?: ServerGroupNetworking;
67
70
 
68
71
  override get owner() {
69
72
  return super.owner as ServerNode;
@@ -148,15 +151,15 @@ export class ServerNetworkRuntime extends NetworkRuntime {
148
151
 
149
152
  const port = this.owner.state.network.port;
150
153
  try {
151
- const ipv6Intf = await UdpInterface.create(
154
+ this.#ipv6UdpInterface = await UdpInterface.create(
152
155
  this.owner.env.get(Network),
153
156
  "udp6",
154
157
  port ? port : undefined,
155
158
  netconf.listeningAddressIpv6,
156
159
  );
157
- interfaces.add(ipv6Intf);
160
+ interfaces.add(this.#ipv6UdpInterface);
158
161
 
159
- await this.owner.set({ network: { operationalPort: ipv6Intf.port } });
162
+ await this.owner.set({ network: { operationalPort: this.#ipv6UdpInterface.port } });
160
163
  } catch (error) {
161
164
  NoAddressAvailableError.accept(error);
162
165
  logger.info(`IPv6 UDP interface not created because IPv6 is not available, but required my Matter.`);
@@ -285,6 +288,8 @@ export class ServerNetworkRuntime extends NetworkRuntime {
285
288
  maxPathsPerInvoke: this.owner.state.basicInformation.maxPathsPerInvoke,
286
289
  };
287
290
 
291
+ await this.#initializeGroupNetworking();
292
+
288
293
  // Install our interaction server
289
294
  const interactionServer = new InteractionServer(this.owner, env.get(SessionManager));
290
295
  env.set(InteractionServer, interactionServer);
@@ -359,6 +364,9 @@ export class ServerNetworkRuntime extends NetworkRuntime {
359
364
 
360
365
  await this.owner.prepareRuntimeShutdown();
361
366
 
367
+ this.#groupNetworking?.close();
368
+ this.#groupNetworking = undefined;
369
+
362
370
  // Now all sessions are closed, so we wait for Advertiser to be gone
363
371
  await advertisementShutdown;
364
372
 
@@ -393,4 +401,18 @@ export class ServerNetworkRuntime extends NetworkRuntime {
393
401
  agent.get(SubscriptionBehavior).reestablishFormerSubscriptions(env.get(InteractionServer)),
394
402
  );
395
403
  }
404
+
405
+ async #initializeGroupNetworking() {
406
+ if (this.#groupNetworking) {
407
+ logger.warn("Group networking already initialized, skipping.");
408
+ return;
409
+ }
410
+ if (this.#ipv6UdpInterface === undefined) {
411
+ logger.warn("No IPv6 UDP interface available, skipping group networking initialization.");
412
+ return;
413
+ }
414
+
415
+ this.#groupNetworking = new ServerGroupNetworking(this.owner.env, this.#ipv6UdpInterface);
416
+ await this.#groupNetworking.construction;
417
+ }
396
418
  }
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { EventEmitter, Observable } from "#general";
8
8
  import type { ServerNode } from "#node/ServerNode.js";
9
- import { ExposedFabricInformation, SecureSession, SessionManager, Subscription } from "#protocol";
9
+ import { ExposedFabricInformation, NodeSession, SessionManager, Subscription } from "#protocol";
10
10
  import { NodeId } from "#types";
11
11
  import { NodeLifecycle } from "../../../node/NodeLifecycle.js";
12
12
  import { Behavior } from "../../Behavior.js";
@@ -28,7 +28,7 @@ export class SessionsBehavior extends Behavior {
28
28
  this.reactTo((this.endpoint.lifecycle as NodeLifecycle).offline, this.#enterOfflineMode);
29
29
  }
30
30
 
31
- #convertToExposedSession(session: SecureSession): SessionsBehavior.Session {
31
+ #convertToExposedSession(session: NodeSession): SessionsBehavior.Session {
32
32
  return {
33
33
  name: session.name,
34
34
  nodeId: session.nodeId,
@@ -49,7 +49,7 @@ export class SessionsBehavior extends Behavior {
49
49
  this.reactTo(sessions.subscriptionsChanged, this.#subscriptionsChanged, { lock: true });
50
50
  }
51
51
 
52
- #sessionOpened(session: SecureSession) {
52
+ #sessionOpened(session: NodeSession) {
53
53
  if (session.isPase) {
54
54
  return;
55
55
  }
@@ -58,7 +58,7 @@ export class SessionsBehavior extends Behavior {
58
58
  this.events.opened.emit(exposedSession);
59
59
  }
60
60
 
61
- #sessionClosed(session: SecureSession) {
61
+ #sessionClosed(session: NodeSession) {
62
62
  if (!(session.id in this.state.sessions)) {
63
63
  return;
64
64
  }
@@ -67,7 +67,7 @@ export class SessionsBehavior extends Behavior {
67
67
  this.events.closed.emit(this.#convertToExposedSession(session));
68
68
  }
69
69
 
70
- #subscriptionsChanged(session: SecureSession, subscription: Subscription) {
70
+ #subscriptionsChanged(session: NodeSession, subscription: Subscription) {
71
71
  if (session.isPase) {
72
72
  return;
73
73
  }
@@ -15,6 +15,8 @@ import {
15
15
  AclEndpointContext,
16
16
  FabricManager,
17
17
  IncomingSubjectDescriptor,
18
+ NodeSession,
19
+ SecureSession,
18
20
  } from "#protocol";
19
21
  import {
20
22
  CaseAuthenticatedTag,
@@ -159,7 +161,7 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
159
161
 
160
162
  if (subjects !== null) {
161
163
  for (const subject of subjects) {
162
- if (GroupId(subject) === GroupId.UNSPECIFIED_GROUP_ID) {
164
+ if (GroupId(Number(subject)) === GroupId.NO_GROUP_ID) {
163
165
  throw new StatusResponseError(
164
166
  "Subject must be a valid GroupId for Group ACLs",
165
167
  StatusCode.ConstraintError,
@@ -202,6 +204,21 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
202
204
  }
203
205
  }
204
206
 
207
+ /**
208
+ * Determine and return the adminPassCodeId and adminNodeId from the node that initiated the ACL change.
209
+ * it is either the root node of the fabric or 0 if the session is undefined or a PASE session.
210
+ */
211
+ #adminDataFromSession(session: SecureSession | undefined) {
212
+ if (session === undefined || (NodeSession.is(session) && session.isPase)) {
213
+ return { adminPasscodeId: 0, adminNodeId: null };
214
+ }
215
+ const adminNodeId = session?.associatedFabric.rootNodeId;
216
+ if (adminNodeId === undefined) {
217
+ throw new InternalError("Admin Node ID is undefined, should never happen");
218
+ }
219
+ return { adminPasscodeId: null, adminNodeId };
220
+ }
221
+
205
222
  #handleAccessControlListChange(
206
223
  value: AccessControlTypes.AccessControlEntry[],
207
224
  oldValue: AccessControlTypes.AccessControlEntry[],
@@ -218,12 +235,7 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
218
235
  if (relevantFabricIndex === undefined || this.events.accessControlEntryChanged === undefined) {
219
236
  return;
220
237
  }
221
- const adminPasscodeId = session === undefined || session?.isPase ? 0 : null;
222
- const adminNodeId = adminPasscodeId === null ? session?.associatedFabric.rootNodeId : null;
223
- if (adminNodeId === undefined) {
224
- // Should never happen
225
- return;
226
- }
238
+ const { adminPasscodeId, adminNodeId } = this.#adminDataFromSession(session);
227
239
  const fabricAcls = value.filter(entry => entry.fabricIndex === relevantFabricIndex);
228
240
  const oldFabricAcls = oldValue.filter(entry => entry.fabricIndex === relevantFabricIndex);
229
241
 
@@ -302,12 +314,7 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
302
314
  if (relevantFabricIndex === undefined || this.events.accessControlExtensionChanged === undefined) {
303
315
  return;
304
316
  }
305
- const adminPasscodeId = session === undefined || session?.isPase ? 0 : null;
306
- const adminNodeId = adminPasscodeId === null ? session?.associatedFabric.rootNodeId : null;
307
- if (adminNodeId === undefined) {
308
- // Should never happen
309
- return;
310
- }
317
+ const { adminPasscodeId, adminNodeId } = this.#adminDataFromSession(session);
311
318
 
312
319
  const fabricExtensions = value.filter(entry => entry.fabricIndex === relevantFabricIndex);
313
320
  const oldFabricExtensions = oldValue.filter(entry => entry.fabricIndex === relevantFabricIndex);
@@ -360,7 +367,7 @@ export class AccessControlServer extends AccessControlBehavior.with("Extension")
360
367
  return [AccessLevel.View];
361
368
  }
362
369
 
363
- return this.aclManager.getGrantedPrivileges(context.session, endpoint, location.cluster);
370
+ return this.aclManager.getGrantedPrivileges(context, endpoint, location.cluster);
364
371
  }
365
372
 
366
373
  /**
@@ -4,15 +4,14 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import { Behavior } from "#behavior/Behavior.js";
7
8
  import { ActionContext } from "#behavior/context/ActionContext.js";
8
- import { Behavior } from "#behavior/index.js";
9
9
  import { Transitions } from "#behavior/Transitions.js";
10
10
  import { GeneralDiagnosticsBehavior } from "#behaviors/general-diagnostics";
11
11
  import { OnOffServer } from "#behaviors/on-off";
12
12
  import { ColorControl } from "#clusters/color-control";
13
13
  import { GeneralDiagnostics } from "#clusters/general-diagnostics";
14
14
  import { Endpoint } from "#endpoint/Endpoint.js";
15
- import { RootEndpoint } from "#endpoints/root";
16
15
  import {
17
16
  addValueWithOverflow,
18
17
  AsyncObservable,
@@ -21,6 +20,7 @@ import {
21
20
  Logger,
22
21
  MaybePromise,
23
22
  } from "#general";
23
+ import { ServerNode } from "#node/ServerNode.js";
24
24
  import { Val } from "#protocol";
25
25
  import { ClusterType, StatusCode, StatusResponseError, TypeFromPartialBitSchema } from "#types";
26
26
  import { ColorControlBehavior } from "./ColorControlBehavior.js";
@@ -1726,8 +1726,8 @@ export class ColorControlBaseServer extends ColorControlBase {
1726
1726
  }
1727
1727
 
1728
1728
  #getBootReason() {
1729
- const rootEndpoint = this.endpoint.ownerOfType(RootEndpoint);
1730
- if (rootEndpoint !== undefined && rootEndpoint.behaviors.has(GeneralDiagnosticsBehavior)) {
1729
+ const rootEndpoint = this.env.get(ServerNode);
1730
+ if (rootEndpoint.behaviors.has(GeneralDiagnosticsBehavior)) {
1731
1731
  return rootEndpoint.stateOf(GeneralDiagnosticsBehavior).bootReason;
1732
1732
  }
1733
1733
  }
@@ -9,8 +9,8 @@ import { BasicInformationServer } from "#behaviors/basic-information";
9
9
  import { AdministratorCommissioning } from "#clusters/administrator-commissioning";
10
10
  import { GeneralCommissioning } from "#clusters/general-commissioning";
11
11
  import { Logger, MatterFlowError, MaybePromise } from "#general";
12
- import { ServerNode } from "#node/ServerNode.js";
13
- import { assertSecureSession, DeviceCommissioner, FabricManager, SecureSession, SessionManager } from "#protocol";
12
+ import type { ServerNode } from "#node/ServerNode.js";
13
+ import { DeviceCommissioner, FabricManager, GroupSession, NodeSession, SecureSession, SessionManager } from "#protocol";
14
14
  import { GeneralCommissioningBehavior } from "./GeneralCommissioningBehavior.js";
15
15
  import { ServerNodeFailsafeContext } from "./ServerNodeFailsafeContext.js";
16
16
 
@@ -45,7 +45,7 @@ export class GeneralCommissioningServer extends GeneralCommissioningBehavior {
45
45
  }
46
46
 
47
47
  /** As required by Commissioning Flows any new PASE session needs to arm the failsafe for 60s. */
48
- async #handleAddedPaseSessions(session: SecureSession) {
48
+ async #handleAddedPaseSessions(session: NodeSession) {
49
49
  if (
50
50
  !session.isPase || // Only PASE sessions
51
51
  session.fabric !== undefined // That does not have an assigned fabric (can never happen in real usecases)
@@ -60,7 +60,7 @@ export class GeneralCommissioningServer extends GeneralCommissioningBehavior {
60
60
  { breadcrumb, expiryLengthSeconds }: GeneralCommissioning.ArmFailSafeRequest,
61
61
  session: SecureSession,
62
62
  ) {
63
- assertSecureSession(session, "armFailSafe can only be called on a secure session");
63
+ NodeSession.assert(session, "armFailSafe can only be called on a secure session");
64
64
  const commissioner = this.env.get(DeviceCommissioner);
65
65
 
66
66
  try {
@@ -195,10 +195,11 @@ export class GeneralCommissioningServer extends GeneralCommissioningBehavior {
195
195
  }
196
196
 
197
197
  override async commissioningComplete() {
198
- if (this.session.isPase) {
198
+ const session = this.session;
199
+ if ((NodeSession.is(session) && session.isPase) || GroupSession.is(session)) {
199
200
  return {
200
201
  errorCode: GeneralCommissioning.CommissioningError.InvalidAuthentication,
201
- debugText: "Command not executed over CASE session.",
202
+ debugText: "Command must be executed over CASE session.",
202
203
  };
203
204
  }
204
205
 
@@ -211,7 +212,7 @@ export class GeneralCommissioningServer extends GeneralCommissioningBehavior {
211
212
  }
212
213
  const failsafeContext = commissioner.failsafeContext;
213
214
 
214
- assertSecureSession(this.session, "commissioningComplete can only be called on a secure session");
215
+ SecureSession.assert(session, "commissioningComplete can only be called on a secure session");
215
216
 
216
217
  const timedFabric = failsafeContext.associatedFabric?.fabricIndex;
217
218
  if (fabric.fabricIndex !== timedFabric) {
@@ -7,7 +7,7 @@
7
7
  import { NetworkCommissioningBehavior } from "#behaviors/network-commissioning";
8
8
  import { Endpoint } from "#endpoint/Endpoint.js";
9
9
  import { Immutable, Lifecycle, UnsupportedDependencyError } from "#general";
10
- import { ServerNode } from "#node/ServerNode.js";
10
+ import type { ServerNode } from "#node/ServerNode.js";
11
11
  import { Fabric, FabricManager, FailsafeContext } from "#protocol";
12
12
 
13
13
  /**