From e3a109091f55878d80e3dcfc1a9dfa6a42c6e2e2 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Thu, 26 Jun 2025 13:19:33 +0200 Subject: [PATCH 1/3] Fix Groups implementation to pass the new G 2.2 python test --- .../GroupKeyManagementServer.ts | 16 +++++++++++++--- .../node/src/behaviors/groups/GroupsServer.ts | 9 ++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts index 6f3e350cc2..bbdacfa078 100644 --- a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts +++ b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts @@ -430,6 +430,16 @@ export class GroupKeyManagementServer extends GroupKeyManagementBehavior { } this.state.groupTable[existingGroupIndex].groupName = groupName; } else { + if ( + this.state.groupTable.filter(({ fabricIndex }) => fabricIndex === fabricIndex).length >= + this.state.maxGroupsPerFabric + ) { + throw new StatusResponseError( + `Too many groups for fabric ${fabricIndex}, maximum is ${this.state.maxGroupsPerFabric}`, + StatusCode.ResourceExhausted, + ); + } + // Create a new group entry this.state.groupTable.push({ groupId, @@ -454,7 +464,8 @@ export class GroupKeyManagementServer extends GroupKeyManagementBehavior { const fabricIndex = fabric.fabricIndex; // Remove the endpoint from all groups - for (const entry of groupTable) { + for (let i = groupTable.length - 1; i >= 0; i--) { + const entry = groupTable[i]; if (entry.fabricIndex !== fabricIndex || (groupId !== undefined && entry.groupId !== groupId)) { continue; } @@ -463,8 +474,7 @@ export class GroupKeyManagementServer extends GroupKeyManagementBehavior { if (entry.endpoints.length === 1 && entry.endpoints[0] === endpointId) { const groupId = entry.groupId; // If no endpoints left, remove the group entry - const index = groupTable.indexOf(entry); - groupTable.splice(index, 1); + groupTable.splice(i, 1); fabric.groups.endpoints.delete(groupId); } else { entry.endpoints = entry.endpoints.filter(id => id !== endpointId); diff --git a/packages/node/src/behaviors/groups/GroupsServer.ts b/packages/node/src/behaviors/groups/GroupsServer.ts index 0e73b5b6b8..d66e5db0ea 100644 --- a/packages/node/src/behaviors/groups/GroupsServer.ts +++ b/packages/node/src/behaviors/groups/GroupsServer.ts @@ -9,7 +9,7 @@ import { IdentifyBehavior } from "#behaviors/identify"; import { Groups } from "#clusters/groups"; import { Endpoint } from "#endpoint/Endpoint.js"; import { RootEndpoint } from "#endpoints/root"; -import { Logger } from "#general"; +import { InternalError, Logger } from "#general"; import { AccessLevel } from "#model"; import { Command, @@ -21,14 +21,10 @@ import { TlvObject, TlvString, } from "#types"; -import { InternalError } from "@matter/general"; import { GroupsBehavior } from "./GroupsBehavior.js"; const logger = Logger.get("GroupsServer"); -// We enable group names by default -const GroupsBase = GroupsBehavior.with(Groups.Feature.GroupNames); - /** * Monkey patching Tlv Structure of addGroup* commands to prevent data validation of the groupName field to be * handled as ConstraintError because we need to return a special error. @@ -58,6 +54,9 @@ Groups.Cluster.commands = { ), }; +// We enable group names by default +const GroupsBase = GroupsBehavior.with(Groups.Feature.GroupNames); + /** * This is the default server implementation of {@link GroupsBehavior}. */ From 3c946455ea996432a3bf2b9fb8d97e13690eebc9 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Thu, 26 Jun 2025 13:25:36 +0200 Subject: [PATCH 2/3] Update packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../behaviors/group-key-management/GroupKeyManagementServer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts index bbdacfa078..1b2a20bcc7 100644 --- a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts +++ b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts @@ -431,7 +431,7 @@ export class GroupKeyManagementServer extends GroupKeyManagementBehavior { this.state.groupTable[existingGroupIndex].groupName = groupName; } else { if ( - this.state.groupTable.filter(({ fabricIndex }) => fabricIndex === fabricIndex).length >= + this.state.groupTable.filter(({ fabricIndex: entryFabricIndex }) => entryFabricIndex === fabricIndex).length >= this.state.maxGroupsPerFabric ) { throw new StatusResponseError( From 83437bdcc30fcf5c54459e87c91bc6a25a9a5431 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Thu, 26 Jun 2025 13:34:25 +0200 Subject: [PATCH 3/3] linter --- .../group-key-management/GroupKeyManagementServer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts index 1b2a20bcc7..bdf3de37e2 100644 --- a/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts +++ b/packages/node/src/behaviors/group-key-management/GroupKeyManagementServer.ts @@ -431,8 +431,8 @@ export class GroupKeyManagementServer extends GroupKeyManagementBehavior { this.state.groupTable[existingGroupIndex].groupName = groupName; } else { if ( - this.state.groupTable.filter(({ fabricIndex: entryFabricIndex }) => entryFabricIndex === fabricIndex).length >= - this.state.maxGroupsPerFabric + this.state.groupTable.filter(({ fabricIndex: entryFabricIndex }) => entryFabricIndex === fabricIndex) + .length >= this.state.maxGroupsPerFabric ) { throw new StatusResponseError( `Too many groups for fabric ${fabricIndex}, maximum is ${this.state.maxGroupsPerFabric}`,