Line data Source code
1 : /*
2 : * Copyright (c) 2025 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #include <app/server-cluster/SingleEndpointServerClusterRegistry.h>
18 :
19 : #include <app/ConcreteClusterPath.h>
20 : #include <app/server-cluster/ServerClusterInterface.h>
21 : #include <lib/core/CHIPError.h>
22 : #include <lib/core/DataModelTypes.h>
23 : #include <lib/support/CHIPMem.h>
24 : #include <lib/support/CodeUtils.h>
25 : #include <optional>
26 :
27 : namespace chip {
28 : namespace app {
29 :
30 1028 : CHIP_ERROR SingleEndpointServerClusterRegistry::Register(ServerClusterRegistration & entry)
31 : {
32 1028 : Span<const ConcreteClusterPath> paths = entry.serverClusterInterface->GetPaths();
33 1028 : VerifyOrReturnError(!paths.empty(), CHIP_ERROR_INVALID_ARGUMENT);
34 :
35 : // Codegen registry requirements (so that we can support endpoint unregistration): every
36 : // path must belong to the same endpoint id.
37 2061 : for (const ConcreteClusterPath & path : paths)
38 : {
39 1035 : VerifyOrReturnError(path.mEndpointId == paths[0].mEndpointId, CHIP_ERROR_INVALID_ARGUMENT);
40 : }
41 :
42 1026 : return ServerClusterInterfaceRegistry::Register(entry);
43 : }
44 :
45 17978 : SingleEndpointServerClusterRegistry::ClustersList SingleEndpointServerClusterRegistry::ClustersOnEndpoint(EndpointId endpointId)
46 : {
47 17978 : return { mRegistrations, endpointId };
48 : }
49 :
50 24 : void SingleEndpointServerClusterRegistry::UnregisterAllFromEndpoint(EndpointId endpointId)
51 : {
52 24 : ServerClusterRegistration * prev = nullptr;
53 24 : ServerClusterRegistration * current = mRegistrations;
54 2179 : while (current != nullptr)
55 : {
56 : // Requirements for Paths:
57 : // - GetPaths() MUST be non-empty
58 : // - GetPaths() MUST belong to the same endpoint
59 : // Loop below relies on that: if the endpoint matches, it can be removed
60 2155 : auto paths = current->serverClusterInterface->GetPaths();
61 2155 : if (paths.empty() || paths.front().mEndpointId == endpointId)
62 : {
63 406 : if (mCachedInterface == current->serverClusterInterface)
64 : {
65 5 : mCachedInterface = nullptr;
66 : }
67 406 : if (prev == nullptr)
68 : {
69 35 : mRegistrations = current->next;
70 : }
71 : else
72 : {
73 371 : prev->next = current->next;
74 : }
75 406 : ServerClusterRegistration * actual_next = current->next;
76 :
77 406 : current->next = nullptr; // Make sure current does not look like part of a list.
78 406 : if (mContext.has_value())
79 : {
80 1 : current->serverClusterInterface->Shutdown();
81 : }
82 :
83 406 : current = actual_next;
84 : }
85 : else
86 : {
87 1749 : prev = current;
88 1749 : current = current->next;
89 : }
90 : }
91 24 : }
92 :
93 : } // namespace app
94 : } // namespace chip
|