Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / src / dbus / client / thread_api_dbus.cpp
1 /*
2  *    Copyright (c) 2020, 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 #include <map>
30 #include <string.h>
31
32 #include "common/code_utils.hpp"
33 #include "dbus/client/client_error.hpp"
34 #include "dbus/client/thread_api_dbus.hpp"
35 #include "dbus/common/constants.hpp"
36 #include "dbus/common/dbus_message_helper.hpp"
37 #include "dbus/common/dbus_resources.hpp"
38
39 namespace otbr {
40 namespace DBus {
41
42 static ClientError NameToDeviceRole(const std::string &aRoleName, DeviceRole &aDeviceRole)
43 {
44     static std::pair<const char *, DeviceRole> sRoleMap[] = {
45         {OTBR_ROLE_NAME_DISABLED, OTBR_DEVICE_ROLE_DISABLED}, {OTBR_ROLE_NAME_DETACHED, OTBR_DEVICE_ROLE_DETACHED},
46         {OTBR_ROLE_NAME_CHILD, OTBR_DEVICE_ROLE_CHILD},       {OTBR_ROLE_NAME_ROUTER, OTBR_DEVICE_ROLE_ROUTER},
47         {OTBR_ROLE_NAME_LEADER, OTBR_DEVICE_ROLE_LEADER},
48     };
49     ClientError error = ClientError::OT_ERROR_NOT_FOUND;
50
51     for (const auto &p : sRoleMap)
52     {
53         if (p.first == aRoleName)
54         {
55             aDeviceRole = p.second;
56             error       = ClientError::ERROR_NONE;
57             break;
58         }
59     }
60
61     return error;
62 }
63
64 bool IsThreadActive(DeviceRole aRole)
65 {
66     bool isActive = false;
67
68     switch (aRole)
69     {
70     case OTBR_DEVICE_ROLE_DISABLED:
71     case OTBR_DEVICE_ROLE_DETACHED:
72         isActive = false;
73         break;
74     case OTBR_DEVICE_ROLE_CHILD:
75     case OTBR_DEVICE_ROLE_ROUTER:
76     case OTBR_DEVICE_ROLE_LEADER:
77         isActive = true;
78         break;
79     }
80
81     return isActive;
82 }
83
84 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection)
85     : mInterfaceName("wpan0")
86     , mConnection(aConnection)
87 {
88     SubscribeDeviceRoleSignal();
89 }
90
91 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection, const std::string &aInterfaceName)
92     : mInterfaceName(aInterfaceName)
93     , mConnection(aConnection)
94 {
95     SubscribeDeviceRoleSignal();
96 }
97
98 ClientError ThreadApiDBus::SubscribeDeviceRoleSignal(void)
99 {
100     std::string matchRule = "type='signal',interface='" DBUS_INTERFACE_PROPERTIES "'";
101     DBusError   error;
102     ClientError ret = ClientError::ERROR_NONE;
103
104     dbus_error_init(&error);
105     dbus_bus_add_match(mConnection, matchRule.c_str(), &error);
106
107     VerifyOrExit(!dbus_error_is_set(&error), ret = ClientError::OT_ERROR_FAILED);
108
109     dbus_connection_add_filter(mConnection, sDBusMessageFilter, this, nullptr);
110 exit:
111     dbus_error_free(&error);
112     return ret;
113 }
114
115 DBusHandlerResult ThreadApiDBus::sDBusMessageFilter(DBusConnection *aConnection,
116                                                     DBusMessage *   aMessage,
117                                                     void *          aThreadApiDBus)
118 {
119     ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
120
121     return api->DBusMessageFilter(aConnection, aMessage);
122 }
123
124 DBusHandlerResult ThreadApiDBus::DBusMessageFilter(DBusConnection *aConnection, DBusMessage *aMessage)
125 {
126     OTBR_UNUSED_VARIABLE(aConnection);
127
128     DBusMessageIter iter, subIter, dictEntryIter, valIter;
129     std::string     interfaceName, propertyName, val;
130     DeviceRole      role = OTBR_DEVICE_ROLE_DISABLED;
131
132     VerifyOrExit(dbus_message_is_signal(aMessage, DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL));
133     VerifyOrExit(dbus_message_iter_init(aMessage, &iter));
134     SuccessOrExit(DBusMessageExtract(&iter, interfaceName));
135     VerifyOrExit(interfaceName == OTBR_DBUS_THREAD_INTERFACE);
136
137     VerifyOrExit(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
138     dbus_message_iter_recurse(&iter, &subIter);
139     VerifyOrExit(dbus_message_iter_get_arg_type(&subIter) == DBUS_TYPE_DICT_ENTRY);
140     dbus_message_iter_recurse(&subIter, &dictEntryIter);
141     SuccessOrExit(DBusMessageExtract(&dictEntryIter, propertyName));
142     VerifyOrExit(dbus_message_iter_get_arg_type(&dictEntryIter) == DBUS_TYPE_VARIANT);
143     dbus_message_iter_recurse(&dictEntryIter, &valIter);
144     SuccessOrExit(DBusMessageExtract(&valIter, val));
145
146     VerifyOrExit(propertyName == OTBR_DBUS_PROPERTY_DEVICE_ROLE);
147     SuccessOrExit(NameToDeviceRole(val, role));
148
149     for (const auto &f : mDeviceRoleHandlers)
150     {
151         f(role);
152     }
153
154 exit:
155     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
156 }
157
158 void ThreadApiDBus::AddDeviceRoleHandler(const DeviceRoleHandler &aHandler)
159 {
160     mDeviceRoleHandlers.push_back(aHandler);
161 }
162
163 ClientError ThreadApiDBus::Scan(const ScanHandler &aHandler)
164 {
165     ClientError error = ClientError::ERROR_NONE;
166
167     VerifyOrExit(mScanHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
168     mScanHandler = aHandler;
169
170     error = CallDBusMethodAsync(OTBR_DBUS_SCAN_METHOD,
171                                 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::ScanPendingCallHandler>);
172     if (error != ClientError::ERROR_NONE)
173     {
174         mScanHandler = nullptr;
175     }
176 exit:
177     return error;
178 }
179
180 void ThreadApiDBus::ScanPendingCallHandler(DBusPendingCall *aPending)
181 {
182     std::vector<ActiveScanResult> scanResults;
183     UniqueDBusMessage             message(dbus_pending_call_steal_reply(aPending));
184     auto                          args = std::tie(scanResults);
185
186     if (message != nullptr)
187     {
188         DBusMessageToTuple(*message, args);
189     }
190
191     mScanHandler(scanResults);
192     mScanHandler = nullptr;
193 }
194
195 ClientError ThreadApiDBus::PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds)
196 {
197     return CallDBusMethodSync(OTBR_DBUS_PERMIT_UNSECURE_JOIN_METHOD, std::tie(aPort, aSeconds));
198 }
199
200 ClientError ThreadApiDBus::Attach(const std::string &         aNetworkName,
201                                   uint16_t                    aPanId,
202                                   uint64_t                    aExtPanId,
203                                   const std::vector<uint8_t> &aMasterKey,
204                                   const std::vector<uint8_t> &aPSKc,
205                                   uint32_t                    aChannelMask,
206                                   const OtResultHandler &     aHandler)
207 {
208     ClientError error = ClientError::ERROR_NONE;
209     const auto  args  = std::tie(aMasterKey, aPanId, aNetworkName, aExtPanId, aPSKc, aChannelMask);
210
211     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
212     mAttachHandler = aHandler;
213
214     if (aHandler)
215     {
216         error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD, args,
217                                     &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
218     }
219     else
220     {
221         error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD, args);
222     }
223     if (error != ClientError::ERROR_NONE)
224     {
225         mAttachHandler = nullptr;
226     }
227 exit:
228     return error;
229 }
230
231 ClientError ThreadApiDBus::Attach(const OtResultHandler &aHandler)
232 {
233     ClientError error = ClientError::ERROR_NONE;
234
235     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
236     mAttachHandler = aHandler;
237
238     if (aHandler)
239     {
240         error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD,
241                                     &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
242     }
243     else
244     {
245         error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD);
246     }
247     if (error != ClientError::ERROR_NONE)
248     {
249         mAttachHandler = nullptr;
250     }
251 exit:
252     return error;
253 }
254
255 void ThreadApiDBus::AttachPendingCallHandler(DBusPendingCall *aPending)
256 {
257     ClientError       ret = ClientError::OT_ERROR_FAILED;
258     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
259     auto              handler = mAttachHandler;
260
261     if (message != nullptr)
262     {
263         ret = CheckErrorMessage(message.get());
264     }
265
266     mAttachHandler = nullptr;
267     handler(ret);
268 }
269
270 ClientError ThreadApiDBus::FactoryReset(const OtResultHandler &aHandler)
271 {
272     ClientError error = ClientError::ERROR_NONE;
273
274     VerifyOrExit(mFactoryResetHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
275     mFactoryResetHandler = aHandler;
276
277     if (aHandler)
278     {
279         error =
280             CallDBusMethodAsync(OTBR_DBUS_FACTORY_RESET_METHOD,
281                                 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::FactoryResetPendingCallHandler>);
282     }
283     else
284     {
285         error = CallDBusMethodSync(OTBR_DBUS_FACTORY_RESET_METHOD);
286     }
287     if (error != ClientError::ERROR_NONE)
288     {
289         mFactoryResetHandler = nullptr;
290     }
291 exit:
292     return error;
293 }
294
295 void ThreadApiDBus::FactoryResetPendingCallHandler(DBusPendingCall *aPending)
296 {
297     ClientError       ret = ClientError::OT_ERROR_FAILED;
298     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
299
300     if (message != nullptr)
301     {
302         ret = CheckErrorMessage(message.get());
303     }
304
305     mFactoryResetHandler(ret);
306     mFactoryResetHandler = nullptr;
307 }
308
309 ClientError ThreadApiDBus::Reset(void)
310 {
311     return CallDBusMethodSync(OTBR_DBUS_RESET_METHOD);
312 }
313
314 ClientError ThreadApiDBus::JoinerStart(const std::string &    aPskd,
315                                        const std::string &    aProvisioningUrl,
316                                        const std::string &    aVendorName,
317                                        const std::string &    aVendorModel,
318                                        const std::string &    aVendorSwVersion,
319                                        const std::string &    aVendorData,
320                                        const OtResultHandler &aHandler)
321 {
322     ClientError error = ClientError::ERROR_NONE;
323     const auto  args  = std::tie(aPskd, aProvisioningUrl, aVendorName, aVendorModel, aVendorSwVersion, aVendorData);
324     DBusPendingCallNotifyFunction notifyFunc =
325         aHandler ? &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::JoinerStartPendingCallHandler> : nullptr;
326
327     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
328     mJoinerHandler = aHandler;
329
330     if (aHandler)
331     {
332         error = CallDBusMethodAsync(OTBR_DBUS_JOINER_START_METHOD, args, notifyFunc);
333     }
334     else
335     {
336         error = CallDBusMethodSync(OTBR_DBUS_JOINER_START_METHOD, args);
337     }
338     if (error != ClientError::ERROR_NONE)
339     {
340         mJoinerHandler = nullptr;
341     }
342 exit:
343     return error;
344 }
345
346 void ThreadApiDBus::JoinerStartPendingCallHandler(DBusPendingCall *aPending)
347 {
348     ClientError       ret = ClientError::ERROR_NONE;
349     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
350     auto              handler = mJoinerHandler;
351
352     if (message != nullptr)
353     {
354         ret = CheckErrorMessage(message.get());
355     }
356
357     mJoinerHandler = nullptr;
358     handler(ret);
359 }
360
361 ClientError ThreadApiDBus::JoinerStop(void)
362 {
363     return CallDBusMethodSync(OTBR_DBUS_JOINER_STOP_METHOD);
364 }
365
366 ClientError ThreadApiDBus::AddOnMeshPrefix(const OnMeshPrefix &aPrefix)
367 {
368     return CallDBusMethodSync(OTBR_DBUS_ADD_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
369 }
370
371 ClientError ThreadApiDBus::RemoveOnMeshPrefix(const Ip6Prefix &aPrefix)
372 {
373     return CallDBusMethodSync(OTBR_DBUS_REMOVE_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
374 }
375
376 ClientError ThreadApiDBus::AddExternalRoute(const ExternalRoute &aExternalRoute)
377 {
378     return CallDBusMethodSync(OTBR_DBUS_ADD_EXTERNAL_ROUTE_METHOD, std::tie(aExternalRoute));
379 }
380
381 ClientError ThreadApiDBus::RemoveExternalRoute(const Ip6Prefix &aPrefix)
382 {
383     return CallDBusMethodSync(OTBR_DBUS_REMOVE_EXTERNAL_ROUTE_METHOD, std::tie(aPrefix));
384 }
385
386 ClientError ThreadApiDBus::SetMeshLocalPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
387 {
388     return SetProperty(OTBR_DBUS_PROPERTY_MESH_LOCAL_PREFIX, aPrefix);
389 }
390
391 ClientError ThreadApiDBus::SetLegacyUlaPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
392 {
393     return SetProperty(OTBR_DBUS_PROPERTY_LEGACY_ULA_PREFIX, aPrefix);
394 }
395
396 ClientError ThreadApiDBus::SetActiveDatasetTlvs(const std::vector<uint8_t> &aDataset)
397 {
398     return SetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
399 }
400
401 ClientError ThreadApiDBus::SetLinkMode(const LinkModeConfig &aConfig)
402 {
403     return SetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
404 }
405
406 ClientError ThreadApiDBus::SetRadioRegion(const std::string &aRadioRegion)
407 {
408     return SetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
409 }
410
411 ClientError ThreadApiDBus::GetLinkMode(LinkModeConfig &aConfig)
412 {
413     return GetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
414 }
415
416 ClientError ThreadApiDBus::GetDeviceRole(DeviceRole &aRole)
417 {
418     std::string roleName;
419     ClientError error;
420
421     SuccessOrExit(error = GetProperty(OTBR_DBUS_PROPERTY_DEVICE_ROLE, roleName));
422     SuccessOrExit(error = NameToDeviceRole(roleName, aRole));
423 exit:
424     return error;
425 }
426
427 ClientError ThreadApiDBus::GetNetworkName(std::string &aNetworkName)
428 {
429     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_NAME, aNetworkName);
430 }
431
432 ClientError ThreadApiDBus::GetPanId(uint16_t &aPanId)
433 {
434     return GetProperty(OTBR_DBUS_PROPERTY_PANID, aPanId);
435 }
436
437 ClientError ThreadApiDBus::GetExtPanId(uint64_t &aExtPanId)
438 {
439     return GetProperty(OTBR_DBUS_PROPERTY_EXTPANID, aExtPanId);
440 }
441
442 ClientError ThreadApiDBus::GetChannel(uint16_t &aChannel)
443 {
444     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL, aChannel);
445 }
446
447 ClientError ThreadApiDBus::GetMasterKey(std::vector<uint8_t> &aMasterKey)
448 {
449     return GetProperty(OTBR_DBUS_PROPERTY_MASTER_KEY, aMasterKey);
450 }
451
452 ClientError ThreadApiDBus::GetCcaFailureRate(uint16_t &aFailureRate)
453 {
454     return GetProperty(OTBR_DBUS_PROPERTY_CCA_FAILURE_RATE, aFailureRate);
455 }
456
457 ClientError ThreadApiDBus::GetLinkCounters(MacCounters &aCounters)
458 {
459     return GetProperty(OTBR_DBUS_PROPERTY_LINK_COUNTERS, aCounters);
460 }
461
462 ClientError ThreadApiDBus::GetIp6Counters(IpCounters &aCounters)
463 {
464     return GetProperty(OTBR_DBUS_PROPERTY_IP6_COUNTERS, aCounters);
465 }
466
467 ClientError ThreadApiDBus::GetSupportedChannelMask(uint32_t &aChannelMask)
468 {
469     return GetProperty(OTBR_DBUS_PROPERTY_SUPPORTED_CHANNEL_MASK, aChannelMask);
470 }
471
472 ClientError ThreadApiDBus::GetRloc16(uint16_t &aRloc16)
473 {
474     return GetProperty(OTBR_DBUS_PROPERTY_RLOC16, aRloc16);
475 }
476
477 ClientError ThreadApiDBus::GetExtendedAddress(uint64_t &aExtendedAddress)
478 {
479     return GetProperty(OTBR_DBUS_PROPERTY_EXTENDED_ADDRESS, aExtendedAddress);
480 }
481
482 ClientError ThreadApiDBus::GetRouterId(uint8_t &aRouterId)
483 {
484     return GetProperty(OTBR_DBUS_PROPERTY_ROUTER_ID, aRouterId);
485 }
486
487 ClientError ThreadApiDBus::GetLeaderData(LeaderData &aLeaderData)
488 {
489     return GetProperty(OTBR_DBUS_PROPERTY_LEADER_DATA, aLeaderData);
490 }
491
492 ClientError ThreadApiDBus::GetNetworkData(std::vector<uint8_t> &aNetworkData)
493 {
494     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_DATA_PRPOERTY, aNetworkData);
495 }
496
497 ClientError ThreadApiDBus::GetStableNetworkData(std::vector<uint8_t> &aNetworkData)
498 {
499     return GetProperty(OTBR_DBUS_PROPERTY_STABLE_NETWORK_DATA_PRPOERTY, aNetworkData);
500 }
501
502 ClientError ThreadApiDBus::GetLocalLeaderWeight(uint8_t &aWeight)
503 {
504     return GetProperty(OTBR_DBUS_PROPERTY_LOCAL_LEADER_WEIGHT, aWeight);
505 }
506
507 ClientError ThreadApiDBus::GetChannelMonitorSampleCount(uint32_t &aSampleCount)
508 {
509     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_SAMPLE_COUNT, aSampleCount);
510 }
511
512 ClientError ThreadApiDBus::GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> &aChannelQualities)
513 {
514     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_ALL_CHANNEL_QUALITIES, aChannelQualities);
515 }
516
517 ClientError ThreadApiDBus::GetChildTable(std::vector<ChildInfo> &aChildTable)
518 {
519     return GetProperty(OTBR_DBUS_PROPERTY_CHILD_TABLE, aChildTable);
520 }
521
522 ClientError ThreadApiDBus::GetNeighborTable(std::vector<NeighborInfo> &aNeighborTable)
523 {
524     return GetProperty(OTBR_DBUS_PROPERTY_NEIGHBOR_TABLE_PROEPRTY, aNeighborTable);
525 }
526
527 ClientError ThreadApiDBus::GetPartitionId(uint32_t &aPartitionId)
528 {
529     return GetProperty(OTBR_DBUS_PROPERTY_PARTITION_ID_PROEPRTY, aPartitionId);
530 }
531
532 ClientError ThreadApiDBus::GetInstantRssi(int8_t &aRssi)
533 {
534     return GetProperty(OTBR_DBUS_PROPERTY_INSTANT_RSSI, aRssi);
535 }
536
537 ClientError ThreadApiDBus::GetRadioTxPower(int8_t &aTxPower)
538 {
539     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_TX_POWER, aTxPower);
540 }
541
542 ClientError ThreadApiDBus::GetExternalRoutes(std::vector<ExternalRoute> &aExternalRoutes)
543 {
544     return GetProperty(OTBR_DBUS_PROPERTY_EXTERNAL_ROUTES, aExternalRoutes);
545 }
546
547 ClientError ThreadApiDBus::GetActiveDatasetTlvs(std::vector<uint8_t> &aDataset)
548 {
549     return GetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
550 }
551
552 ClientError ThreadApiDBus::GetRadioRegion(std::string &aRadioRegion)
553 {
554     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
555 }
556
557 std::string ThreadApiDBus::GetInterfaceName(void)
558 {
559     return mInterfaceName;
560 }
561
562 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName)
563 {
564     ClientError       ret = ClientError::ERROR_NONE;
565     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
566                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
567                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
568     UniqueDBusMessage reply = nullptr;
569     DBusError         error;
570
571     dbus_error_init(&error);
572     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
573     reply = UniqueDBusMessage(
574         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
575     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
576     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
577     ret = DBus::CheckErrorMessage(reply.get());
578 exit:
579     dbus_error_free(&error);
580     return ret;
581 }
582
583 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string &aMethodName, DBusPendingCallNotifyFunction aFunction)
584 {
585     ClientError       ret = ClientError::ERROR_NONE;
586     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
587                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
588                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
589     DBusPendingCall * pending = nullptr;
590
591     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
592     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
593                      true,
594                  ret = ClientError::ERROR_DBUS);
595
596     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
597                  ret = ClientError::ERROR_DBUS);
598 exit:
599     return ret;
600 }
601
602 template <typename ArgType>
603 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName, const ArgType &aArgs)
604 {
605     ClientError             ret = ClientError::ERROR_NONE;
606     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
607                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
608                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
609     DBus::UniqueDBusMessage reply = nullptr;
610     DBusError               error;
611
612     dbus_error_init(&error);
613     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
614     VerifyOrExit(otbr::DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
615     reply = DBus::UniqueDBusMessage(
616         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
617     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
618     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
619     ret = DBus::CheckErrorMessage(reply.get());
620 exit:
621     dbus_error_free(&error);
622     return ret;
623 }
624
625 template <typename ArgType>
626 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string &           aMethodName,
627                                                const ArgType &               aArgs,
628                                                DBusPendingCallNotifyFunction aFunction)
629 {
630     ClientError ret = ClientError::ERROR_NONE;
631
632     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
633                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
634                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
635     DBusPendingCall *       pending = nullptr;
636
637     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
638     VerifyOrExit(DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
639     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
640                      true,
641                  ret = ClientError::ERROR_DBUS);
642
643     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
644                  ret = ClientError::ERROR_DBUS);
645 exit:
646     return ret;
647 }
648
649 template <typename ValType>
650 ClientError ThreadApiDBus::SetProperty(const std::string &aPropertyName, const ValType &aValue)
651 {
652     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
653                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
654                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_SET_METHOD));
655     DBus::UniqueDBusMessage reply = nullptr;
656     ClientError             ret   = ClientError::ERROR_NONE;
657     DBusError               error;
658     DBusMessageIter         iter;
659
660     dbus_error_init(&error);
661     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
662
663     dbus_message_iter_init_append(message.get(), &iter);
664     VerifyOrExit(DBus::DBusMessageEncode(&iter, OTBR_DBUS_THREAD_INTERFACE) == OTBR_ERROR_NONE,
665                  ret = ClientError::ERROR_DBUS);
666     VerifyOrExit(DBus::DBusMessageEncode(&iter, aPropertyName) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
667     VerifyOrExit(DBus::DBusMessageEncodeToVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
668
669     reply = DBus::UniqueDBusMessage(
670         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
671
672     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
673     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
674     ret = DBus::CheckErrorMessage(reply.get());
675 exit:
676     dbus_error_free(&error);
677     return ret;
678 }
679
680 template <typename ValType> ClientError ThreadApiDBus::GetProperty(const std::string &aPropertyName, ValType &aValue)
681 {
682     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
683                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
684                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_METHOD));
685     DBus::UniqueDBusMessage reply = nullptr;
686
687     ClientError     ret = ClientError::ERROR_NONE;
688     DBusError       error;
689     DBusMessageIter iter;
690
691     dbus_error_init(&error);
692     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
693     otbr::DBus::TupleToDBusMessage(*message, std::tie(OTBR_DBUS_THREAD_INTERFACE, aPropertyName));
694     reply = DBus::UniqueDBusMessage(
695         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
696
697     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
698     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
699     SuccessOrExit(DBus::CheckErrorMessage(reply.get()));
700     VerifyOrExit(dbus_message_iter_init(reply.get(), &iter), ret = ClientError::ERROR_DBUS);
701     VerifyOrExit(DBus::DBusMessageExtractFromVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
702
703 exit:
704     dbus_error_free(&error);
705     return ret;
706 }
707
708 template <void (ThreadApiDBus::*Handler)(DBusPendingCall *aPending)>
709 void ThreadApiDBus::sHandleDBusPendingCall(DBusPendingCall *aPending, void *aThreadApiDBus)
710 {
711     ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
712
713     (api->*Handler)(aPending);
714 }
715
716 } // namespace DBus
717 } // namespace otbr