1 /*
2 * Copyright (c) 2024, 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 "dbus_thread_object_ncp.hpp"
30
31 #include "common/api_strings.hpp"
32 #include "common/byteswap.hpp"
33 #include "common/code_utils.hpp"
34 #include "dbus/common/constants.hpp"
35 #include "dbus/server/dbus_agent.hpp"
36 #include "utils/thread_helper.hpp"
37
38 using std::placeholders::_1;
39 using std::placeholders::_2;
40
41 namespace otbr {
42 namespace DBus {
43
DBusThreadObjectNcp(DBusConnection & aConnection,const std::string & aInterfaceName,otbr::Ncp::NcpHost & aHost)44 DBusThreadObjectNcp::DBusThreadObjectNcp(DBusConnection &aConnection,
45 const std::string &aInterfaceName,
46 otbr::Ncp::NcpHost &aHost)
47 : DBusObject(&aConnection, OTBR_DBUS_OBJECT_PREFIX + aInterfaceName)
48 , mHost(aHost)
49 {
50 }
51
Init(void)52 otbrError DBusThreadObjectNcp::Init(void)
53 {
54 otbrError error = OTBR_ERROR_NONE;
55
56 SuccessOrExit(error = DBusObject::Initialize(true));
57
58 RegisterAsyncGetPropertyHandler(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_PROPERTY_DEVICE_ROLE,
59 std::bind(&DBusThreadObjectNcp::AsyncGetDeviceRoleHandler, this, _1));
60
61 RegisterMethod(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_JOIN_METHOD,
62 std::bind(&DBusThreadObjectNcp::JoinHandler, this, _1));
63 RegisterMethod(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_LEAVE_NETWORK_METHOD,
64 std::bind(&DBusThreadObjectNcp::LeaveHandler, this, _1));
65 RegisterMethod(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_SCHEDULE_MIGRATION_METHOD,
66 std::bind(&DBusThreadObjectNcp::ScheduleMigrationHandler, this, _1));
67
68 SuccessOrExit(error = Signal(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_SIGNAL_READY, std::make_tuple()));
69 exit:
70 return error;
71 }
72
AsyncGetDeviceRoleHandler(DBusRequest & aRequest)73 void DBusThreadObjectNcp::AsyncGetDeviceRoleHandler(DBusRequest &aRequest)
74 {
75 otDeviceRole role = mHost.GetDeviceRole();
76
77 ReplyAsyncGetProperty(aRequest, GetDeviceRoleName(role));
78 }
79
ReplyAsyncGetProperty(DBusRequest & aRequest,const std::string & aContent)80 void DBusThreadObjectNcp::ReplyAsyncGetProperty(DBusRequest &aRequest, const std::string &aContent)
81 {
82 UniqueDBusMessage reply{dbus_message_new_method_return(aRequest.GetMessage())};
83 DBusMessageIter replyIter;
84 otError error = OT_ERROR_NONE;
85
86 dbus_message_iter_init_append(reply.get(), &replyIter);
87 SuccessOrExit(error = OtbrErrorToOtError(DBusMessageEncodeToVariant(&replyIter, aContent)));
88
89 exit:
90 if (error == OT_ERROR_NONE)
91 {
92 dbus_connection_send(aRequest.GetConnection(), reply.get(), nullptr);
93 }
94 else
95 {
96 aRequest.ReplyOtResult(error);
97 }
98 }
99
JoinHandler(DBusRequest & aRequest)100 void DBusThreadObjectNcp::JoinHandler(DBusRequest &aRequest)
101 {
102 std::vector<uint8_t> dataset;
103 otOperationalDatasetTlvs activeOpDatasetTlvs;
104 otError error = OT_ERROR_NONE;
105
106 auto args = std::tie(dataset);
107
108 SuccessOrExit(DBusMessageToTuple(*aRequest.GetMessage(), args), error = OT_ERROR_INVALID_ARGS);
109
110 VerifyOrExit(dataset.size() <= sizeof(activeOpDatasetTlvs.mTlvs), error = OT_ERROR_INVALID_ARGS);
111 std::copy(dataset.begin(), dataset.end(), activeOpDatasetTlvs.mTlvs);
112 activeOpDatasetTlvs.mLength = dataset.size();
113
114 mHost.Join(activeOpDatasetTlvs, [aRequest](otError aError, const std::string &aErrorInfo) mutable {
115 OT_UNUSED_VARIABLE(aErrorInfo);
116 aRequest.ReplyOtResult(aError);
117 });
118
119 exit:
120 if (error != OT_ERROR_NONE)
121 {
122 aRequest.ReplyOtResult(error);
123 }
124 }
125
LeaveHandler(DBusRequest & aRequest)126 void DBusThreadObjectNcp::LeaveHandler(DBusRequest &aRequest)
127 {
128 mHost.Leave([aRequest](otError aError, const std::string &aErrorInfo) mutable {
129 OT_UNUSED_VARIABLE(aErrorInfo);
130 aRequest.ReplyOtResult(aError);
131 });
132 }
133
ScheduleMigrationHandler(DBusRequest & aRequest)134 void DBusThreadObjectNcp::ScheduleMigrationHandler(DBusRequest &aRequest)
135 {
136 std::vector<uint8_t> dataset;
137 uint32_t delayInMilli;
138 otOperationalDatasetTlvs pendingOpDatasetTlvs;
139 otError error = OT_ERROR_NONE;
140
141 auto args = std::tie(dataset, delayInMilli);
142
143 SuccessOrExit(DBusMessageToTuple(*aRequest.GetMessage(), args), error = OT_ERROR_INVALID_ARGS);
144
145 VerifyOrExit(dataset.size() <= sizeof(pendingOpDatasetTlvs.mTlvs), error = OT_ERROR_INVALID_ARGS);
146 std::copy(dataset.begin(), dataset.end(), pendingOpDatasetTlvs.mTlvs);
147 pendingOpDatasetTlvs.mLength = dataset.size();
148
149 SuccessOrExit(error = agent::ThreadHelper::ProcessDatasetForMigration(pendingOpDatasetTlvs, delayInMilli));
150
151 mHost.ScheduleMigration(pendingOpDatasetTlvs, [aRequest](otError aError, const std::string &aErrorInfo) mutable {
152 OT_UNUSED_VARIABLE(aErrorInfo);
153 aRequest.ReplyOtResult(aError);
154 });
155
156 exit:
157 if (error != OT_ERROR_NONE)
158 {
159 aRequest.ReplyOtResult(error);
160 }
161 }
162
163 } // namespace DBus
164 } // namespace otbr
165