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