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 : #pragma once
18 :
19 : #include "ServerClusterInterface.h"
20 : #include <app/server-cluster/ServerClusterInterfaceRegistry.h>
21 :
22 : namespace chip {
23 : namespace app {
24 :
25 : /// This class specializes ServerClusterInterfaceRegistry to register ServerClusterInterface references
26 : /// that are limited to a single endpoint. In other words, GetPaths() must return path(s) in the same
27 : /// endpoint.
28 : /// The assumption that every ServerClusterInterface registered is limited to a single endpoint
29 : /// allows us to provide additional helper methods such as `ClustersOnEndpoint()` and `UnregisterAllFromEndpoint()`.
30 : class SingleEndpointServerClusterRegistry : public ServerClusterInterfaceRegistry
31 : {
32 : public:
33 : /// represents an iterable list of clusters
34 : class ClustersList
35 : {
36 : public:
37 : class Iterator
38 : {
39 : public:
40 35940 : Iterator(ServerClusterRegistration * interface, EndpointId endpoint) : mEndpointId(endpoint), mRegistration(interface)
41 : {
42 35940 : if (mRegistration != nullptr)
43 : {
44 16 : mSpan = interface->serverClusterInterface->GetPaths();
45 : }
46 35940 : AdvanceUntilMatchingEndpoint();
47 35940 : }
48 :
49 208 : Iterator & operator++()
50 : {
51 208 : if (!mSpan.empty())
52 : {
53 208 : mSpan = mSpan.SubSpan(1);
54 : }
55 208 : AdvanceUntilMatchingEndpoint();
56 208 : return *this;
57 : }
58 2 : bool operator==(const Iterator & other) const { return mRegistration == other.mRegistration; }
59 18174 : bool operator!=(const Iterator & other) const { return mRegistration != other.mRegistration; }
60 208 : ClusterId operator*() { return mSpan.begin()->mClusterId; }
61 :
62 : private:
63 : const EndpointId mEndpointId;
64 : ServerClusterRegistration * mRegistration;
65 : Span<const ConcreteClusterPath> mSpan;
66 :
67 36148 : void AdvanceUntilMatchingEndpoint()
68 : {
69 40353 : while (mRegistration != nullptr)
70 : {
71 4413 : if (mSpan.empty())
72 : {
73 2205 : mRegistration = mRegistration->next;
74 2205 : if (mRegistration != nullptr)
75 : {
76 2189 : mSpan = mRegistration->serverClusterInterface->GetPaths();
77 : }
78 2205 : continue;
79 : }
80 2208 : if (mSpan.begin()->mEndpointId == mEndpointId)
81 : {
82 208 : return;
83 : }
84 :
85 : // need to keep searching
86 2000 : mSpan = mSpan.SubSpan(1);
87 : }
88 : }
89 : };
90 :
91 17968 : constexpr ClustersList(ServerClusterRegistration * start, EndpointId endpointId) : mEndpointId(endpointId), mStart(start) {}
92 17968 : Iterator begin() { return { mStart, mEndpointId }; }
93 17972 : Iterator end() { return { nullptr, mEndpointId }; }
94 :
95 : private:
96 : const EndpointId mEndpointId;
97 : ServerClusterRegistration * mStart;
98 : };
99 :
100 184 : ~SingleEndpointServerClusterRegistry() = default;
101 :
102 : /// Add the given entry to the registry.
103 : /// NOTE the requirement of entries to be part of the same endpoint.
104 : ///
105 : /// Requirements:
106 : /// - entry MUST NOT be part of any other registration
107 : /// - paths MUST be part of the same endpoint
108 : ///
109 : /// - LIFETIME of entry must outlive the Registry (or entry must be unregistered)
110 : ///
111 : /// There can be only a single registration for a given `endpointId/clusterId` path.
112 : [[nodiscard]] CHIP_ERROR Register(ServerClusterRegistration & entry);
113 :
114 : /// Provides a list of clusters that are registered for the given endpoint.
115 : ///
116 : /// ClustersList points inside the internal registrations of the registry, so
117 : /// the list is only valid as long as the registry is not modified.
118 : ClustersList ClustersOnEndpoint(EndpointId endpointId);
119 :
120 : /// Unregister all registrations for the given endpoint.
121 : void UnregisterAllFromEndpoint(EndpointId endpointId,
122 : ClusterShutdownType clusterShutdownType = ClusterShutdownType::kClusterShutdown);
123 : };
124 :
125 : } // namespace app
126 : } // namespace chip
|