• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SetMeshLocalPrefix(const std::array<uint8_t,OTBR_IP6_PREFIX_SIZE> & aPrefix)466 ClientError ThreadApiDBus::SetMeshLocalPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
467 {
468     return SetProperty(OTBR_DBUS_PROPERTY_MESH_LOCAL_PREFIX, aPrefix);
469 }
470 
SetActiveDatasetTlvs(const std::vector<uint8_t> & aDataset)471 ClientError ThreadApiDBus::SetActiveDatasetTlvs(const std::vector<uint8_t> &aDataset)
472 {
473     return SetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
474 }
475 
SetFeatureFlagListData(const std::vector<uint8_t> & aFeatureFlagListData)476 ClientError ThreadApiDBus::SetFeatureFlagListData(const std::vector<uint8_t> &aFeatureFlagListData)
477 {
478     return SetProperty(OTBR_DBUS_PROPERTY_FEATURE_FLAG_LIST_DATA, aFeatureFlagListData);
479 }
480 
SetLinkMode(const LinkModeConfig & aConfig)481 ClientError ThreadApiDBus::SetLinkMode(const LinkModeConfig &aConfig)
482 {
483     return SetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
484 }
485 
SetRadioRegion(const std::string & aRadioRegion)486 ClientError ThreadApiDBus::SetRadioRegion(const std::string &aRadioRegion)
487 {
488     return SetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
489 }
490 
GetLinkMode(LinkModeConfig & aConfig)491 ClientError ThreadApiDBus::GetLinkMode(LinkModeConfig &aConfig)
492 {
493     return GetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
494 }
495 
GetDeviceRole(DeviceRole & aRole)496 ClientError ThreadApiDBus::GetDeviceRole(DeviceRole &aRole)
497 {
498     std::string roleName;
499     ClientError error;
500 
501     SuccessOrExit(error = GetProperty(OTBR_DBUS_PROPERTY_DEVICE_ROLE, roleName));
502     SuccessOrExit(error = NameToDeviceRole(roleName, aRole));
503 exit:
504     return error;
505 }
506 
GetNetworkName(std::string & aNetworkName)507 ClientError ThreadApiDBus::GetNetworkName(std::string &aNetworkName)
508 {
509     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_NAME, aNetworkName);
510 }
511 
GetPanId(uint16_t & aPanId)512 ClientError ThreadApiDBus::GetPanId(uint16_t &aPanId)
513 {
514     return GetProperty(OTBR_DBUS_PROPERTY_PANID, aPanId);
515 }
516 
GetExtPanId(uint64_t & aExtPanId)517 ClientError ThreadApiDBus::GetExtPanId(uint64_t &aExtPanId)
518 {
519     return GetProperty(OTBR_DBUS_PROPERTY_EXTPANID, aExtPanId);
520 }
521 
GetChannel(uint16_t & aChannel)522 ClientError ThreadApiDBus::GetChannel(uint16_t &aChannel)
523 {
524     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL, aChannel);
525 }
526 
GetNetworkKey(std::vector<uint8_t> & aNetworkKey)527 ClientError ThreadApiDBus::GetNetworkKey(std::vector<uint8_t> &aNetworkKey)
528 {
529     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_KEY, aNetworkKey);
530 }
531 
GetCcaFailureRate(uint16_t & aFailureRate)532 ClientError ThreadApiDBus::GetCcaFailureRate(uint16_t &aFailureRate)
533 {
534     return GetProperty(OTBR_DBUS_PROPERTY_CCA_FAILURE_RATE, aFailureRate);
535 }
536 
GetLinkCounters(MacCounters & aCounters)537 ClientError ThreadApiDBus::GetLinkCounters(MacCounters &aCounters)
538 {
539     return GetProperty(OTBR_DBUS_PROPERTY_LINK_COUNTERS, aCounters);
540 }
541 
GetIp6Counters(IpCounters & aCounters)542 ClientError ThreadApiDBus::GetIp6Counters(IpCounters &aCounters)
543 {
544     return GetProperty(OTBR_DBUS_PROPERTY_IP6_COUNTERS, aCounters);
545 }
546 
GetSupportedChannelMask(uint32_t & aChannelMask)547 ClientError ThreadApiDBus::GetSupportedChannelMask(uint32_t &aChannelMask)
548 {
549     return GetProperty(OTBR_DBUS_PROPERTY_SUPPORTED_CHANNEL_MASK, aChannelMask);
550 }
551 
GetPreferredChannelMask(uint32_t & aChannelMask)552 ClientError ThreadApiDBus::GetPreferredChannelMask(uint32_t &aChannelMask)
553 {
554     return GetProperty(OTBR_DBUS_PROPERTY_PREFERRED_CHANNEL_MASK, aChannelMask);
555 }
556 
GetRloc16(uint16_t & aRloc16)557 ClientError ThreadApiDBus::GetRloc16(uint16_t &aRloc16)
558 {
559     return GetProperty(OTBR_DBUS_PROPERTY_RLOC16, aRloc16);
560 }
561 
GetExtendedAddress(uint64_t & aExtendedAddress)562 ClientError ThreadApiDBus::GetExtendedAddress(uint64_t &aExtendedAddress)
563 {
564     return GetProperty(OTBR_DBUS_PROPERTY_EXTENDED_ADDRESS, aExtendedAddress);
565 }
566 
GetRouterId(uint8_t & aRouterId)567 ClientError ThreadApiDBus::GetRouterId(uint8_t &aRouterId)
568 {
569     return GetProperty(OTBR_DBUS_PROPERTY_ROUTER_ID, aRouterId);
570 }
571 
GetLeaderData(LeaderData & aLeaderData)572 ClientError ThreadApiDBus::GetLeaderData(LeaderData &aLeaderData)
573 {
574     return GetProperty(OTBR_DBUS_PROPERTY_LEADER_DATA, aLeaderData);
575 }
576 
GetNetworkData(std::vector<uint8_t> & aNetworkData)577 ClientError ThreadApiDBus::GetNetworkData(std::vector<uint8_t> &aNetworkData)
578 {
579     return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_DATA_PRPOERTY, aNetworkData);
580 }
581 
GetStableNetworkData(std::vector<uint8_t> & aNetworkData)582 ClientError ThreadApiDBus::GetStableNetworkData(std::vector<uint8_t> &aNetworkData)
583 {
584     return GetProperty(OTBR_DBUS_PROPERTY_STABLE_NETWORK_DATA_PRPOERTY, aNetworkData);
585 }
586 
GetLocalLeaderWeight(uint8_t & aWeight)587 ClientError ThreadApiDBus::GetLocalLeaderWeight(uint8_t &aWeight)
588 {
589     return GetProperty(OTBR_DBUS_PROPERTY_LOCAL_LEADER_WEIGHT, aWeight);
590 }
591 
GetChannelMonitorSampleCount(uint32_t & aSampleCount)592 ClientError ThreadApiDBus::GetChannelMonitorSampleCount(uint32_t &aSampleCount)
593 {
594     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_SAMPLE_COUNT, aSampleCount);
595 }
596 
GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> & aChannelQualities)597 ClientError ThreadApiDBus::GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> &aChannelQualities)
598 {
599     return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_ALL_CHANNEL_QUALITIES, aChannelQualities);
600 }
601 
GetChildTable(std::vector<ChildInfo> & aChildTable)602 ClientError ThreadApiDBus::GetChildTable(std::vector<ChildInfo> &aChildTable)
603 {
604     return GetProperty(OTBR_DBUS_PROPERTY_CHILD_TABLE, aChildTable);
605 }
606 
GetNeighborTable(std::vector<NeighborInfo> & aNeighborTable)607 ClientError ThreadApiDBus::GetNeighborTable(std::vector<NeighborInfo> &aNeighborTable)
608 {
609     return GetProperty(OTBR_DBUS_PROPERTY_NEIGHBOR_TABLE_PROEPRTY, aNeighborTable);
610 }
611 
GetPartitionId(uint32_t & aPartitionId)612 ClientError ThreadApiDBus::GetPartitionId(uint32_t &aPartitionId)
613 {
614     return GetProperty(OTBR_DBUS_PROPERTY_PARTITION_ID_PROEPRTY, aPartitionId);
615 }
616 
GetInstantRssi(int8_t & aRssi)617 ClientError ThreadApiDBus::GetInstantRssi(int8_t &aRssi)
618 {
619     return GetProperty(OTBR_DBUS_PROPERTY_INSTANT_RSSI, aRssi);
620 }
621 
GetRadioTxPower(int8_t & aTxPower)622 ClientError ThreadApiDBus::GetRadioTxPower(int8_t &aTxPower)
623 {
624     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_TX_POWER, aTxPower);
625 }
626 
GetExternalRoutes(std::vector<ExternalRoute> & aExternalRoutes)627 ClientError ThreadApiDBus::GetExternalRoutes(std::vector<ExternalRoute> &aExternalRoutes)
628 {
629     return GetProperty(OTBR_DBUS_PROPERTY_EXTERNAL_ROUTES, aExternalRoutes);
630 }
631 
GetOnMeshPrefixes(std::vector<OnMeshPrefix> & aOnMeshPrefixes)632 ClientError ThreadApiDBus::GetOnMeshPrefixes(std::vector<OnMeshPrefix> &aOnMeshPrefixes)
633 {
634     return GetProperty(OTBR_DBUS_PROPERTY_ON_MESH_PREFIXES, aOnMeshPrefixes);
635 }
636 
GetActiveDatasetTlvs(std::vector<uint8_t> & aDataset)637 ClientError ThreadApiDBus::GetActiveDatasetTlvs(std::vector<uint8_t> &aDataset)
638 {
639     return GetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
640 }
641 
GetPendingDatasetTlvs(std::vector<uint8_t> & aDataset)642 ClientError ThreadApiDBus::GetPendingDatasetTlvs(std::vector<uint8_t> &aDataset)
643 {
644     return GetProperty(OTBR_DBUS_PROPERTY_PENDING_DATASET_TLVS, aDataset);
645 }
646 
GetFeatureFlagListData(std::vector<uint8_t> & aFeatureFlagListData)647 ClientError ThreadApiDBus::GetFeatureFlagListData(std::vector<uint8_t> &aFeatureFlagListData)
648 {
649     return GetProperty(OTBR_DBUS_PROPERTY_FEATURE_FLAG_LIST_DATA, aFeatureFlagListData);
650 }
651 
GetRadioRegion(std::string & aRadioRegion)652 ClientError ThreadApiDBus::GetRadioRegion(std::string &aRadioRegion)
653 {
654     return GetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
655 }
656 
GetSrpServerInfo(SrpServerInfo & aSrpServerInfo)657 ClientError ThreadApiDBus::GetSrpServerInfo(SrpServerInfo &aSrpServerInfo)
658 {
659     return GetProperty(OTBR_DBUS_PROPERTY_SRP_SERVER_INFO, aSrpServerInfo);
660 }
661 
662 #if OTBR_ENABLE_TREL
GetTrelInfo(TrelInfo & aTrelInfo)663 ClientError ThreadApiDBus::GetTrelInfo(TrelInfo &aTrelInfo)
664 {
665     return GetProperty(OTBR_DBUS_PROPERTY_TREL_INFO, aTrelInfo);
666 }
667 #endif
668 
GetMdnsTelemetryInfo(MdnsTelemetryInfo & aMdnsTelemetryInfo)669 ClientError ThreadApiDBus::GetMdnsTelemetryInfo(MdnsTelemetryInfo &aMdnsTelemetryInfo)
670 {
671     return GetProperty(OTBR_DBUS_PROPERTY_MDNS_TELEMETRY_INFO, aMdnsTelemetryInfo);
672 }
673 
GetNat64State(Nat64ComponentState & aState)674 ClientError ThreadApiDBus::GetNat64State(Nat64ComponentState &aState)
675 {
676     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_STATE, aState);
677 }
678 
GetNat64Mappings(std::vector<Nat64AddressMapping> & aMappings)679 ClientError ThreadApiDBus::GetNat64Mappings(std::vector<Nat64AddressMapping> &aMappings)
680 {
681     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_MAPPINGS, aMappings);
682 }
683 
GetNat64ProtocolCounters(Nat64ProtocolCounters & aCounters)684 ClientError ThreadApiDBus::GetNat64ProtocolCounters(Nat64ProtocolCounters &aCounters)
685 {
686     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_PROTOCOL_COUNTERS, aCounters);
687 }
688 
GetNat64ErrorCounters(Nat64ErrorCounters & aCounters)689 ClientError ThreadApiDBus::GetNat64ErrorCounters(Nat64ErrorCounters &aCounters)
690 {
691     return GetProperty(OTBR_DBUS_PROPERTY_NAT64_ERROR_COUNTERS, aCounters);
692 }
693 
694 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
GetDnssdCounters(DnssdCounters & aDnssdCounters)695 ClientError ThreadApiDBus::GetDnssdCounters(DnssdCounters &aDnssdCounters)
696 {
697     return GetProperty(OTBR_DBUS_PROPERTY_DNSSD_COUNTERS, aDnssdCounters);
698 }
699 #endif
700 
GetTelemetryData(std::vector<uint8_t> & aTelemetryData)701 ClientError ThreadApiDBus::GetTelemetryData(std::vector<uint8_t> &aTelemetryData)
702 {
703     return GetProperty(OTBR_DBUS_PROPERTY_TELEMETRY_DATA, aTelemetryData);
704 }
705 
GetCapabilities(std::vector<uint8_t> & aCapabilities)706 ClientError ThreadApiDBus::GetCapabilities(std::vector<uint8_t> &aCapabilities)
707 {
708     return GetProperty(OTBR_DBUS_PROPERTY_CAPABILITIES, aCapabilities);
709 }
710 
GetInterfaceName(void)711 std::string ThreadApiDBus::GetInterfaceName(void)
712 {
713     return mInterfaceName;
714 }
715 
CallDBusMethodSync(const std::string & aMethodName)716 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName)
717 {
718     ClientError       ret = ClientError::ERROR_NONE;
719     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
720                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
721                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
722     UniqueDBusMessage reply = nullptr;
723     DBusError         error;
724 
725     dbus_error_init(&error);
726     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
727     reply = UniqueDBusMessage(
728         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
729     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
730     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
731     ret = DBus::CheckErrorMessage(reply.get());
732 exit:
733     dbus_error_free(&error);
734     return ret;
735 }
736 
CallDBusMethodAsync(const std::string & aMethodName,DBusPendingCallNotifyFunction aFunction)737 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string &aMethodName, DBusPendingCallNotifyFunction aFunction)
738 {
739     ClientError       ret = ClientError::ERROR_NONE;
740     UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
741                                                            (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
742                                                            OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
743     DBusPendingCall  *pending = nullptr;
744 
745     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
746     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
747                      true,
748                  ret = ClientError::ERROR_DBUS);
749 
750     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
751                  ret = ClientError::ERROR_DBUS);
752 exit:
753     return ret;
754 }
755 
756 template <typename ArgType>
CallDBusMethodSync(const std::string & aMethodName,const ArgType & aArgs)757 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName, const ArgType &aArgs)
758 {
759     ClientError             ret = ClientError::ERROR_NONE;
760     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
761                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
762                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
763     DBus::UniqueDBusMessage reply = nullptr;
764     DBusError               error;
765 
766     dbus_error_init(&error);
767     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
768     VerifyOrExit(otbr::DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
769     reply = DBus::UniqueDBusMessage(
770         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
771     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
772     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
773     ret = DBus::CheckErrorMessage(reply.get());
774 exit:
775     dbus_error_free(&error);
776     return ret;
777 }
778 
779 template <typename ArgType>
CallDBusMethodAsync(const std::string & aMethodName,const ArgType & aArgs,DBusPendingCallNotifyFunction aFunction)780 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string            &aMethodName,
781                                                const ArgType                &aArgs,
782                                                DBusPendingCallNotifyFunction aFunction)
783 {
784     ClientError ret = ClientError::ERROR_NONE;
785 
786     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
787                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
788                                                                  OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
789     DBusPendingCall        *pending = nullptr;
790 
791     VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
792     VerifyOrExit(DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
793     VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
794                      true,
795                  ret = ClientError::ERROR_DBUS);
796 
797     VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
798                  ret = ClientError::ERROR_DBUS);
799 exit:
800     return ret;
801 }
802 
803 template <typename ValType>
SetProperty(const std::string & aPropertyName,const ValType & aValue)804 ClientError ThreadApiDBus::SetProperty(const std::string &aPropertyName, const ValType &aValue)
805 {
806     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
807                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
808                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_SET_METHOD));
809     DBus::UniqueDBusMessage reply = nullptr;
810     ClientError             ret   = ClientError::ERROR_NONE;
811     DBusError               error;
812     DBusMessageIter         iter;
813 
814     dbus_error_init(&error);
815     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
816 
817     dbus_message_iter_init_append(message.get(), &iter);
818     VerifyOrExit(DBus::DBusMessageEncode(&iter, OTBR_DBUS_THREAD_INTERFACE) == OTBR_ERROR_NONE,
819                  ret = ClientError::ERROR_DBUS);
820     VerifyOrExit(DBus::DBusMessageEncode(&iter, aPropertyName) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
821     VerifyOrExit(DBus::DBusMessageEncodeToVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
822 
823     reply = DBus::UniqueDBusMessage(
824         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
825 
826     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
827     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
828     ret = DBus::CheckErrorMessage(reply.get());
829 exit:
830     dbus_error_free(&error);
831     return ret;
832 }
833 
GetProperty(const std::string & aPropertyName,ValType & aValue)834 template <typename ValType> ClientError ThreadApiDBus::GetProperty(const std::string &aPropertyName, ValType &aValue)
835 {
836     DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
837                                                                  (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
838                                                                  DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_METHOD));
839     DBus::UniqueDBusMessage reply = nullptr;
840 
841     ClientError     ret = ClientError::ERROR_NONE;
842     DBusError       error;
843     DBusMessageIter iter;
844 
845     dbus_error_init(&error);
846     VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
847     otbr::DBus::TupleToDBusMessage(*message, std::tie(OTBR_DBUS_THREAD_INTERFACE, aPropertyName));
848     reply = DBus::UniqueDBusMessage(
849         dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
850 
851     VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
852     VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
853     SuccessOrExit(DBus::CheckErrorMessage(reply.get()));
854     VerifyOrExit(dbus_message_iter_init(reply.get(), &iter), ret = ClientError::ERROR_DBUS);
855     VerifyOrExit(DBus::DBusMessageExtractFromVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
856 
857 exit:
858     dbus_error_free(&error);
859     return ret;
860 }
861 
862 template <void (ThreadApiDBus::*Handler)(DBusPendingCall *aPending)>
sHandleDBusPendingCall(DBusPendingCall * aPending,void * aThreadApiDBus)863 void ThreadApiDBus::sHandleDBusPendingCall(DBusPendingCall *aPending, void *aThreadApiDBus)
864 {
865     ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
866 
867     (api->*Handler)(aPending);
868 }
869 
AttachAllNodesTo(const std::vector<uint8_t> & aDataset)870 ClientError ThreadApiDBus::AttachAllNodesTo(const std::vector<uint8_t> &aDataset)
871 {
872     auto args = std::tie(aDataset);
873     return CallDBusMethodSync(OTBR_DBUS_ATTACH_ALL_NODES_TO_METHOD, args);
874 }
875 
UpdateVendorMeshCopTxtEntries(std::vector<TxtEntry> & aUpdate)876 ClientError ThreadApiDBus::UpdateVendorMeshCopTxtEntries(std::vector<TxtEntry> &aUpdate)
877 {
878     auto args = std::tie(aUpdate);
879     return CallDBusMethodSync(OTBR_DBUS_UPDATE_VENDOR_MESHCOP_TXT_METHOD, args);
880 }
881 
882 } // namespace DBus
883 } // namespace otbr
884