xref: /aosp_15_r20/external/ot-br-posix/src/dbus/client/thread_api_dbus.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
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/api_strings.hpp"
33 #include "common/code_utils.hpp"
34 #include "dbus/client/client_error.hpp"
35 #include "dbus/client/thread_api_dbus.hpp"
36 #include "dbus/common/constants.hpp"
37 #include "dbus/common/dbus_message_helper.hpp"
38 #include "dbus/common/dbus_resources.hpp"
39 
40 namespace otbr {
41 namespace DBus {
42 
NameToDeviceRole(const std::string & aRoleName,DeviceRole & aDeviceRole)43 static ClientError NameToDeviceRole(const std::string &aRoleName, DeviceRole &aDeviceRole)
44 {
45     static std::pair<const char *, DeviceRole> sRoleMap[] = {
46         {OTBR_ROLE_NAME_DISABLED, OTBR_DEVICE_ROLE_DISABLED}, {OTBR_ROLE_NAME_DETACHED, OTBR_DEVICE_ROLE_DETACHED},
47         {OTBR_ROLE_NAME_CHILD, OTBR_DEVICE_ROLE_CHILD},       {OTBR_ROLE_NAME_ROUTER, OTBR_DEVICE_ROLE_ROUTER},
48         {OTBR_ROLE_NAME_LEADER, OTBR_DEVICE_ROLE_LEADER},
49     };
50     ClientError error = ClientError::OT_ERROR_NOT_FOUND;
51 
52     for (const auto &p : sRoleMap)
53     {
54         if (p.first == aRoleName)
55         {
56             aDeviceRole = p.second;
57             error       = ClientError::ERROR_NONE;
58             break;
59         }
60     }
61 
62     return error;
63 }
64 
IsThreadActive(DeviceRole aRole)65 bool IsThreadActive(DeviceRole aRole)
66 {
67     bool isActive = false;
68 
69     switch (aRole)
70     {
71     case OTBR_DEVICE_ROLE_DISABLED:
72     case OTBR_DEVICE_ROLE_DETACHED:
73         isActive = false;
74         break;
75     case OTBR_DEVICE_ROLE_CHILD:
76     case OTBR_DEVICE_ROLE_ROUTER:
77     case OTBR_DEVICE_ROLE_LEADER:
78         isActive = true;
79         break;
80     }
81 
82     return isActive;
83 }
84 
ThreadApiDBus(DBusConnection * aConnection)85 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection)
86     : mInterfaceName("wpan0")
87     , mConnection(aConnection)
88 {
89     SubscribeDeviceRoleSignal();
90 }
91 
ThreadApiDBus(DBusConnection * aConnection,const std::string & aInterfaceName)92 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection, const std::string &aInterfaceName)
93     : mInterfaceName(aInterfaceName)
94     , mConnection(aConnection)
95 {
96     SubscribeDeviceRoleSignal();
97 }
98 
SubscribeDeviceRoleSignal(void)99 ClientError ThreadApiDBus::SubscribeDeviceRoleSignal(void)
100 {
101     std::string matchRule = "type='signal',interface='" DBUS_INTERFACE_PROPERTIES "'";
102     DBusError   error;
103     ClientError ret = ClientError::ERROR_NONE;
104 
105     dbus_error_init(&error);
106     dbus_bus_add_match(mConnection, matchRule.c_str(), &error);
107 
108     VerifyOrExit(!dbus_error_is_set(&error), ret = ClientError::OT_ERROR_FAILED);
109 
110     dbus_connection_add_filter(mConnection, sDBusMessageFilter, this, nullptr);
111 exit:
112     dbus_error_free(&error);
113     return ret;
114 }
115 
sDBusMessageFilter(DBusConnection * aConnection,DBusMessage * aMessage,void * aThreadApiDBus)116 DBusHandlerResult ThreadApiDBus::sDBusMessageFilter(DBusConnection *aConnection,
117                                                     DBusMessage    *aMessage,
118                                                     void           *aThreadApiDBus)
119 {
120     ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
121 
122     return api->DBusMessageFilter(aConnection, aMessage);
123 }
124 
DBusMessageFilter(DBusConnection * aConnection,DBusMessage * aMessage)125 DBusHandlerResult ThreadApiDBus::DBusMessageFilter(DBusConnection *aConnection, DBusMessage *aMessage)
126 {
127     DBusHandlerResult handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
128     OTBR_UNUSED_VARIABLE(aConnection);
129 
130     DBusMessageIter iter, subIter, dictEntryIter, valIter;
131     std::string     interfaceName, propertyName, val;
132     DeviceRole      role = OTBR_DEVICE_ROLE_DISABLED;
133 
134     VerifyOrExit(dbus_message_is_signal(aMessage, DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL));
135     VerifyOrExit(dbus_message_iter_init(aMessage, &iter));
136     SuccessOrExit(DBusMessageExtract(&iter, interfaceName));
137     VerifyOrExit(interfaceName == OTBR_DBUS_THREAD_INTERFACE);
138 
139     VerifyOrExit(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
140     dbus_message_iter_recurse(&iter, &subIter);
141     VerifyOrExit(dbus_message_iter_get_arg_type(&subIter) == DBUS_TYPE_DICT_ENTRY);
142     dbus_message_iter_recurse(&subIter, &dictEntryIter);
143     SuccessOrExit(DBusMessageExtract(&dictEntryIter, propertyName));
144     VerifyOrExit(dbus_message_iter_get_arg_type(&dictEntryIter) == DBUS_TYPE_VARIANT);
145     dbus_message_iter_recurse(&dictEntryIter, &valIter);
146     SuccessOrExit(DBusMessageExtract(&valIter, val));
147 
148     VerifyOrExit(propertyName == OTBR_DBUS_PROPERTY_DEVICE_ROLE);
149     SuccessOrExit(NameToDeviceRole(val, role));
150 
151     for (const auto &f : mDeviceRoleHandlers)
152     {
153         f(role);
154     }
155     handled = DBUS_HANDLER_RESULT_HANDLED;
156 
157 exit:
158     return handled;
159 }
160 
AddDeviceRoleHandler(const DeviceRoleHandler & aHandler)161 void ThreadApiDBus::AddDeviceRoleHandler(const DeviceRoleHandler &aHandler)
162 {
163     mDeviceRoleHandlers.push_back(aHandler);
164 }
165 
Scan(const ScanHandler & aHandler)166 ClientError ThreadApiDBus::Scan(const ScanHandler &aHandler)
167 {
168     ClientError error = ClientError::ERROR_NONE;
169 
170     VerifyOrExit(mScanHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
171     mScanHandler = aHandler;
172 
173     error = CallDBusMethodAsync(OTBR_DBUS_SCAN_METHOD,
174                                 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::ScanPendingCallHandler>);
175     if (error != ClientError::ERROR_NONE)
176     {
177         mScanHandler = nullptr;
178     }
179 exit:
180     return error;
181 }
182 
ScanPendingCallHandler(DBusPendingCall * aPending)183 void ThreadApiDBus::ScanPendingCallHandler(DBusPendingCall *aPending)
184 {
185     std::vector<ActiveScanResult> scanResults;
186     UniqueDBusMessage             message(dbus_pending_call_steal_reply(aPending));
187     auto                          args = std::tie(scanResults);
188 
189     if (message != nullptr)
190     {
191         DBusMessageToTuple(*message, args);
192     }
193 
194     mScanHandler(scanResults);
195     mScanHandler = nullptr;
196 }
197 
EnergyScan(uint32_t aScanDuration,const EnergyScanHandler & aHandler)198 ClientError ThreadApiDBus::EnergyScan(uint32_t aScanDuration, const EnergyScanHandler &aHandler)
199 {
200     ClientError error = ClientError::ERROR_NONE;
201     const auto  args  = std::tie(aScanDuration);
202 
203     VerifyOrExit(mEnergyScanHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
204     mEnergyScanHandler = aHandler;
205 
206     error = CallDBusMethodAsync(OTBR_DBUS_ENERGY_SCAN_METHOD, args,
207                                 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::EnergyScanPendingCallHandler>);
208     if (error != ClientError::ERROR_NONE)
209     {
210         mEnergyScanHandler = nullptr;
211     }
212 exit:
213     return error;
214 }
215 
EnergyScanPendingCallHandler(DBusPendingCall * aPending)216 void ThreadApiDBus::EnergyScanPendingCallHandler(DBusPendingCall *aPending)
217 {
218     std::vector<EnergyScanResult> results;
219     UniqueDBusMessage             message(dbus_pending_call_steal_reply(aPending));
220     auto                          args = std::tie(results);
221 
222     if (message != nullptr)
223     {
224         DBusMessageToTuple(*message, args);
225     }
226 
227     mEnergyScanHandler(results);
228     mEnergyScanHandler = nullptr;
229 }
230 
PermitUnsecureJoin(uint16_t aPort,uint32_t aSeconds)231 ClientError ThreadApiDBus::PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds)
232 {
233     return CallDBusMethodSync(OTBR_DBUS_PERMIT_UNSECURE_JOIN_METHOD, std::tie(aPort, aSeconds));
234 }
235 
Attach(const std::string & aNetworkName,uint16_t aPanId,uint64_t aExtPanId,const std::vector<uint8_t> & aNetworkKey,const std::vector<uint8_t> & aPSKc,uint32_t aChannelMask,const OtResultHandler & aHandler)236 ClientError ThreadApiDBus::Attach(const std::string          &aNetworkName,
237                                   uint16_t                    aPanId,
238                                   uint64_t                    aExtPanId,
239                                   const std::vector<uint8_t> &aNetworkKey,
240                                   const std::vector<uint8_t> &aPSKc,
241                                   uint32_t                    aChannelMask,
242                                   const OtResultHandler      &aHandler)
243 {
244     ClientError error = ClientError::ERROR_NONE;
245     const auto  args  = std::tie(aNetworkKey, aPanId, aNetworkName, aExtPanId, aPSKc, aChannelMask);
246 
247     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
248     mAttachHandler = aHandler;
249 
250     if (aHandler)
251     {
252         error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD, args,
253                                     &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
254     }
255     else
256     {
257         error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD, args);
258     }
259     if (error != ClientError::ERROR_NONE)
260     {
261         mAttachHandler = nullptr;
262     }
263 exit:
264     return error;
265 }
266 
Attach(const OtResultHandler & aHandler)267 ClientError ThreadApiDBus::Attach(const OtResultHandler &aHandler)
268 {
269     ClientError error = ClientError::ERROR_NONE;
270 
271     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
272     mAttachHandler = aHandler;
273 
274     if (aHandler)
275     {
276         error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD,
277                                     &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
278     }
279     else
280     {
281         error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD);
282     }
283     if (error != ClientError::ERROR_NONE)
284     {
285         mAttachHandler = nullptr;
286     }
287 exit:
288     return error;
289 }
290 
AttachPendingCallHandler(DBusPendingCall * aPending)291 void ThreadApiDBus::AttachPendingCallHandler(DBusPendingCall *aPending)
292 {
293     ClientError       ret = ClientError::OT_ERROR_FAILED;
294     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
295     auto              handler = mAttachHandler;
296 
297     if (message != nullptr)
298     {
299         ret = CheckErrorMessage(message.get());
300     }
301 
302     mAttachHandler = nullptr;
303     handler(ret);
304 }
305 
Detach(const OtResultHandler & aHandler)306 ClientError ThreadApiDBus::Detach(const OtResultHandler &aHandler)
307 {
308     ClientError error = ClientError::ERROR_NONE;
309 
310     VerifyOrExit(mDetachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
311     mDetachHandler = aHandler;
312 
313     if (aHandler)
314     {
315         error = CallDBusMethodAsync(OTBR_DBUS_DETACH_METHOD,
316                                     &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::DetachPendingCallHandler>);
317     }
318     else
319     {
320         error = CallDBusMethodSync(OTBR_DBUS_DETACH_METHOD);
321     }
322     if (error != ClientError::ERROR_NONE)
323     {
324         mDetachHandler = nullptr;
325     }
326 exit:
327     return error;
328 }
329 
DetachPendingCallHandler(DBusPendingCall * aPending)330 void ThreadApiDBus::DetachPendingCallHandler(DBusPendingCall *aPending)
331 {
332     ClientError       ret = ClientError::OT_ERROR_FAILED;
333     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
334     auto              handler = mDetachHandler;
335 
336     if (message != nullptr)
337     {
338         ret = CheckErrorMessage(message.get());
339     }
340 
341     mDetachHandler = nullptr;
342     handler(ret);
343 }
344 
FactoryReset(const OtResultHandler & aHandler)345 ClientError ThreadApiDBus::FactoryReset(const OtResultHandler &aHandler)
346 {
347     ClientError error = ClientError::ERROR_NONE;
348 
349     VerifyOrExit(mFactoryResetHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
350     mFactoryResetHandler = aHandler;
351 
352     if (aHandler)
353     {
354         error =
355             CallDBusMethodAsync(OTBR_DBUS_FACTORY_RESET_METHOD,
356                                 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::FactoryResetPendingCallHandler>);
357     }
358     else
359     {
360         error = CallDBusMethodSync(OTBR_DBUS_FACTORY_RESET_METHOD);
361     }
362     if (error != ClientError::ERROR_NONE)
363     {
364         mFactoryResetHandler = nullptr;
365     }
366 exit:
367     return error;
368 }
369 
FactoryResetPendingCallHandler(DBusPendingCall * aPending)370 void ThreadApiDBus::FactoryResetPendingCallHandler(DBusPendingCall *aPending)
371 {
372     ClientError       ret = ClientError::OT_ERROR_FAILED;
373     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
374 
375     if (message != nullptr)
376     {
377         ret = CheckErrorMessage(message.get());
378     }
379 
380     mFactoryResetHandler(ret);
381     mFactoryResetHandler = nullptr;
382 }
383 
Reset(void)384 ClientError ThreadApiDBus::Reset(void)
385 {
386     return CallDBusMethodSync(OTBR_DBUS_RESET_METHOD);
387 }
388 
JoinerStart(const std::string & aPskd,const std::string & aProvisioningUrl,const std::string & aVendorName,const std::string & aVendorModel,const std::string & aVendorSwVersion,const std::string & aVendorData,const OtResultHandler & aHandler)389 ClientError ThreadApiDBus::JoinerStart(const std::string     &aPskd,
390                                        const std::string     &aProvisioningUrl,
391                                        const std::string     &aVendorName,
392                                        const std::string     &aVendorModel,
393                                        const std::string     &aVendorSwVersion,
394                                        const std::string     &aVendorData,
395                                        const OtResultHandler &aHandler)
396 {
397     ClientError error = ClientError::ERROR_NONE;
398     const auto  args  = std::tie(aPskd, aProvisioningUrl, aVendorName, aVendorModel, aVendorSwVersion, aVendorData);
399     DBusPendingCallNotifyFunction notifyFunc =
400         aHandler ? &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::JoinerStartPendingCallHandler> : nullptr;
401 
402     VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
403     mJoinerHandler = aHandler;
404 
405     if (aHandler)
406     {
407         error = CallDBusMethodAsync(OTBR_DBUS_JOINER_START_METHOD, args, notifyFunc);
408     }
409     else
410     {
411         error = CallDBusMethodSync(OTBR_DBUS_JOINER_START_METHOD, args);
412     }
413     if (error != ClientError::ERROR_NONE)
414     {
415         mJoinerHandler = nullptr;
416     }
417 exit:
418     return error;
419 }
420 
JoinerStartPendingCallHandler(DBusPendingCall * aPending)421 void ThreadApiDBus::JoinerStartPendingCallHandler(DBusPendingCall *aPending)
422 {
423     ClientError       ret = ClientError::ERROR_NONE;
424     UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
425     auto              handler = mJoinerHandler;
426 
427     if (message != nullptr)
428     {
429         ret = CheckErrorMessage(message.get());
430     }
431 
432     mJoinerHandler = nullptr;
433     handler(ret);
434 }
435 
JoinerStop(void)436 ClientError ThreadApiDBus::JoinerStop(void)
437 {
438     return CallDBusMethodSync(OTBR_DBUS_JOINER_STOP_METHOD);
439 }
440 
AddOnMeshPrefix(const OnMeshPrefix & aPrefix)441 ClientError ThreadApiDBus::AddOnMeshPrefix(const OnMeshPrefix &aPrefix)
442 {
443     return CallDBusMethodSync(OTBR_DBUS_ADD_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
444 }
445 
RemoveOnMeshPrefix(const Ip6Prefix & aPrefix)446 ClientError ThreadApiDBus::RemoveOnMeshPrefix(const Ip6Prefix &aPrefix)
447 {
448     return CallDBusMethodSync(OTBR_DBUS_REMOVE_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
449 }
450 
AddExternalRoute(const ExternalRoute & aExternalRoute)451 ClientError ThreadApiDBus::AddExternalRoute(const ExternalRoute &aExternalRoute)
452 {
453     return CallDBusMethodSync(OTBR_DBUS_ADD_EXTERNAL_ROUTE_METHOD, std::tie(aExternalRoute));
454 }
455 
RemoveExternalRoute(const Ip6Prefix & aPrefix)456 ClientError ThreadApiDBus::RemoveExternalRoute(const Ip6Prefix &aPrefix)
457 {
458     return CallDBusMethodSync(OTBR_DBUS_REMOVE_EXTERNAL_ROUTE_METHOD, std::tie(aPrefix));
459 }
460 
SetNat64Enabled(bool aEnabled)461 ClientError ThreadApiDBus::SetNat64Enabled(bool aEnabled)
462 {
463     return CallDBusMethodSync(OTBR_DBUS_SET_NAT64_ENABLED_METHOD, std::tie(aEnabled));
464 }
465 
SetEphemeralKeyEnabled(bool aEnabled)466 ClientError ThreadApiDBus::SetEphemeralKeyEnabled(bool aEnabled)
467 {
468     return SetProperty(OTBR_DBUS_PROPERTY_EPHEMERAL_KEY_ENABLED, aEnabled);
469 }
470 
SetMeshLocalPrefix(const std::array<uint8_t,OTBR_IP6_PREFIX_SIZE> & aPrefix)471 ClientError ThreadApiDBus::SetMeshLocalPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
472 {
473     return SetProperty(OTBR_DBUS_PROPERTY_MESH_LOCAL_PREFIX, aPrefix);
474 }
475 
SetActiveDatasetTlvs(const std::vector<uint8_t> & aDataset)476 ClientError ThreadApiDBus::SetActiveDatasetTlvs(const std::vector<uint8_t> &aDataset)
477 {
478     return SetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
479 }
480 
SetFeatureFlagListData(const std::vector<uint8_t> & aFeatureFlagListData)481 ClientError ThreadApiDBus::SetFeatureFlagListData(const std::vector<uint8_t> &aFeatureFlagListData)
482 {
483     return SetProperty(OTBR_DBUS_PROPERTY_FEATURE_FLAG_LIST_DATA, aFeatureFlagListData);
484 }
485 
SetLinkMode(const LinkModeConfig & aConfig)486 ClientError ThreadApiDBus::SetLinkMode(const LinkModeConfig &aConfig)
487 {
488     return SetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
489 }
490 
SetRadioRegion(const std::string & aRadioRegion)491 ClientError ThreadApiDBus::SetRadioRegion(const std::string &aRadioRegion)
492 {
493     return SetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
494 }
495 
GetEphemeralKeyEnabled(bool & aEnabled)496 ClientError ThreadApiDBus::GetEphemeralKeyEnabled(bool &aEnabled)
497 {
498     return GetProperty(OTBR_DBUS_PROPERTY_EPHEMERAL_KEY_ENABLED, aEnabled);
499 }
500 
GetLinkMode(LinkModeConfig & aConfig)501 ClientError ThreadApiDBus::GetLinkMode(LinkModeConfig &aConfig)
502 {
503     return GetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
504 }
505 
GetDeviceRole(DeviceRole & aRole)506 ClientError ThreadApiDBus::GetDeviceRole(DeviceRole &aRole)
507 {
508     std::string roleName;
509     ClientError error;
510 
511     SuccessOrExit(error = GetProperty(OTBR_DBUS_PROPERTY_DEVICE_ROLE, roleName));
512     SuccessOrExit(error = NameToDeviceRole(roleName, aRole));
513 exit:
514     return error;
515 }
516 
GetNetworkName(std::string & aNetworkName)517 ClientError ThreadApiDBus::GetNetworkName(std::string &aNetworkName)
518 {
519     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_NAME, aNetworkName);
520 }
521 
GetPanId(uint16_t & aPanId)522 ClientError ThreadApiDBus::GetPanId(uint16_t &aPanId)
523 {
524     return GetProperty(OTBR_DBUS_PROPERTY_PANID, aPanId);
525 }
526 
GetExtPanId(uint64_t & aExtPanId)527 ClientError ThreadApiDBus::GetExtPanId(uint64_t &aExtPanId)
528 {
529     return GetProperty(OTBR_DBUS_PROPERTY_EXTPANID, aExtPanId);
530 }
531 
GetChannel(uint16_t & aChannel)532 ClientError ThreadApiDBus::GetChannel(uint16_t &aChannel)
533 {
534     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL, aChannel);
535 }
536 
GetNetworkKey(std::vector<uint8_t> & aNetworkKey)537 ClientError ThreadApiDBus::GetNetworkKey(std::vector<uint8_t> &aNetworkKey)
538 {
539     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_KEY, aNetworkKey);
540 }
541 
GetCcaFailureRate(uint16_t & aFailureRate)542 ClientError ThreadApiDBus::GetCcaFailureRate(uint16_t &aFailureRate)
543 {
544     return GetProperty(OTBR_DBUS_PROPERTY_CCA_FAILURE_RATE, aFailureRate);
545 }
546 
GetLinkCounters(MacCounters & aCounters)547 ClientError ThreadApiDBus::GetLinkCounters(MacCounters &aCounters)
548 {
549     return GetProperty(OTBR_DBUS_PROPERTY_LINK_COUNTERS, aCounters);
550 }
551 
GetIp6Counters(IpCounters & aCounters)552 ClientError ThreadApiDBus::GetIp6Counters(IpCounters &aCounters)
553 {
554     return GetProperty(OTBR_DBUS_PROPERTY_IP6_COUNTERS, aCounters);
555 }
556 
GetSupportedChannelMask(uint32_t & aChannelMask)557 ClientError ThreadApiDBus::GetSupportedChannelMask(uint32_t &aChannelMask)
558 {
559     return GetProperty(OTBR_DBUS_PROPERTY_SUPPORTED_CHANNEL_MASK, aChannelMask);
560 }
561 
GetPreferredChannelMask(uint32_t & aChannelMask)562 ClientError ThreadApiDBus::GetPreferredChannelMask(uint32_t &aChannelMask)
563 {
564     return GetProperty(OTBR_DBUS_PROPERTY_PREFERRED_CHANNEL_MASK, aChannelMask);
565 }
566 
GetRloc16(uint16_t & aRloc16)567 ClientError ThreadApiDBus::GetRloc16(uint16_t &aRloc16)
568 {
569     return GetProperty(OTBR_DBUS_PROPERTY_RLOC16, aRloc16);
570 }
571 
GetExtendedAddress(uint64_t & aExtendedAddress)572 ClientError ThreadApiDBus::GetExtendedAddress(uint64_t &aExtendedAddress)
573 {
574     return GetProperty(OTBR_DBUS_PROPERTY_EXTENDED_ADDRESS, aExtendedAddress);
575 }
576 
GetRouterId(uint8_t & aRouterId)577 ClientError ThreadApiDBus::GetRouterId(uint8_t &aRouterId)
578 {
579     return GetProperty(OTBR_DBUS_PROPERTY_ROUTER_ID, aRouterId);
580 }
581 
GetLeaderData(LeaderData & aLeaderData)582 ClientError ThreadApiDBus::GetLeaderData(LeaderData &aLeaderData)
583 {
584     return GetProperty(OTBR_DBUS_PROPERTY_LEADER_DATA, aLeaderData);
585 }
586 
GetNetworkData(std::vector<uint8_t> & aNetworkData)587 ClientError ThreadApiDBus::GetNetworkData(std::vector<uint8_t> &aNetworkData)
588 {
589     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_DATA_PRPOERTY, aNetworkData);
590 }
591 
GetStableNetworkData(std::vector<uint8_t> & aNetworkData)592 ClientError ThreadApiDBus::GetStableNetworkData(std::vector<uint8_t> &aNetworkData)
593 {
594     return GetProperty(OTBR_DBUS_PROPERTY_STABLE_NETWORK_DATA_PRPOERTY, aNetworkData);
595 }
596 
GetLocalLeaderWeight(uint8_t & aWeight)597 ClientError ThreadApiDBus::GetLocalLeaderWeight(uint8_t &aWeight)
598 {
599     return GetProperty(OTBR_DBUS_PROPERTY_LOCAL_LEADER_WEIGHT, aWeight);
600 }
601 
GetChannelMonitorSampleCount(uint32_t & aSampleCount)602 ClientError ThreadApiDBus::GetChannelMonitorSampleCount(uint32_t &aSampleCount)
603 {
604     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_SAMPLE_COUNT, aSampleCount);
605 }
606 
GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> & aChannelQualities)607 ClientError ThreadApiDBus::GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> &aChannelQualities)
608 {
609     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_ALL_CHANNEL_QUALITIES, aChannelQualities);
610 }
611 
GetChildTable(std::vector<ChildInfo> & aChildTable)612 ClientError ThreadApiDBus::GetChildTable(std::vector<ChildInfo> &aChildTable)
613 {
614     return GetProperty(OTBR_DBUS_PROPERTY_CHILD_TABLE, aChildTable);
615 }
616 
GetNeighborTable(std::vector<NeighborInfo> & aNeighborTable)617 ClientError ThreadApiDBus::GetNeighborTable(std::vector<NeighborInfo> &aNeighborTable)
618 {
619     return GetProperty(OTBR_DBUS_PROPERTY_NEIGHBOR_TABLE_PROEPRTY, aNeighborTable);
620 }
621 
GetPartitionId(uint32_t & aPartitionId)622 ClientError ThreadApiDBus::GetPartitionId(uint32_t &aPartitionId)
623 {
624     return GetProperty(OTBR_DBUS_PROPERTY_PARTITION_ID_PROEPRTY, aPartitionId);
625 }
626 
GetInstantRssi(int8_t & aRssi)627 ClientError ThreadApiDBus::GetInstantRssi(int8_t &aRssi)
628 {
629     return GetProperty(OTBR_DBUS_PROPERTY_INSTANT_RSSI, aRssi);
630 }
631 
GetRadioTxPower(int8_t & aTxPower)632 ClientError ThreadApiDBus::GetRadioTxPower(int8_t &aTxPower)
633 {
634     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_TX_POWER, aTxPower);
635 }
636 
GetExternalRoutes(std::vector<ExternalRoute> & aExternalRoutes)637 ClientError ThreadApiDBus::GetExternalRoutes(std::vector<ExternalRoute> &aExternalRoutes)
638 {
639     return GetProperty(OTBR_DBUS_PROPERTY_EXTERNAL_ROUTES, aExternalRoutes);
640 }
641 
GetOnMeshPrefixes(std::vector<OnMeshPrefix> & aOnMeshPrefixes)642 ClientError ThreadApiDBus::GetOnMeshPrefixes(std::vector<OnMeshPrefix> &aOnMeshPrefixes)
643 {
644     return GetProperty(OTBR_DBUS_PROPERTY_ON_MESH_PREFIXES, aOnMeshPrefixes);
645 }
646 
GetActiveDatasetTlvs(std::vector<uint8_t> & aDataset)647 ClientError ThreadApiDBus::GetActiveDatasetTlvs(std::vector<uint8_t> &aDataset)
648 {
649     return GetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
650 }
651 
GetPendingDatasetTlvs(std::vector<uint8_t> & aDataset)652 ClientError ThreadApiDBus::GetPendingDatasetTlvs(std::vector<uint8_t> &aDataset)
653 {
654     return GetProperty(OTBR_DBUS_PROPERTY_PENDING_DATASET_TLVS, aDataset);
655 }
656 
GetFeatureFlagListData(std::vector<uint8_t> & aFeatureFlagListData)657 ClientError ThreadApiDBus::GetFeatureFlagListData(std::vector<uint8_t> &aFeatureFlagListData)
658 {
659     return GetProperty(OTBR_DBUS_PROPERTY_FEATURE_FLAG_LIST_DATA, aFeatureFlagListData);
660 }
661 
GetRadioRegion(std::string & aRadioRegion)662 ClientError ThreadApiDBus::GetRadioRegion(std::string &aRadioRegion)
663 {
664     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
665 }
666 
GetSrpServerInfo(SrpServerInfo & aSrpServerInfo)667 ClientError ThreadApiDBus::GetSrpServerInfo(SrpServerInfo &aSrpServerInfo)
668 {
669     return GetProperty(OTBR_DBUS_PROPERTY_SRP_SERVER_INFO, aSrpServerInfo);
670 }
671 
672 #if OTBR_ENABLE_TREL
GetTrelInfo(TrelInfo & aTrelInfo)673 ClientError ThreadApiDBus::GetTrelInfo(TrelInfo &aTrelInfo)
674 {
675     return GetProperty(OTBR_DBUS_PROPERTY_TREL_INFO, aTrelInfo);
676 }
677 #endif
678 
GetMdnsTelemetryInfo(MdnsTelemetryInfo & aMdnsTelemetryInfo)679 ClientError ThreadApiDBus::GetMdnsTelemetryInfo(MdnsTelemetryInfo &aMdnsTelemetryInfo)
680 {
681     return GetProperty(OTBR_DBUS_PROPERTY_MDNS_TELEMETRY_INFO, aMdnsTelemetryInfo);
682 }
683 
GetNat64State(Nat64ComponentState & aState)684 ClientError ThreadApiDBus::GetNat64State(Nat64ComponentState &aState)
685 {
686     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_STATE, aState);
687 }
688 
GetNat64Mappings(std::vector<Nat64AddressMapping> & aMappings)689 ClientError ThreadApiDBus::GetNat64Mappings(std::vector<Nat64AddressMapping> &aMappings)
690 {
691     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_MAPPINGS, aMappings);
692 }
693 
GetNat64ProtocolCounters(Nat64ProtocolCounters & aCounters)694 ClientError ThreadApiDBus::GetNat64ProtocolCounters(Nat64ProtocolCounters &aCounters)
695 {
696     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_PROTOCOL_COUNTERS, aCounters);
697 }
698 
GetNat64ErrorCounters(Nat64ErrorCounters & aCounters)699 ClientError ThreadApiDBus::GetNat64ErrorCounters(Nat64ErrorCounters &aCounters)
700 {
701     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_ERROR_COUNTERS, aCounters);
702 }
703 
704 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
GetDnssdCounters(DnssdCounters & aDnssdCounters)705 ClientError ThreadApiDBus::GetDnssdCounters(DnssdCounters &aDnssdCounters)
706 {
707     return GetProperty(OTBR_DBUS_PROPERTY_DNSSD_COUNTERS, aDnssdCounters);
708 }
709 #endif
710 
GetTelemetryData(std::vector<uint8_t> & aTelemetryData)711 ClientError ThreadApiDBus::GetTelemetryData(std::vector<uint8_t> &aTelemetryData)
712 {
713     return GetProperty(OTBR_DBUS_PROPERTY_TELEMETRY_DATA, aTelemetryData);
714 }
715 
GetCapabilities(std::vector<uint8_t> & aCapabilities)716 ClientError ThreadApiDBus::GetCapabilities(std::vector<uint8_t> &aCapabilities)
717 {
718     return GetProperty(OTBR_DBUS_PROPERTY_CAPABILITIES, aCapabilities);
719 }
720 
GetInterfaceName(void)721 std::string ThreadApiDBus::GetInterfaceName(void)
722 {
723     return mInterfaceName;
724 }
725 
CallDBusMethodSync(const std::string & aMethodName)726 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName)
727 {
728     ClientError       ret = ClientError::ERROR_NONE;
729     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
730                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
731                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
732     UniqueDBusMessage reply = nullptr;
733     DBusError         error;
734 
735     dbus_error_init(&error);
736     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
737     reply = UniqueDBusMessage(
738         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
739     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
740     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
741     ret = DBus::CheckErrorMessage(reply.get());
742 exit:
743     dbus_error_free(&error);
744     return ret;
745 }
746 
CallDBusMethodAsync(const std::string & aMethodName,DBusPendingCallNotifyFunction aFunction)747 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string &aMethodName, DBusPendingCallNotifyFunction aFunction)
748 {
749     ClientError       ret = ClientError::ERROR_NONE;
750     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
751                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
752                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
753     DBusPendingCall  *pending = nullptr;
754 
755     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
756     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
757                      true,
758                  ret = ClientError::ERROR_DBUS);
759 
760     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
761                  ret = ClientError::ERROR_DBUS);
762 exit:
763     return ret;
764 }
765 
766 template <typename ArgType>
CallDBusMethodSync(const std::string & aMethodName,const ArgType & aArgs)767 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName, const ArgType &aArgs)
768 {
769     ClientError             ret = ClientError::ERROR_NONE;
770     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
771                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
772                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
773     DBus::UniqueDBusMessage reply = nullptr;
774     DBusError               error;
775 
776     dbus_error_init(&error);
777     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
778     VerifyOrExit(otbr::DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
779     reply = DBus::UniqueDBusMessage(
780         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
781     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
782     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
783     ret = DBus::CheckErrorMessage(reply.get());
784 exit:
785     dbus_error_free(&error);
786     return ret;
787 }
788 
789 template <typename ArgType>
CallDBusMethodAsync(const std::string & aMethodName,const ArgType & aArgs,DBusPendingCallNotifyFunction aFunction)790 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string            &aMethodName,
791                                                const ArgType                &aArgs,
792                                                DBusPendingCallNotifyFunction aFunction)
793 {
794     ClientError ret = ClientError::ERROR_NONE;
795 
796     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
797                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
798                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
799     DBusPendingCall        *pending = nullptr;
800 
801     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
802     VerifyOrExit(DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
803     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
804                      true,
805                  ret = ClientError::ERROR_DBUS);
806 
807     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
808                  ret = ClientError::ERROR_DBUS);
809 exit:
810     return ret;
811 }
812 
813 template <typename ValType>
SetProperty(const std::string & aPropertyName,const ValType & aValue)814 ClientError ThreadApiDBus::SetProperty(const std::string &aPropertyName, const ValType &aValue)
815 {
816     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
817                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
818                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_SET_METHOD));
819     DBus::UniqueDBusMessage reply = nullptr;
820     ClientError             ret   = ClientError::ERROR_NONE;
821     DBusError               error;
822     DBusMessageIter         iter;
823 
824     dbus_error_init(&error);
825     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
826 
827     dbus_message_iter_init_append(message.get(), &iter);
828     VerifyOrExit(DBus::DBusMessageEncode(&iter, OTBR_DBUS_THREAD_INTERFACE) == OTBR_ERROR_NONE,
829                  ret = ClientError::ERROR_DBUS);
830     VerifyOrExit(DBus::DBusMessageEncode(&iter, aPropertyName) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
831     VerifyOrExit(DBus::DBusMessageEncodeToVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
832 
833     reply = DBus::UniqueDBusMessage(
834         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
835 
836     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
837     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
838     ret = DBus::CheckErrorMessage(reply.get());
839 exit:
840     dbus_error_free(&error);
841     return ret;
842 }
843 
GetProperty(const std::string & aPropertyName,ValType & aValue)844 template <typename ValType> ClientError ThreadApiDBus::GetProperty(const std::string &aPropertyName, ValType &aValue)
845 {
846     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
847                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
848                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_METHOD));
849     DBus::UniqueDBusMessage reply = nullptr;
850 
851     ClientError     ret = ClientError::ERROR_NONE;
852     DBusError       error;
853     DBusMessageIter iter;
854 
855     dbus_error_init(&error);
856     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
857     otbr::DBus::TupleToDBusMessage(*message, std::tie(OTBR_DBUS_THREAD_INTERFACE, aPropertyName));
858     reply = DBus::UniqueDBusMessage(
859         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
860 
861     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
862     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
863     SuccessOrExit(DBus::CheckErrorMessage(reply.get()));
864     VerifyOrExit(dbus_message_iter_init(reply.get(), &iter), ret = ClientError::ERROR_DBUS);
865     VerifyOrExit(DBus::DBusMessageExtractFromVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
866 
867 exit:
868     dbus_error_free(&error);
869     return ret;
870 }
871 
872 template <void (ThreadApiDBus::*Handler)(DBusPendingCall *aPending)>
sHandleDBusPendingCall(DBusPendingCall * aPending,void * aThreadApiDBus)873 void ThreadApiDBus::sHandleDBusPendingCall(DBusPendingCall *aPending, void *aThreadApiDBus)
874 {
875     ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
876 
877     (api->*Handler)(aPending);
878 }
879 
AttachAllNodesTo(const std::vector<uint8_t> & aDataset)880 ClientError ThreadApiDBus::AttachAllNodesTo(const std::vector<uint8_t> &aDataset)
881 {
882     auto args = std::tie(aDataset);
883     return CallDBusMethodSync(OTBR_DBUS_ATTACH_ALL_NODES_TO_METHOD, args);
884 }
885 
UpdateVendorMeshCopTxtEntries(std::vector<TxtEntry> & aUpdate)886 ClientError ThreadApiDBus::UpdateVendorMeshCopTxtEntries(std::vector<TxtEntry> &aUpdate)
887 {
888     auto args = std::tie(aUpdate);
889     return CallDBusMethodSync(OTBR_DBUS_UPDATE_VENDOR_MESHCOP_TXT_METHOD, args);
890 }
891 
892 } // namespace DBus
893 } // namespace otbr
894