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