2 * Copyright (c) 2020, The OpenThread Authors.
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.
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.
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"
42 static ClientError NameToDeviceRole(const std::string &aRoleName, DeviceRole &aDeviceRole)
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},
49 ClientError error = ClientError::OT_ERROR_NOT_FOUND;
51 for (const auto &p : sRoleMap)
53 if (p.first == aRoleName)
55 aDeviceRole = p.second;
56 error = ClientError::ERROR_NONE;
64 bool IsThreadActive(DeviceRole aRole)
66 bool isActive = false;
70 case OTBR_DEVICE_ROLE_DISABLED:
71 case OTBR_DEVICE_ROLE_DETACHED:
74 case OTBR_DEVICE_ROLE_CHILD:
75 case OTBR_DEVICE_ROLE_ROUTER:
76 case OTBR_DEVICE_ROLE_LEADER:
84 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection)
85 : mInterfaceName("wpan0")
86 , mConnection(aConnection)
88 SubscribeDeviceRoleSignal();
91 ThreadApiDBus::ThreadApiDBus(DBusConnection *aConnection, const std::string &aInterfaceName)
92 : mInterfaceName(aInterfaceName)
93 , mConnection(aConnection)
95 SubscribeDeviceRoleSignal();
98 ClientError ThreadApiDBus::SubscribeDeviceRoleSignal(void)
100 std::string matchRule = "type='signal',interface='" DBUS_INTERFACE_PROPERTIES "'";
102 ClientError ret = ClientError::ERROR_NONE;
104 dbus_error_init(&error);
105 dbus_bus_add_match(mConnection, matchRule.c_str(), &error);
107 VerifyOrExit(!dbus_error_is_set(&error), ret = ClientError::OT_ERROR_FAILED);
109 dbus_connection_add_filter(mConnection, sDBusMessageFilter, this, nullptr);
111 dbus_error_free(&error);
115 DBusHandlerResult ThreadApiDBus::sDBusMessageFilter(DBusConnection *aConnection,
116 DBusMessage * aMessage,
117 void * aThreadApiDBus)
119 ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
121 return api->DBusMessageFilter(aConnection, aMessage);
124 DBusHandlerResult ThreadApiDBus::DBusMessageFilter(DBusConnection *aConnection, DBusMessage *aMessage)
126 OTBR_UNUSED_VARIABLE(aConnection);
128 DBusMessageIter iter, subIter, dictEntryIter, valIter;
129 std::string interfaceName, propertyName, val;
130 DeviceRole role = OTBR_DEVICE_ROLE_DISABLED;
132 VerifyOrExit(dbus_message_is_signal(aMessage, DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL));
133 VerifyOrExit(dbus_message_iter_init(aMessage, &iter));
134 SuccessOrExit(DBusMessageExtract(&iter, interfaceName));
135 VerifyOrExit(interfaceName == OTBR_DBUS_THREAD_INTERFACE);
137 VerifyOrExit(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
138 dbus_message_iter_recurse(&iter, &subIter);
139 VerifyOrExit(dbus_message_iter_get_arg_type(&subIter) == DBUS_TYPE_DICT_ENTRY);
140 dbus_message_iter_recurse(&subIter, &dictEntryIter);
141 SuccessOrExit(DBusMessageExtract(&dictEntryIter, propertyName));
142 VerifyOrExit(dbus_message_iter_get_arg_type(&dictEntryIter) == DBUS_TYPE_VARIANT);
143 dbus_message_iter_recurse(&dictEntryIter, &valIter);
144 SuccessOrExit(DBusMessageExtract(&valIter, val));
146 VerifyOrExit(propertyName == OTBR_DBUS_PROPERTY_DEVICE_ROLE);
147 SuccessOrExit(NameToDeviceRole(val, role));
149 for (const auto &f : mDeviceRoleHandlers)
155 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
158 void ThreadApiDBus::AddDeviceRoleHandler(const DeviceRoleHandler &aHandler)
160 mDeviceRoleHandlers.push_back(aHandler);
163 ClientError ThreadApiDBus::Scan(const ScanHandler &aHandler)
165 ClientError error = ClientError::ERROR_NONE;
167 VerifyOrExit(mScanHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
168 mScanHandler = aHandler;
170 error = CallDBusMethodAsync(OTBR_DBUS_SCAN_METHOD,
171 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::ScanPendingCallHandler>);
172 if (error != ClientError::ERROR_NONE)
174 mScanHandler = nullptr;
180 void ThreadApiDBus::ScanPendingCallHandler(DBusPendingCall *aPending)
182 std::vector<ActiveScanResult> scanResults;
183 UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
184 auto args = std::tie(scanResults);
186 if (message != nullptr)
188 DBusMessageToTuple(*message, args);
191 mScanHandler(scanResults);
192 mScanHandler = nullptr;
195 ClientError ThreadApiDBus::PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds)
197 return CallDBusMethodSync(OTBR_DBUS_PERMIT_UNSECURE_JOIN_METHOD, std::tie(aPort, aSeconds));
200 ClientError ThreadApiDBus::Attach(const std::string & aNetworkName,
203 const std::vector<uint8_t> &aMasterKey,
204 const std::vector<uint8_t> &aPSKc,
205 uint32_t aChannelMask,
206 const OtResultHandler & aHandler)
208 ClientError error = ClientError::ERROR_NONE;
209 const auto args = std::tie(aMasterKey, aPanId, aNetworkName, aExtPanId, aPSKc, aChannelMask);
211 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
212 mAttachHandler = aHandler;
216 error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD, args,
217 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
221 error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD, args);
223 if (error != ClientError::ERROR_NONE)
225 mAttachHandler = nullptr;
231 ClientError ThreadApiDBus::Attach(const OtResultHandler &aHandler)
233 ClientError error = ClientError::ERROR_NONE;
235 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
236 mAttachHandler = aHandler;
240 error = CallDBusMethodAsync(OTBR_DBUS_ATTACH_METHOD,
241 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::AttachPendingCallHandler>);
245 error = CallDBusMethodSync(OTBR_DBUS_ATTACH_METHOD);
247 if (error != ClientError::ERROR_NONE)
249 mAttachHandler = nullptr;
255 void ThreadApiDBus::AttachPendingCallHandler(DBusPendingCall *aPending)
257 ClientError ret = ClientError::OT_ERROR_FAILED;
258 UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
259 auto handler = mAttachHandler;
261 if (message != nullptr)
263 ret = CheckErrorMessage(message.get());
266 mAttachHandler = nullptr;
270 ClientError ThreadApiDBus::FactoryReset(const OtResultHandler &aHandler)
272 ClientError error = ClientError::ERROR_NONE;
274 VerifyOrExit(mFactoryResetHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
275 mFactoryResetHandler = aHandler;
280 CallDBusMethodAsync(OTBR_DBUS_FACTORY_RESET_METHOD,
281 &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::FactoryResetPendingCallHandler>);
285 error = CallDBusMethodSync(OTBR_DBUS_FACTORY_RESET_METHOD);
287 if (error != ClientError::ERROR_NONE)
289 mFactoryResetHandler = nullptr;
295 void ThreadApiDBus::FactoryResetPendingCallHandler(DBusPendingCall *aPending)
297 ClientError ret = ClientError::OT_ERROR_FAILED;
298 UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
300 if (message != nullptr)
302 ret = CheckErrorMessage(message.get());
305 mFactoryResetHandler(ret);
306 mFactoryResetHandler = nullptr;
309 ClientError ThreadApiDBus::Reset(void)
311 return CallDBusMethodSync(OTBR_DBUS_RESET_METHOD);
314 ClientError ThreadApiDBus::JoinerStart(const std::string & aPskd,
315 const std::string & aProvisioningUrl,
316 const std::string & aVendorName,
317 const std::string & aVendorModel,
318 const std::string & aVendorSwVersion,
319 const std::string & aVendorData,
320 const OtResultHandler &aHandler)
322 ClientError error = ClientError::ERROR_NONE;
323 const auto args = std::tie(aPskd, aProvisioningUrl, aVendorName, aVendorModel, aVendorSwVersion, aVendorData);
324 DBusPendingCallNotifyFunction notifyFunc =
325 aHandler ? &ThreadApiDBus::sHandleDBusPendingCall<&ThreadApiDBus::JoinerStartPendingCallHandler> : nullptr;
327 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = ClientError::OT_ERROR_INVALID_STATE);
328 mJoinerHandler = aHandler;
332 error = CallDBusMethodAsync(OTBR_DBUS_JOINER_START_METHOD, args, notifyFunc);
336 error = CallDBusMethodSync(OTBR_DBUS_JOINER_START_METHOD, args);
338 if (error != ClientError::ERROR_NONE)
340 mJoinerHandler = nullptr;
346 void ThreadApiDBus::JoinerStartPendingCallHandler(DBusPendingCall *aPending)
348 ClientError ret = ClientError::ERROR_NONE;
349 UniqueDBusMessage message(dbus_pending_call_steal_reply(aPending));
350 auto handler = mJoinerHandler;
352 if (message != nullptr)
354 ret = CheckErrorMessage(message.get());
357 mJoinerHandler = nullptr;
361 ClientError ThreadApiDBus::JoinerStop(void)
363 return CallDBusMethodSync(OTBR_DBUS_JOINER_STOP_METHOD);
366 ClientError ThreadApiDBus::AddOnMeshPrefix(const OnMeshPrefix &aPrefix)
368 return CallDBusMethodSync(OTBR_DBUS_ADD_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
371 ClientError ThreadApiDBus::RemoveOnMeshPrefix(const Ip6Prefix &aPrefix)
373 return CallDBusMethodSync(OTBR_DBUS_REMOVE_ON_MESH_PREFIX_METHOD, std::tie(aPrefix));
376 ClientError ThreadApiDBus::AddExternalRoute(const ExternalRoute &aExternalRoute)
378 return CallDBusMethodSync(OTBR_DBUS_ADD_EXTERNAL_ROUTE_METHOD, std::tie(aExternalRoute));
381 ClientError ThreadApiDBus::RemoveExternalRoute(const Ip6Prefix &aPrefix)
383 return CallDBusMethodSync(OTBR_DBUS_REMOVE_EXTERNAL_ROUTE_METHOD, std::tie(aPrefix));
386 ClientError ThreadApiDBus::SetMeshLocalPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
388 return SetProperty(OTBR_DBUS_PROPERTY_MESH_LOCAL_PREFIX, aPrefix);
391 ClientError ThreadApiDBus::SetLegacyUlaPrefix(const std::array<uint8_t, OTBR_IP6_PREFIX_SIZE> &aPrefix)
393 return SetProperty(OTBR_DBUS_PROPERTY_LEGACY_ULA_PREFIX, aPrefix);
396 ClientError ThreadApiDBus::SetActiveDatasetTlvs(const std::vector<uint8_t> &aDataset)
398 return SetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
401 ClientError ThreadApiDBus::SetLinkMode(const LinkModeConfig &aConfig)
403 return SetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
406 ClientError ThreadApiDBus::SetRadioRegion(const std::string &aRadioRegion)
408 return SetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
411 ClientError ThreadApiDBus::GetLinkMode(LinkModeConfig &aConfig)
413 return GetProperty(OTBR_DBUS_PROPERTY_LINK_MODE, aConfig);
416 ClientError ThreadApiDBus::GetDeviceRole(DeviceRole &aRole)
418 std::string roleName;
421 SuccessOrExit(error = GetProperty(OTBR_DBUS_PROPERTY_DEVICE_ROLE, roleName));
422 SuccessOrExit(error = NameToDeviceRole(roleName, aRole));
427 ClientError ThreadApiDBus::GetNetworkName(std::string &aNetworkName)
429 return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_NAME, aNetworkName);
432 ClientError ThreadApiDBus::GetPanId(uint16_t &aPanId)
434 return GetProperty(OTBR_DBUS_PROPERTY_PANID, aPanId);
437 ClientError ThreadApiDBus::GetExtPanId(uint64_t &aExtPanId)
439 return GetProperty(OTBR_DBUS_PROPERTY_EXTPANID, aExtPanId);
442 ClientError ThreadApiDBus::GetChannel(uint16_t &aChannel)
444 return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL, aChannel);
447 ClientError ThreadApiDBus::GetMasterKey(std::vector<uint8_t> &aMasterKey)
449 return GetProperty(OTBR_DBUS_PROPERTY_MASTER_KEY, aMasterKey);
452 ClientError ThreadApiDBus::GetCcaFailureRate(uint16_t &aFailureRate)
454 return GetProperty(OTBR_DBUS_PROPERTY_CCA_FAILURE_RATE, aFailureRate);
457 ClientError ThreadApiDBus::GetLinkCounters(MacCounters &aCounters)
459 return GetProperty(OTBR_DBUS_PROPERTY_LINK_COUNTERS, aCounters);
462 ClientError ThreadApiDBus::GetIp6Counters(IpCounters &aCounters)
464 return GetProperty(OTBR_DBUS_PROPERTY_IP6_COUNTERS, aCounters);
467 ClientError ThreadApiDBus::GetSupportedChannelMask(uint32_t &aChannelMask)
469 return GetProperty(OTBR_DBUS_PROPERTY_SUPPORTED_CHANNEL_MASK, aChannelMask);
472 ClientError ThreadApiDBus::GetRloc16(uint16_t &aRloc16)
474 return GetProperty(OTBR_DBUS_PROPERTY_RLOC16, aRloc16);
477 ClientError ThreadApiDBus::GetExtendedAddress(uint64_t &aExtendedAddress)
479 return GetProperty(OTBR_DBUS_PROPERTY_EXTENDED_ADDRESS, aExtendedAddress);
482 ClientError ThreadApiDBus::GetRouterId(uint8_t &aRouterId)
484 return GetProperty(OTBR_DBUS_PROPERTY_ROUTER_ID, aRouterId);
487 ClientError ThreadApiDBus::GetLeaderData(LeaderData &aLeaderData)
489 return GetProperty(OTBR_DBUS_PROPERTY_LEADER_DATA, aLeaderData);
492 ClientError ThreadApiDBus::GetNetworkData(std::vector<uint8_t> &aNetworkData)
494 return GetProperty(OTBR_DBUS_PROPERTY_NETWORK_DATA_PRPOERTY, aNetworkData);
497 ClientError ThreadApiDBus::GetStableNetworkData(std::vector<uint8_t> &aNetworkData)
499 return GetProperty(OTBR_DBUS_PROPERTY_STABLE_NETWORK_DATA_PRPOERTY, aNetworkData);
502 ClientError ThreadApiDBus::GetLocalLeaderWeight(uint8_t &aWeight)
504 return GetProperty(OTBR_DBUS_PROPERTY_LOCAL_LEADER_WEIGHT, aWeight);
507 ClientError ThreadApiDBus::GetChannelMonitorSampleCount(uint32_t &aSampleCount)
509 return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_SAMPLE_COUNT, aSampleCount);
512 ClientError ThreadApiDBus::GetChannelMonitorAllChannelQualities(std::vector<ChannelQuality> &aChannelQualities)
514 return GetProperty(OTBR_DBUS_PROPERTY_CHANNEL_MONITOR_ALL_CHANNEL_QUALITIES, aChannelQualities);
517 ClientError ThreadApiDBus::GetChildTable(std::vector<ChildInfo> &aChildTable)
519 return GetProperty(OTBR_DBUS_PROPERTY_CHILD_TABLE, aChildTable);
522 ClientError ThreadApiDBus::GetNeighborTable(std::vector<NeighborInfo> &aNeighborTable)
524 return GetProperty(OTBR_DBUS_PROPERTY_NEIGHBOR_TABLE_PROEPRTY, aNeighborTable);
527 ClientError ThreadApiDBus::GetPartitionId(uint32_t &aPartitionId)
529 return GetProperty(OTBR_DBUS_PROPERTY_PARTITION_ID_PROEPRTY, aPartitionId);
532 ClientError ThreadApiDBus::GetInstantRssi(int8_t &aRssi)
534 return GetProperty(OTBR_DBUS_PROPERTY_INSTANT_RSSI, aRssi);
537 ClientError ThreadApiDBus::GetRadioTxPower(int8_t &aTxPower)
539 return GetProperty(OTBR_DBUS_PROPERTY_RADIO_TX_POWER, aTxPower);
542 ClientError ThreadApiDBus::GetExternalRoutes(std::vector<ExternalRoute> &aExternalRoutes)
544 return GetProperty(OTBR_DBUS_PROPERTY_EXTERNAL_ROUTES, aExternalRoutes);
547 ClientError ThreadApiDBus::GetActiveDatasetTlvs(std::vector<uint8_t> &aDataset)
549 return GetProperty(OTBR_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, aDataset);
552 ClientError ThreadApiDBus::GetRadioRegion(std::string &aRadioRegion)
554 return GetProperty(OTBR_DBUS_PROPERTY_RADIO_REGION, aRadioRegion);
557 std::string ThreadApiDBus::GetInterfaceName(void)
559 return mInterfaceName;
562 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName)
564 ClientError ret = ClientError::ERROR_NONE;
565 UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
566 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
567 OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
568 UniqueDBusMessage reply = nullptr;
571 dbus_error_init(&error);
572 VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
573 reply = UniqueDBusMessage(
574 dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
575 VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
576 VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
577 ret = DBus::CheckErrorMessage(reply.get());
579 dbus_error_free(&error);
583 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string &aMethodName, DBusPendingCallNotifyFunction aFunction)
585 ClientError ret = ClientError::ERROR_NONE;
586 UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
587 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
588 OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
589 DBusPendingCall * pending = nullptr;
591 VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
592 VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
594 ret = ClientError::ERROR_DBUS);
596 VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
597 ret = ClientError::ERROR_DBUS);
602 template <typename ArgType>
603 ClientError ThreadApiDBus::CallDBusMethodSync(const std::string &aMethodName, const ArgType &aArgs)
605 ClientError ret = ClientError::ERROR_NONE;
606 DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
607 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
608 OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
609 DBus::UniqueDBusMessage reply = nullptr;
612 dbus_error_init(&error);
613 VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
614 VerifyOrExit(otbr::DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
615 reply = DBus::UniqueDBusMessage(
616 dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
617 VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
618 VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
619 ret = DBus::CheckErrorMessage(reply.get());
621 dbus_error_free(&error);
625 template <typename ArgType>
626 ClientError ThreadApiDBus::CallDBusMethodAsync(const std::string & aMethodName,
627 const ArgType & aArgs,
628 DBusPendingCallNotifyFunction aFunction)
630 ClientError ret = ClientError::ERROR_NONE;
632 DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
633 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
634 OTBR_DBUS_THREAD_INTERFACE, aMethodName.c_str()));
635 DBusPendingCall * pending = nullptr;
637 VerifyOrExit(message != nullptr, ret = ClientError::ERROR_DBUS);
638 VerifyOrExit(DBus::TupleToDBusMessage(*message, aArgs) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
639 VerifyOrExit(dbus_connection_send_with_reply(mConnection, message.get(), &pending, DBUS_TIMEOUT_USE_DEFAULT) ==
641 ret = ClientError::ERROR_DBUS);
643 VerifyOrExit(dbus_pending_call_set_notify(pending, aFunction, this, &ThreadApiDBus::EmptyFree) == true,
644 ret = ClientError::ERROR_DBUS);
649 template <typename ValType>
650 ClientError ThreadApiDBus::SetProperty(const std::string &aPropertyName, const ValType &aValue)
652 DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
653 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
654 DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_SET_METHOD));
655 DBus::UniqueDBusMessage reply = nullptr;
656 ClientError ret = ClientError::ERROR_NONE;
658 DBusMessageIter iter;
660 dbus_error_init(&error);
661 VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
663 dbus_message_iter_init_append(message.get(), &iter);
664 VerifyOrExit(DBus::DBusMessageEncode(&iter, OTBR_DBUS_THREAD_INTERFACE) == OTBR_ERROR_NONE,
665 ret = ClientError::ERROR_DBUS);
666 VerifyOrExit(DBus::DBusMessageEncode(&iter, aPropertyName) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
667 VerifyOrExit(DBus::DBusMessageEncodeToVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
669 reply = DBus::UniqueDBusMessage(
670 dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
672 VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
673 VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
674 ret = DBus::CheckErrorMessage(reply.get());
676 dbus_error_free(&error);
680 template <typename ValType> ClientError ThreadApiDBus::GetProperty(const std::string &aPropertyName, ValType &aValue)
682 DBus::UniqueDBusMessage message(dbus_message_new_method_call((OTBR_DBUS_SERVER_PREFIX + mInterfaceName).c_str(),
683 (OTBR_DBUS_OBJECT_PREFIX + mInterfaceName).c_str(),
684 DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_METHOD));
685 DBus::UniqueDBusMessage reply = nullptr;
687 ClientError ret = ClientError::ERROR_NONE;
689 DBusMessageIter iter;
691 dbus_error_init(&error);
692 VerifyOrExit(message != nullptr, ret = ClientError::OT_ERROR_FAILED);
693 otbr::DBus::TupleToDBusMessage(*message, std::tie(OTBR_DBUS_THREAD_INTERFACE, aPropertyName));
694 reply = DBus::UniqueDBusMessage(
695 dbus_connection_send_with_reply_and_block(mConnection, message.get(), DBUS_TIMEOUT_USE_DEFAULT, &error));
697 VerifyOrExit(!dbus_error_is_set(&error), ret = DBus::ConvertFromDBusErrorName(error.message));
698 VerifyOrExit(reply != nullptr, ret = ClientError::ERROR_DBUS);
699 SuccessOrExit(DBus::CheckErrorMessage(reply.get()));
700 VerifyOrExit(dbus_message_iter_init(reply.get(), &iter), ret = ClientError::ERROR_DBUS);
701 VerifyOrExit(DBus::DBusMessageExtractFromVariant(&iter, aValue) == OTBR_ERROR_NONE, ret = ClientError::ERROR_DBUS);
704 dbus_error_free(&error);
708 template <void (ThreadApiDBus::*Handler)(DBusPendingCall *aPending)>
709 void ThreadApiDBus::sHandleDBusPendingCall(DBusPendingCall *aPending, void *aThreadApiDBus)
711 ThreadApiDBus *api = static_cast<ThreadApiDBus *>(aThreadApiDBus);
713 (api->*Handler)(aPending);