Line data Source code
1 : /*
2 : * Copyright (c) 2026 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 <cstdint>
20 : #include <cstring>
21 : #include <inet/IPAddress.h>
22 : #include <lib/core/CHIPError.h>
23 : #include <lib/core/DataModelTypes.h>
24 : #include <lib/core/Optional.h>
25 : #include <lib/support/Span.h>
26 :
27 : namespace chip {
28 : namespace Groupcast {
29 :
30 : /**
31 : * @brief Class to store GroupcastTesting event data
32 : *
33 : * This class stores all fields from the GroupcastTesting event,
34 : * including IP addresses as byte arrays for proper storage.
35 : */
36 : class Testing
37 : {
38 : public:
39 : /**
40 : * @brief Test result enum matching GroupcastTestResultEnum from the Groupcast cluster.
41 : * This cannot point to the raw code-generated type due to build deps, so it is copied for convenience.
42 : */
43 : enum Result : uint8_t
44 : {
45 : kSuccess = 0x00,
46 : kGeneralError = 0x01,
47 : kMessageReplay = 0x02,
48 : kFailedAuth = 0x03,
49 : kNoAvailableKey = 0x04,
50 : kSendFailure = 0x05,
51 : };
52 :
53 : static constexpr size_t kIPv6AddressLength = 16; // IPv6 address is 16 bytes
54 :
55 10 : Testing() = default;
56 : ~Testing() = default;
57 :
58 : // Getters for optional fields
59 : const chip::Optional<chip::GroupId> & GetGroupID() const { return mGroupID; }
60 : const chip::Optional<chip::EndpointId> & GetEndpointID() const { return mEndpointID; }
61 : const chip::Optional<chip::ClusterId> & GetClusterID() const { return mClusterID; }
62 : const chip::Optional<uint32_t> & GetElementID() const { return mElementID; }
63 0 : const chip::Optional<bool> & GetAccessAllowed() const { return mAccessAllowed; }
64 :
65 : // Setters for optional fields
66 : void SetGroupID(const chip::Optional<chip::GroupId> & groupID) { mGroupID = groupID; }
67 0 : void SetGroupID(chip::GroupId groupID) { mGroupID = MakeOptional(groupID); }
68 : void ClearGroupID() { mGroupID = chip::Optional<chip::GroupId>(); }
69 :
70 : void SetEndpointID(const chip::Optional<chip::EndpointId> & endpointID) { mEndpointID = endpointID; }
71 0 : void SetEndpointID(chip::EndpointId endpointID) { mEndpointID = MakeOptional(endpointID); }
72 : void ClearEndpointID() { mEndpointID = chip::Optional<chip::EndpointId>(); }
73 :
74 : void SetClusterID(const chip::Optional<chip::ClusterId> & clusterID) { mClusterID = clusterID; }
75 0 : void SetClusterID(chip::ClusterId clusterID) { mClusterID = MakeOptional(clusterID); }
76 : void ClearClusterID() { mClusterID = chip::Optional<chip::ClusterId>(); }
77 :
78 : void SetElementID(const chip::Optional<uint32_t> & elementID) { mElementID = elementID; }
79 0 : void SetElementID(uint32_t elementID) { mElementID = MakeOptional(elementID); }
80 : void ClearElementID() { mElementID = chip::Optional<uint32_t>(); }
81 :
82 : void SetAccessAllowed(const chip::Optional<bool> & accessAllowed) { mAccessAllowed = accessAllowed; }
83 0 : void SetAccessAllowed(bool accessAllowed) { mAccessAllowed = MakeOptional(accessAllowed); }
84 : void ClearAccessAllowed() { mAccessAllowed = chip::Optional<bool>(); }
85 :
86 : // Getters for required fields
87 60 : bool IsEnabled() const { return mEnabled; }
88 : uint8_t GetTestResult() const { return mTestResult; }
89 0 : Result GetTestResultEnum() const { return static_cast<Result>(mTestResult); }
90 17 : chip::FabricIndex GetFabricIndex() const { return mFabricIndex; }
91 0 : bool IsFabricUnderTest(chip::FabricIndex fabricIndex) { return mFabricIndex == fabricIndex; }
92 :
93 : // Setters for required fields
94 4 : void SetEnabled(bool enabled) { mEnabled = enabled; }
95 : void SetTestResult(uint8_t result) { mTestResult = result; }
96 0 : void SetTestResult(Result result) { mTestResult = static_cast<uint8_t>(result); }
97 4 : void SetFabricIndex(chip::FabricIndex fabricIndex) { mFabricIndex = fabricIndex; }
98 :
99 : // IP address getters
100 : chip::ByteSpan GetSourceIpAddress() const { return chip::ByteSpan(mSourceIpAddress, mSourceIpAddressLength); }
101 : chip::ByteSpan GetDestinationIpAddress() const { return chip::ByteSpan(mDestinationIpAddress, mDestinationIpAddressLength); }
102 : bool HasSourceIpAddress() const { return mSourceIpAddressLength > 0; }
103 : bool HasDestinationIpAddress() const { return mDestinationIpAddressLength > 0; }
104 :
105 : /**
106 : * @brief Set source IP address from Inet::IPAddress.
107 : * @param ipAddress IPAddress containing the IPv6 address
108 : */
109 0 : void SetSourceIpAddress(const Inet::IPAddress & ipAddress)
110 : {
111 0 : if (ipAddress.IsIPv6())
112 : {
113 0 : uint8_t * p = mSourceIpAddress;
114 0 : ipAddress.WriteAddress(p);
115 0 : mSourceIpAddressLength = kIPv6AddressLength;
116 : }
117 0 : }
118 :
119 : /**
120 : * @brief Set destination IP address from Inet::IPAddress.
121 : * @param ipAddress IPAddress containing the IPv6 address
122 : */
123 0 : void SetDestinationIpAddress(const Inet::IPAddress & ipAddress)
124 : {
125 0 : if (ipAddress.IsIPv6())
126 : {
127 0 : uint8_t * p = mDestinationIpAddress;
128 0 : ipAddress.WriteAddress(p);
129 0 : mDestinationIpAddressLength = kIPv6AddressLength;
130 : }
131 0 : }
132 :
133 : /**
134 : * @brief Clear source IP address
135 : */
136 : void ClearSourceIpAddress() { mSourceIpAddressLength = 0; }
137 :
138 : /**
139 : * @brief Clear destination IP address
140 : */
141 : void ClearDestinationIpAddress() { mDestinationIpAddressLength = 0; }
142 :
143 : /**
144 : * @brief Template method to convert stored data to event type
145 : * @tparam EventType The event type structure (e.g., Groupcast::Events::GroupcastTesting::Type)
146 : * @param event Output event structure to populate
147 : */
148 : template <typename EventType>
149 0 : void ToEventType(EventType & event) const
150 : {
151 0 : event.groupcastTestResult = static_cast<decltype(event.groupcastTestResult)>(mTestResult);
152 0 : event.fabricIndex = mFabricIndex;
153 0 : event.groupID = mGroupID;
154 0 : event.endpointID = mEndpointID;
155 0 : event.clusterID = mClusterID;
156 0 : event.elementID = mElementID;
157 0 : event.accessAllowed = mAccessAllowed;
158 :
159 0 : if (mSourceIpAddressLength > 0)
160 : {
161 0 : event.sourceIpAddress = MakeOptional(chip::ByteSpan(mSourceIpAddress, mSourceIpAddressLength));
162 : }
163 : else
164 : {
165 0 : event.sourceIpAddress = chip::Optional<chip::ByteSpan>();
166 : }
167 :
168 0 : if (mDestinationIpAddressLength > 0)
169 : {
170 0 : event.destinationIpAddress = MakeOptional(chip::ByteSpan(mDestinationIpAddress, mDestinationIpAddressLength));
171 : }
172 : else
173 : {
174 0 : event.destinationIpAddress = chip::Optional<chip::ByteSpan>();
175 : }
176 0 : }
177 :
178 : /**
179 : * @brief Clear all stored data
180 : */
181 4 : void Clear()
182 : {
183 4 : mSourceIpAddressLength = 0;
184 4 : mDestinationIpAddressLength = 0;
185 4 : mGroupID = chip::Optional<chip::GroupId>();
186 4 : mEndpointID = chip::Optional<chip::EndpointId>();
187 4 : mClusterID = chip::Optional<chip::ClusterId>();
188 4 : mElementID = chip::Optional<uint32_t>();
189 4 : mAccessAllowed = chip::Optional<bool>();
190 4 : mTestResult = 0;
191 4 : }
192 :
193 : private:
194 : bool mEnabled = false;
195 : // IP addresses stored as IPv6 address bytes (16 bytes) in network byte order (RFC 4291)
196 : uint8_t mSourceIpAddress[kIPv6AddressLength];
197 : uint8_t mDestinationIpAddress[kIPv6AddressLength];
198 : size_t mSourceIpAddressLength = 0;
199 : size_t mDestinationIpAddressLength = 0;
200 : // Optional fields
201 : chip::Optional<chip::GroupId> mGroupID;
202 : chip::Optional<chip::EndpointId> mEndpointID;
203 : chip::Optional<chip::ClusterId> mClusterID;
204 : chip::Optional<uint32_t> mElementID;
205 : chip::Optional<bool> mAccessAllowed;
206 : // Required fields
207 : uint8_t mTestResult = 0;
208 : chip::FabricIndex mFabricIndex = kUndefinedFabricIndex;
209 : };
210 :
211 : /**
212 : * @brief Get the singleton Testing instance.
213 : *
214 : * Callers must externally synchronize usage of this function.
215 : *
216 : * @return Reference to the global GroupcastTesting instance
217 : */
218 : Testing & GetTesting();
219 :
220 : } // namespace Groupcast
221 : } // namespace chip
|