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