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