• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2019, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * This file includes utilities for manipulate d-bus message.
32  */
33 
34 #ifndef DBUS_MESSAGE_HELPER_HPP_
35 #define DBUS_MESSAGE_HELPER_HPP_
36 
37 #include <array>
38 #include <string>
39 #include <tuple>
40 #include <vector>
41 
42 #include <dbus/dbus.h>
43 
44 #include "common/code_utils.hpp"
45 #include "common/types.hpp"
46 #include "dbus/common/dbus_resources.hpp"
47 #include "dbus/common/types.hpp"
48 
49 namespace otbr {
50 namespace DBus {
51 
52 otbrError DBusMessageEncode(DBusMessageIter *aIter, const otbrError &aError);
53 otbrError DBusMessageExtract(DBusMessageIter *aIter, otbrError &aError);
54 otbrError DBusMessageEncode(DBusMessageIter *aIter, const ActiveScanResult &aScanResult);
55 otbrError DBusMessageExtract(DBusMessageIter *aIter, ActiveScanResult &aScanResult);
56 otbrError DBusMessageEncode(DBusMessageIter *aIter, const EnergyScanResult &aResult);
57 otbrError DBusMessageExtract(DBusMessageIter *aIter, EnergyScanResult &aResult);
58 otbrError DBusMessageEncode(DBusMessageIter *aIter, const LinkModeConfig &aConfig);
59 otbrError DBusMessageExtract(DBusMessageIter *aIter, LinkModeConfig &aConfig);
60 otbrError DBusMessageEncode(DBusMessageIter *aIter, const Ip6Prefix &aPrefix);
61 otbrError DBusMessageExtract(DBusMessageIter *aIter, Ip6Prefix &aPrefix);
62 otbrError DBusMessageEncode(DBusMessageIter *aIter, const ExternalRoute &aRoute);
63 otbrError DBusMessageExtract(DBusMessageIter *aIter, ExternalRoute &aRoute);
64 otbrError DBusMessageEncode(DBusMessageIter *aIter, const OnMeshPrefix &aPrefix);
65 otbrError DBusMessageExtract(DBusMessageIter *aIter, OnMeshPrefix &aPrefix);
66 otbrError DBusMessageEncode(DBusMessageIter *aIter, const MacCounters &aCounters);
67 otbrError DBusMessageExtract(DBusMessageIter *aIter, MacCounters &aCounters);
68 otbrError DBusMessageEncode(DBusMessageIter *aIter, const IpCounters &aCounters);
69 otbrError DBusMessageExtract(DBusMessageIter *aIter, IpCounters &aCounters);
70 otbrError DBusMessageEncode(DBusMessageIter *aIter, const ChildInfo &aChildInfo);
71 otbrError DBusMessageExtract(DBusMessageIter *aIter, ChildInfo &aChildInfo);
72 otbrError DBusMessageEncode(DBusMessageIter *aIter, const NeighborInfo &aNeighborInfo);
73 otbrError DBusMessageExtract(DBusMessageIter *aIter, NeighborInfo &aNeighborInfo);
74 otbrError DBusMessageEncode(DBusMessageIter *aIter, const LeaderData &aLeaderData);
75 otbrError DBusMessageExtract(DBusMessageIter *aIter, LeaderData &aLeaderData);
76 otbrError DBusMessageEncode(DBusMessageIter *aIter, const ChannelQuality &aQuality);
77 otbrError DBusMessageExtract(DBusMessageIter *aIter, ChannelQuality &aQuality);
78 otbrError DBusMessageEncode(DBusMessageIter *aIter, const TxtEntry &aTxtEntry);
79 otbrError DBusMessageExtract(DBusMessageIter *aIter, TxtEntry &aTxtEntry);
80 otbrError DBusMessageEncode(DBusMessageIter *aIter, const SrpServerInfo::Registration &aRegistration);
81 otbrError DBusMessageExtract(DBusMessageIter *aIter, SrpServerInfo::Registration &aRegistration);
82 otbrError DBusMessageEncode(DBusMessageIter *aIter, const SrpServerInfo::ResponseCounters &aResponseCounters);
83 otbrError DBusMessageExtract(DBusMessageIter *aIter, SrpServerInfo::ResponseCounters &aResponseCounters);
84 otbrError DBusMessageEncode(DBusMessageIter *aIter, const SrpServerInfo &aSrpServerInfo);
85 otbrError DBusMessageExtract(DBusMessageIter *aIter, SrpServerInfo &aSrpServerInfo);
86 otbrError DBusMessageEncode(DBusMessageIter *aIter, const MdnsResponseCounters &aMdnsResponseCounters);
87 otbrError DBusMessageExtract(DBusMessageIter *aIter, MdnsResponseCounters &aMdnsResponseCounters);
88 otbrError DBusMessageEncode(DBusMessageIter *aIter, const MdnsTelemetryInfo &aMdnsTelemetryInfo);
89 otbrError DBusMessageExtract(DBusMessageIter *aIter, MdnsTelemetryInfo &aMdnsTelemetryInfo);
90 otbrError DBusMessageEncode(DBusMessageIter *aIter, const DnssdCounters &aDnssdCounters);
91 otbrError DBusMessageExtract(DBusMessageIter *aIter, DnssdCounters &aDnssdCounters);
92 otbrError DBusMessageEncode(DBusMessageIter *aIter, const RadioSpinelMetrics &aRadioSpinelMetrics);
93 otbrError DBusMessageExtract(DBusMessageIter *aIter, RadioSpinelMetrics &RadioSpinelMetrics);
94 otbrError DBusMessageEncode(DBusMessageIter *aIter, const RcpInterfaceMetrics &aRcpInterfaceMetrics);
95 otbrError DBusMessageExtract(DBusMessageIter *aIter, RcpInterfaceMetrics &aRcpInterfaceMetrics);
96 otbrError DBusMessageEncode(DBusMessageIter *aIter, const RadioCoexMetrics &aRadioCoexMetrics);
97 otbrError DBusMessageExtract(DBusMessageIter *aIter, RadioCoexMetrics &aRadioCoexMetrics);
98 
99 template <typename T> struct DBusTypeTrait;
100 
101 template <> struct DBusTypeTrait<IpCounters>
102 {
103     // struct of 32 bytes
104     static constexpr const char *TYPE_AS_STRING = "(uuuu)";
105 };
106 
107 template <> struct DBusTypeTrait<MacCounters>
108 {
109     // struct of 32 bytes
110     static constexpr const char *TYPE_AS_STRING = "(uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu)";
111 };
112 
113 template <> struct DBusTypeTrait<LinkModeConfig>
114 {
115     // struct of four booleans
116     static constexpr const char *TYPE_AS_STRING = "(bbb)";
117 };
118 
119 template <> struct DBusTypeTrait<std::vector<uint8_t>>
120 {
121     // array of bytes
122     static constexpr const char *TYPE_AS_STRING = "ay";
123 };
124 
125 template <size_t SIZE> struct DBusTypeTrait<std::array<uint8_t, SIZE>>
126 {
127     // array of bytes
128     static constexpr const char *TYPE_AS_STRING = "ay";
129 };
130 
131 template <> struct DBusTypeTrait<Ip6Prefix>
132 {
133     // struct of {array of bytes, byte}
134     static constexpr const char *TYPE_AS_STRING = "(ayy)";
135 };
136 
137 template <> struct DBusTypeTrait<ExternalRoute>
138 {
139     // struct of {{array of bytes, byte}, uint16, byte, bool, bool}
140     static constexpr const char *TYPE_AS_STRING = "((ayy)qybb)";
141 };
142 
143 template <> struct DBusTypeTrait<std::vector<ExternalRoute>>
144 {
145     // array of {{array of bytes, byte}, uint16, byte, bool, bool}
146     static constexpr const char *TYPE_AS_STRING = "a((ayy)qybb)";
147 };
148 
149 template <> struct DBusTypeTrait<OnMeshPrefix>
150 {
151     // struct of {{array of bytes, byte}, uint16, byte, bool, bool, bool, bool, bool, bool, bool, bool, bool}
152     static constexpr const char *TYPE_AS_STRING = "((ayy)qybbbbbbbbb)";
153 };
154 
155 template <> struct DBusTypeTrait<std::vector<OnMeshPrefix>>
156 {
157     // array of {{array of bytes, byte}, uint16, byte, bool, bool, bool, bool, bool, bool, bool, bool, bool}
158     static constexpr const char *TYPE_AS_STRING = "a((ayy)qybbbbbbbbb)";
159 };
160 
161 template <> struct DBusTypeTrait<LeaderData>
162 {
163     // struct of { uint32, byte, byte, byte, byte }
164     static constexpr const char *TYPE_AS_STRING = "(uyyyy)";
165 };
166 
167 template <> struct DBusTypeTrait<std::vector<ChannelQuality>>
168 {
169     // array of struct of { uint8, uint16 }
170     static constexpr const char *TYPE_AS_STRING = "a(yq)";
171 };
172 
173 template <> struct DBusTypeTrait<NeighborInfo>
174 {
175     // struct of { uint64, uint32, uint16, uint32, uint32, uint8,
176     //             uint8, uint8, uint16, uint16, bool, bool, bool, bool }
177     static constexpr const char *TYPE_AS_STRING = "(tuquuyyyqqbbbb)";
178 };
179 
180 template <> struct DBusTypeTrait<std::vector<NeighborInfo>>
181 {
182     // array of struct of { uint64, uint32, uint16, uint32, uint32, uint8,
183     //                      uint8, uint8, uint16, uint16, bool, bool, bool }
184     static constexpr const char *TYPE_AS_STRING = "a(tuquuyyyqqbbbb)";
185 };
186 
187 template <> struct DBusTypeTrait<ChildInfo>
188 {
189     // struct of { uint64, uint32, uint32, uint16, uint16, uint8, uint8,
190     //             uint8, uint8, uint16, uint16, bool, bool, bool, bool }
191     static constexpr const char *TYPE_AS_STRING = "(tuuqqyyyyqqbbbb)";
192 };
193 
194 template <> struct DBusTypeTrait<ActiveScanResult>
195 {
196     // struct of { uint64, string, uint64, array<uint8>, uint16, uint16, uint8,
197     //             uint8, uint8, uint8, bool, bool }
198     static constexpr const char *TYPE_AS_STRING = "(tstayqqyyyybb)";
199 };
200 
201 template <> struct DBusTypeTrait<EnergyScanResult>
202 {
203     // struct of { uint8, int8_t }
204     static constexpr const char *TYPE_AS_STRING = "(yy)";
205 };
206 
207 template <> struct DBusTypeTrait<ChannelQuality>
208 {
209     // struct of { uint8, uint16}
210     static constexpr const char *TYPE_AS_STRING = "(yq)";
211 };
212 
213 template <> struct DBusTypeTrait<std::vector<ChildInfo>>
214 {
215     // array of struct of { uint64, uint32, uint32, uint16, uint16, uint8, uint8,
216     //                      uint8, uint8, uint16, uint16, bool, bool, bool, bool }
217     static constexpr const char *TYPE_AS_STRING = "a(tuuqqyyyyqqbbbb)";
218 };
219 
220 template <> struct DBusTypeTrait<TxtEntry>
221 {
222     // struct of { string, array<uint8> }
223     static constexpr const char *TYPE_AS_STRING = "(say)";
224 };
225 
226 template <> struct DBusTypeTrait<std::vector<TxtEntry>>
227 {
228     // array of struct of { string, array<uint8> }
229     static constexpr const char *TYPE_AS_STRING = "a(say)";
230 };
231 
232 template <> struct DBusTypeTrait<SrpServerState>
233 {
234     static constexpr int         TYPE           = DBUS_TYPE_BYTE;
235     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_BYTE_AS_STRING;
236 };
237 
238 template <> struct DBusTypeTrait<SrpServerAddressMode>
239 {
240     static constexpr int         TYPE           = DBUS_TYPE_BYTE;
241     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_BYTE_AS_STRING;
242 };
243 
244 template <> struct DBusTypeTrait<SrpServerInfo>
245 {
246     // struct of { uint8, uint16, uint8,
247     //              struct of { uint32, uint32, uint64, uint64, uint64, uint64 },
248     //              struct of { uint32, uint32, uint64, uint64, uint64, uint64 },
249     //              struct of { uint32, uint32, uint32, uint32, uint32, uint32} }
250     static constexpr const char *TYPE_AS_STRING = "(yqy(uutttt)(uutttt)(uuuuuu))";
251 };
252 
253 template <> struct DBusTypeTrait<MdnsTelemetryInfo>
254 {
255     // struct of { struct of { uint32, uint32, uint32, uint32, uint32, uint32 },
256     //              struct of { uint32, uint32, uint32, uint32, uint32, uint32 },
257     //              struct of { uint32, uint32, uint32, uint32, uint32, uint32 },
258     //              struct of { uint32, uint32, uint32, uint32, uint32, uint32 },
259     //              uint32, uint32, uint32, uint32 }
260     static constexpr const char *TYPE_AS_STRING = "((uuuuuu)(uuuuuu)(uuuuuu)(uuuuuu)uuuu)";
261 };
262 
263 template <> struct DBusTypeTrait<DnssdCounters>
264 {
265     // struct of { uint32, uint32, uint32, uint32, uint32, uint32, uint32 }
266     static constexpr const char *TYPE_AS_STRING = "(uuuuuuu)";
267 };
268 
269 template <> struct DBusTypeTrait<RadioSpinelMetrics>
270 {
271     // struct of { uint32, uint32, uint32, uint32 }
272     static constexpr const char *TYPE_AS_STRING = "(uuuu)";
273 };
274 
275 template <> struct DBusTypeTrait<RcpInterfaceMetrics>
276 {
277     // struct of { uint8, uint64, uint64, uint64, uint64, uint64, uint64, uint64 }
278     static constexpr const char *TYPE_AS_STRING = "(yttttttt)";
279 };
280 
281 template <> struct DBusTypeTrait<RadioCoexMetrics>
282 {
283     // struct of { uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32,
284     //             uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32,
285     //             uint32, uint32, bool }
286     static constexpr const char *TYPE_AS_STRING = "(uuuuuuuuuuuuuuuuuub)";
287 };
288 
289 template <> struct DBusTypeTrait<int8_t>
290 {
291     static constexpr int         TYPE           = DBUS_TYPE_BYTE;
292     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_BYTE_AS_STRING;
293 };
294 
295 template <> struct DBusTypeTrait<uint8_t>
296 {
297     static constexpr int         TYPE           = DBUS_TYPE_BYTE;
298     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_BYTE_AS_STRING;
299 };
300 
301 template <> struct DBusTypeTrait<uint16_t>
302 {
303     static constexpr int         TYPE           = DBUS_TYPE_UINT16;
304     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_UINT16_AS_STRING;
305 };
306 
307 template <> struct DBusTypeTrait<uint32_t>
308 {
309     static constexpr int         TYPE           = DBUS_TYPE_UINT32;
310     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_UINT32_AS_STRING;
311 };
312 
313 template <> struct DBusTypeTrait<uint64_t>
314 {
315     static constexpr int         TYPE           = DBUS_TYPE_UINT64;
316     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_UINT64_AS_STRING;
317 };
318 
319 template <> struct DBusTypeTrait<int16_t>
320 {
321     static constexpr int         TYPE           = DBUS_TYPE_INT16;
322     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_INT16_AS_STRING;
323 };
324 
325 template <> struct DBusTypeTrait<int32_t>
326 {
327     static constexpr int         TYPE           = DBUS_TYPE_INT32;
328     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_INT32_AS_STRING;
329 };
330 
331 template <> struct DBusTypeTrait<int64_t>
332 {
333     static constexpr int         TYPE           = DBUS_TYPE_INT64;
334     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_INT64_AS_STRING;
335 };
336 
337 template <> struct DBusTypeTrait<std::string>
338 {
339     static constexpr int         TYPE           = DBUS_TYPE_STRING;
340     static constexpr const char *TYPE_AS_STRING = DBUS_TYPE_STRING_AS_STRING;
341 };
342 
343 otbrError DBusMessageEncode(DBusMessageIter *aIter, bool aValue);
344 otbrError DBusMessageEncode(DBusMessageIter *aIter, int8_t aValue);
345 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::string &aValue);
346 otbrError DBusMessageEncode(DBusMessageIter *aIter, const char *aValue);
347 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<uint8_t> &aValue);
348 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<uint16_t> &aValue);
349 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<uint32_t> &aValue);
350 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<uint64_t> &aValue);
351 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<int16_t> &aValue);
352 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<int32_t> &aValue);
353 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<int64_t> &aValue);
354 otbrError DBusMessageExtract(DBusMessageIter *aIter, bool &aValue);
355 otbrError DBusMessageExtract(DBusMessageIter *aIter, int8_t &aValue);
356 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::string &aValue);
357 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<uint8_t> &aValue);
358 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<uint16_t> &aValue);
359 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<uint32_t> &aValue);
360 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<uint64_t> &aValue);
361 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<int16_t> &aValue);
362 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<int32_t> &aValue);
363 otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<int64_t> &aValue);
364 
DBusMessageExtract(DBusMessageIter * aIter,T & aValue)365 template <typename T> otbrError DBusMessageExtract(DBusMessageIter *aIter, T &aValue)
366 {
367     otbrError error = OTBR_ERROR_DBUS;
368 
369     VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBusTypeTrait<T>::TYPE);
370     dbus_message_iter_get_basic(aIter, &aValue);
371     dbus_message_iter_next(aIter);
372     error = OTBR_ERROR_NONE;
373 
374 exit:
375     return error;
376 }
377 
DBusMessageExtract(DBusMessageIter * aIter,std::vector<T> & aValue)378 template <typename T> otbrError DBusMessageExtract(DBusMessageIter *aIter, std::vector<T> &aValue)
379 {
380     otbrError       error = OTBR_ERROR_NONE;
381     DBusMessageIter subIter;
382 
383     VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY, error = OTBR_ERROR_DBUS);
384     dbus_message_iter_recurse(aIter, &subIter);
385 
386     aValue.clear();
387     while (dbus_message_iter_get_arg_type(&subIter) != DBUS_TYPE_INVALID)
388     {
389         T val;
390         SuccessOrExit(error = DBusMessageExtract(&subIter, val));
391         aValue.push_back(val);
392     }
393     dbus_message_iter_next(aIter);
394 
395 exit:
396     return error;
397 }
398 
DBusMessageExtractPrimitive(DBusMessageIter * aIter,std::vector<T> & aValue)399 template <typename T> otbrError DBusMessageExtractPrimitive(DBusMessageIter *aIter, std::vector<T> &aValue)
400 {
401     DBusMessageIter subIter;
402     otbrError       error = OTBR_ERROR_NONE;
403     T *             val;
404     int             n;
405     int             subtype;
406 
407     VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY, error = OTBR_ERROR_DBUS);
408     dbus_message_iter_recurse(aIter, &subIter);
409 
410     subtype = dbus_message_iter_get_arg_type(&subIter);
411     if (subtype != DBUS_TYPE_INVALID)
412     {
413         VerifyOrExit(dbus_message_iter_get_arg_type(&subIter) == DBusTypeTrait<T>::TYPE, error = OTBR_ERROR_DBUS);
414         dbus_message_iter_get_fixed_array(&subIter, &val, &n);
415 
416         if (val != nullptr)
417         {
418             aValue = std::vector<T>(val, val + n);
419         }
420     }
421     dbus_message_iter_next(aIter);
422 
423 exit:
424     return error;
425 }
426 
DBusMessageExtract(DBusMessageIter * aIter,std::array<T,SIZE> & aValue)427 template <typename T, size_t SIZE> otbrError DBusMessageExtract(DBusMessageIter *aIter, std::array<T, SIZE> &aValue)
428 {
429     DBusMessageIter subIter;
430     otbrError       error = OTBR_ERROR_NONE;
431     T *             val;
432     int             n;
433     int             subtype;
434 
435     VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY, error = OTBR_ERROR_DBUS);
436     dbus_message_iter_recurse(aIter, &subIter);
437 
438     subtype = dbus_message_iter_get_arg_type(&subIter);
439     if (subtype != DBUS_TYPE_INVALID)
440     {
441         VerifyOrExit(dbus_message_iter_get_arg_type(&subIter) == DBusTypeTrait<T>::TYPE, error = OTBR_ERROR_DBUS);
442         dbus_message_iter_get_fixed_array(&subIter, &val, &n);
443         VerifyOrExit(n == SIZE, error = OTBR_ERROR_DBUS);
444 
445         if (val != nullptr)
446         {
447             std::copy(val, val + n, aValue.begin());
448         }
449     }
450     dbus_message_iter_next(aIter);
451 
452 exit:
453     return error;
454 }
455 
DBusMessageEncode(DBusMessageIter * aIter,T aValue)456 template <typename T> otbrError DBusMessageEncode(DBusMessageIter *aIter, T aValue)
457 {
458     otbrError error = OTBR_ERROR_NONE;
459     VerifyOrExit(dbus_message_iter_append_basic(aIter, DBusTypeTrait<T>::TYPE, &aValue), error = OTBR_ERROR_DBUS);
460 
461 exit:
462     return error;
463 }
464 
DBusMessageEncode(DBusMessageIter * aIter,const std::vector<T> & aValue)465 template <typename T> otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::vector<T> &aValue)
466 {
467     otbrError       error = OTBR_ERROR_NONE;
468     DBusMessageIter subIter;
469 
470     VerifyOrExit(dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY, DBusTypeTrait<T>::TYPE_AS_STRING, &subIter),
471                  error = OTBR_ERROR_DBUS);
472 
473     for (const auto &v : aValue)
474     {
475         SuccessOrExit(error = DBusMessageEncode(&subIter, v));
476     }
477 
478     VerifyOrExit(dbus_message_iter_close_container(aIter, &subIter), error = OTBR_ERROR_DBUS);
479 exit:
480     return error;
481 }
482 
DBusMessageEncodePrimitive(DBusMessageIter * aIter,const std::vector<T> & aValue)483 template <typename T> otbrError DBusMessageEncodePrimitive(DBusMessageIter *aIter, const std::vector<T> &aValue)
484 {
485     DBusMessageIter subIter;
486     otbrError       error = OTBR_ERROR_NONE;
487 
488     VerifyOrExit(dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY, DBusTypeTrait<T>::TYPE_AS_STRING, &subIter),
489                  error = OTBR_ERROR_DBUS);
490 
491     if (!aValue.empty())
492     {
493         const T *buf = &aValue.front();
494 
495         VerifyOrExit(dbus_message_iter_append_fixed_array(&subIter, DBusTypeTrait<T>::TYPE, &buf,
496                                                           static_cast<int>(aValue.size())),
497                      error = OTBR_ERROR_DBUS);
498     }
499     VerifyOrExit(dbus_message_iter_close_container(aIter, &subIter), error = OTBR_ERROR_DBUS);
500 exit:
501     return error;
502 }
503 
504 template <typename T, size_t SIZE>
DBusMessageEncode(DBusMessageIter * aIter,const std::array<T,SIZE> & aValue)505 otbrError DBusMessageEncode(DBusMessageIter *aIter, const std::array<T, SIZE> &aValue)
506 {
507     DBusMessageIter subIter;
508     otbrError       error = OTBR_ERROR_NONE;
509 
510     VerifyOrExit(dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY, DBusTypeTrait<T>::TYPE_AS_STRING, &subIter),
511                  error = OTBR_ERROR_DBUS);
512 
513     if (!aValue.empty())
514     {
515         const T *buf = &aValue.front();
516 
517         VerifyOrExit(dbus_message_iter_append_fixed_array(&subIter, DBusTypeTrait<T>::TYPE, &buf,
518                                                           static_cast<int>(aValue.size())),
519                      error = OTBR_ERROR_DBUS);
520     }
521     VerifyOrExit(dbus_message_iter_close_container(aIter, &subIter), error = OTBR_ERROR_DBUS);
522 exit:
523     return error;
524 }
525 
526 template <size_t I, typename... FieldTypes> struct ElementType
527 {
528     using ValueType         = typename std::tuple_element<I, std::tuple<FieldTypes...>>::type;
529     using NonconstValueType = typename std::remove_cv<ValueType>::type;
530     using RawValueType      = typename std::remove_reference<NonconstValueType>::type;
531 };
532 
533 template <size_t I, size_t N, typename... FieldTypes> class DBusMessageIterFor
534 {
535 public:
ConvertToTuple(DBusMessageIter * aIter,std::tuple<FieldTypes...> & aValues)536     static otbrError ConvertToTuple(DBusMessageIter *aIter, std::tuple<FieldTypes...> &aValues)
537     {
538         using RawValueType  = typename ElementType<N - I, FieldTypes...>::RawValueType;
539         RawValueType &val   = std::get<N - I>(aValues);
540         otbrError     error = DBusMessageExtract(aIter, val);
541 
542         SuccessOrExit(error);
543         error = DBusMessageIterFor<I - 1, N, FieldTypes...>::ConvertToTuple(aIter, aValues);
544 
545     exit:
546         return error;
547     }
548 
ConvertToDBusMessage(DBusMessageIter * aIter,const std::tuple<FieldTypes...> & aValues)549     static otbrError ConvertToDBusMessage(DBusMessageIter *aIter, const std::tuple<FieldTypes...> &aValues)
550     {
551         otbrError error = DBusMessageEncode(aIter, std::get<N - I>(aValues));
552 
553         SuccessOrExit(error);
554         error = DBusMessageIterFor<I - 1, N, FieldTypes...>::ConvertToDBusMessage(aIter, aValues);
555 
556     exit:
557         return error;
558     }
559 };
560 
561 template <> class DBusMessageIterFor<0, 0>
562 {
563 public:
ConvertToTuple(DBusMessageIter * aIter,std::tuple<> & aValues)564     static otbrError ConvertToTuple(DBusMessageIter *aIter, std::tuple<> &aValues)
565     {
566         OTBR_UNUSED_VARIABLE(aIter);
567         OTBR_UNUSED_VARIABLE(aValues);
568         return OTBR_ERROR_NONE;
569     }
570 
ConvertToDBusMessage(DBusMessageIter * aIter,const std::tuple<> & aValues)571     static otbrError ConvertToDBusMessage(DBusMessageIter *aIter, const std::tuple<> &aValues)
572     {
573         OTBR_UNUSED_VARIABLE(aIter);
574         OTBR_UNUSED_VARIABLE(aValues);
575         return OTBR_ERROR_NONE;
576     }
577 };
578 
579 template <size_t N, typename... FieldTypes> class DBusMessageIterFor<1, N, FieldTypes...>
580 {
581 public:
ConvertToTuple(DBusMessageIter * aIter,std::tuple<FieldTypes...> & aValues)582     static otbrError ConvertToTuple(DBusMessageIter *aIter, std::tuple<FieldTypes...> &aValues)
583     {
584         using RawValueType  = typename ElementType<N - 1, FieldTypes...>::RawValueType;
585         RawValueType &val   = std::get<N - 1>(aValues);
586         otbrError     error = DBusMessageExtract(aIter, val);
587 
588         return error;
589     }
590 
ConvertToDBusMessage(DBusMessageIter * aIter,const std::tuple<FieldTypes...> & aValues)591     static otbrError ConvertToDBusMessage(DBusMessageIter *aIter, const std::tuple<FieldTypes...> &aValues)
592     {
593         otbrError error = DBusMessageEncode(aIter, std::get<N - 1>(aValues));
594 
595         return error;
596     }
597 };
598 
599 template <typename... FieldTypes>
ConvertToDBusMessage(DBusMessageIter * aIter,const std::tuple<FieldTypes...> & aValues)600 otbrError ConvertToDBusMessage(DBusMessageIter *aIter, const std::tuple<FieldTypes...> &aValues)
601 {
602     return DBusMessageIterFor<sizeof...(FieldTypes), sizeof...(FieldTypes), FieldTypes...>::ConvertToDBusMessage(
603         aIter, aValues);
604 }
605 
606 template <typename... FieldTypes>
ConvertToTuple(DBusMessageIter * aIter,std::tuple<FieldTypes...> & aValues)607 constexpr otbrError ConvertToTuple(DBusMessageIter *aIter, std::tuple<FieldTypes...> &aValues)
608 {
609     return DBusMessageIterFor<sizeof...(FieldTypes), sizeof...(FieldTypes), FieldTypes...>::ConvertToTuple(aIter,
610                                                                                                            aValues);
611 }
612 
613 /**
614  * This function converts a value to a d-bus variant.
615  *
616  * @param[out] aIter   The message iterator pointing to the variant.
617  * @param[in]  aValue  The value input.
618  *
619  * @retval OTBR_ERROR_NONE  Successfully encoded to the variant.
620  * @retval OTBR_ERROR_DBUS  Failed to encode to the variant.
621  */
DBusMessageEncodeToVariant(DBusMessageIter * aIter,const ValueType & aValue)622 template <typename ValueType> otbrError DBusMessageEncodeToVariant(DBusMessageIter *aIter, const ValueType &aValue)
623 {
624     otbrError       error = OTBR_ERROR_NONE;
625     DBusMessageIter subIter;
626 
627     VerifyOrExit(
628         dbus_message_iter_open_container(aIter, DBUS_TYPE_VARIANT, DBusTypeTrait<ValueType>::TYPE_AS_STRING, &subIter),
629         error = OTBR_ERROR_DBUS);
630 
631     SuccessOrExit(error = DBusMessageEncode(&subIter, aValue));
632 
633     VerifyOrExit(dbus_message_iter_close_container(aIter, &subIter), error = OTBR_ERROR_DBUS);
634 
635 exit:
636     return error;
637 }
638 
639 /**
640  * This function converts a d-bus variant to a value.
641  *
642  * @param[in]  aIter   The message iterator pointing to the variant.
643  * @param[out] aValue  The value output.
644  *
645  * @retval OTBR_ERROR_NONE  Successfully decoded the variant.
646  * @retval OTBR_ERROR_DBUS  Failed to decode the variant.
647  */
DBusMessageExtractFromVariant(DBusMessageIter * aIter,ValueType & aValue)648 template <typename ValueType> otbrError DBusMessageExtractFromVariant(DBusMessageIter *aIter, ValueType &aValue)
649 {
650     otbrError       error = OTBR_ERROR_NONE;
651     DBusMessageIter subIter;
652 
653     VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_VARIANT, error = OTBR_ERROR_DBUS);
654     dbus_message_iter_recurse(aIter, &subIter);
655 
656     SuccessOrExit(error = DBusMessageExtract(&subIter, aValue));
657 
658 exit:
659     return error;
660 }
661 
662 /**
663  * This function converts a d-bus message to a tuple of C++ types.
664  *
665  * @param[in]  aMessage  The dbus message to decode.
666  * @param[out] aValues   The tuple output.
667  *
668  * @retval OTBR_ERROR_NONE  Successfully decoded the message.
669  * @retval OTBR_ERROR_DBUS  Failed to decode the message.
670  */
671 template <typename... FieldTypes>
DBusMessageToTuple(DBusMessage & aMessage,std::tuple<FieldTypes...> & aValues)672 otbrError DBusMessageToTuple(DBusMessage &aMessage, std::tuple<FieldTypes...> &aValues)
673 {
674     otbrError       error = OTBR_ERROR_NONE;
675     DBusMessageIter iter;
676 
677     VerifyOrExit(dbus_message_iter_init(&aMessage, &iter), error = OTBR_ERROR_DBUS);
678 
679     error = ConvertToTuple(&iter, aValues);
680 
681 exit:
682     return error;
683 }
684 
685 /**
686  * This function converts a tuple of C++ types to a d-bus message.
687  *
688  * @param[out] aMessage  The dbus message output.
689  * @param[in]  aValues   The tuple to encode.
690  *
691  * @retval OTBR_ERROR_NONE  Successfully encoded the message.
692  * @retval OTBR_ERROR_DBUS  Failed to encode the message.
693  */
694 template <typename... FieldTypes>
TupleToDBusMessage(DBusMessage & aMessage,const std::tuple<FieldTypes...> & aValues)695 otbrError TupleToDBusMessage(DBusMessage &aMessage, const std::tuple<FieldTypes...> &aValues)
696 {
697     DBusMessageIter iter;
698 
699     dbus_message_iter_init_append(&aMessage, &iter);
700     return ConvertToDBusMessage(&iter, aValues);
701 }
702 
703 /**
704  * This function converts a d-bus message to a tuple of C++ types.
705  *
706  * @param[in]  aMessage  The dbus message to decode.
707  * @param[out] aValues   The tuple output.
708  *
709  * @retval OTBR_ERROR_NONE  Successfully decoded the message.
710  * @retval OTBR_ERROR_DBUS  Failed to decode the message.
711  */
712 template <typename... FieldTypes>
DBusMessageToTuple(UniqueDBusMessage const & aMessage,std::tuple<FieldTypes...> & aValues)713 otbrError DBusMessageToTuple(UniqueDBusMessage const &aMessage, std::tuple<FieldTypes...> &aValues)
714 {
715     return DBusMessageToTuple(*aMessage.get(), aValues);
716 }
717 
718 bool IsDBusMessageEmpty(DBusMessage &aMessage);
719 
720 } // namespace DBus
721 } // namespace otbr
722 
723 #endif // DBUS_MESSAGE_HELPER_HPP_
724