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