1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "remote_executor_proxy.h"
17 
18 #include <functional>
19 #include <mutex>
20 
21 #include "co_auth_client.h"
22 #include "iam_check.h"
23 #include "iam_logger.h"
24 #include "iam_para2str.h"
25 #include "iam_ptr.h"
26 #include "thread_handler.h"
27 
28 #define LOG_TAG "USER_AUTH_SA"
29 
30 namespace OHOS {
31 namespace UserIam {
32 namespace UserAuth {
33 class RemoteExecutorProxyCallback : public ExecutorRegisterCallback, public NoCopyable {
34 public:
RemoteExecutorProxyCallback(std::weak_ptr<RemoteExecutorProxy> callback)35     explicit RemoteExecutorProxyCallback(std::weak_ptr<RemoteExecutorProxy> callback) : callback_(callback)
36     {
37     }
38     ~RemoteExecutorProxyCallback() override = default;
39 
OnMessengerReady(const std::shared_ptr<ExecutorMessenger> & messenger,const std::vector<uint8_t> & publicKey,const std::vector<uint64_t> & templateIdList)40     void OnMessengerReady(const std::shared_ptr<ExecutorMessenger> &messenger,
41         const std::vector<uint8_t> &publicKey, const std::vector<uint64_t> &templateIdList) override
42     {
43         auto callback = callback_.lock();
44         IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
45         callback->OnMessengerReady(messenger, publicKey, templateIdList);
46     }
47 
OnBeginExecute(uint64_t scheduleId,const std::vector<uint8_t> & publicKey,const Attributes & commandAttrs)48     int32_t OnBeginExecute(uint64_t scheduleId, const std::vector<uint8_t> &publicKey,
49         const Attributes &commandAttrs) override
50     {
51         auto callback = callback_.lock();
52         IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, GENERAL_ERROR);
53         return callback->OnBeginExecute(scheduleId, publicKey, commandAttrs);
54     }
OnEndExecute(uint64_t scheduleId,const Attributes & commandAttrs)55     int32_t OnEndExecute(uint64_t scheduleId, const Attributes &commandAttrs) override
56     {
57         auto callback = callback_.lock();
58         IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, GENERAL_ERROR);
59         return callback->OnEndExecute(scheduleId, commandAttrs);
60     }
61 
OnSetProperty(const Attributes & properties)62     int32_t OnSetProperty(const Attributes &properties) override
63     {
64         IAM_LOGE("OnSetProperty is not supported");
65         return GENERAL_ERROR;
66     }
67 
OnGetProperty(const Attributes & conditions,Attributes & results)68     int32_t OnGetProperty(const Attributes &conditions, Attributes &results) override
69     {
70         IAM_LOGE("OnGetProperty is not supported");
71         return GENERAL_ERROR;
72     }
73 
OnSendData(uint64_t scheduleId,const Attributes & data)74     int32_t OnSendData(uint64_t scheduleId, const Attributes &data) override
75     {
76         auto callback = callback_.lock();
77         IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, GENERAL_ERROR);
78         return callback->OnSendData(scheduleId, data);
79     }
80 
81 private:
82     std::weak_ptr<RemoteExecutorProxy> callback_;
83 };
84 
85 class RemoteExecutorProxyMessageCallback : public ConnectionListener, public NoCopyable {
86 public:
RemoteExecutorProxyMessageCallback(std::weak_ptr<RemoteExecutorProxy> callback)87     explicit RemoteExecutorProxyMessageCallback(std::weak_ptr<RemoteExecutorProxy> callback)
88         : callback_(callback),
89           threadHandler_(ThreadHandler::GetSingleThreadInstance())
90     {
91     }
92     ~RemoteExecutorProxyMessageCallback() = default;
93 
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)94     void OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
95         const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply) override
96     {
97         IF_FALSE_LOGE_AND_RETURN(request != nullptr);
98         IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
99 
100         IAM_LOGI("connectionName: %{public}s, srcEndPoint: %{public}s", connectionName.c_str(), srcEndPoint.c_str());
101 
102         auto callback = callback_.lock();
103         IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
104         callback->OnMessage(connectionName, srcEndPoint, request, reply);
105     }
106 
OnConnectStatus(const std::string & connectionName,ConnectStatus connectStatus)107     void OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus) override
108     {
109         IAM_LOGI("connectionName: %{public}s, connectStatus %{public}d", connectionName.c_str(), connectStatus);
110 
111         IF_FALSE_LOGE_AND_RETURN(connectStatus == ConnectStatus::DISCONNECTED);
112         IF_FALSE_LOGE_AND_RETURN(threadHandler_ != nullptr);
113         threadHandler_->PostTask([connectionName, connectStatus, callbackTemp = callback_, this]() {
114             IAM_LOGI("OnConnectStatus process begin");
115             auto callback = callbackTemp.lock();
116             IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
117             callback->OnConnectStatus(connectionName, connectStatus);
118             IAM_LOGI("OnConnectStatus process success");
119         });
120 
121         IAM_LOGI("task posted");
122     }
123 
124 private:
125     std::weak_ptr<RemoteExecutorProxy> callback_;
126     std::shared_ptr<ThreadHandler> threadHandler_ = nullptr;
127 };
128 
RemoteExecutorProxy(std::string connectionName,ExecutorInfo registerInfo)129 RemoteExecutorProxy::RemoteExecutorProxy(std::string connectionName, ExecutorInfo registerInfo)
130     : connectionName_(connectionName),
131       registerInfo_(registerInfo),
132       endPointName_(EXECUTOR_PROXY_ENDPOINT_NAME)
133 {
134 }
135 
~RemoteExecutorProxy()136 RemoteExecutorProxy::~RemoteExecutorProxy()
137 {
138     IAM_LOGI("start");
139 
140     RemoteConnectionManager::GetInstance().UnregisterConnectionListener(connectionName_, endPointName_);
141     CoAuthClient::GetInstance().Unregister(executorIndex_);
142 
143     IAM_LOGI("success");
144 }
145 
Start()146 ResultCode RemoteExecutorProxy::Start()
147 {
148     IAM_LOGI("start");
149     {
150         std::lock_guard<std::recursive_mutex> lock(mutex_);
151         connectionCallback_ = Common::MakeShared<RemoteExecutorProxyMessageCallback>(weak_from_this());
152         IF_FALSE_LOGE_AND_RETURN_VAL(connectionCallback_ != nullptr, GENERAL_ERROR);
153 
154         ResultCode registerResult = RemoteConnectionManager::GetInstance().RegisterConnectionListener(connectionName_,
155             endPointName_, connectionCallback_);
156         IF_FALSE_LOGE_AND_RETURN_VAL(registerResult == SUCCESS, GENERAL_ERROR);
157 
158         executorCallback_ = Common::MakeShared<RemoteExecutorProxyCallback>(weak_from_this());
159         IF_FALSE_LOGE_AND_RETURN_VAL(executorCallback_ != nullptr, GENERAL_ERROR);
160     }
161 
162     uint64_t executorIndex = CoAuthClient::GetInstance().Register(registerInfo_, executorCallback_);
163     IF_FALSE_LOGE_AND_RETURN_VAL(executorIndex != INVALID_EXECUTOR_INDEX, GENERAL_ERROR);
164 
165     {
166         std::lock_guard<std::recursive_mutex> lock(mutex_);
167         executorIndex_ = executorIndex;
168     }
169 
170     IAM_LOGI("success");
171     return ResultCode::SUCCESS;
172 }
173 
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)174 void RemoteExecutorProxy::OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
175     const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply)
176 {
177     std::lock_guard<std::recursive_mutex> lock(mutex_);
178     IAM_LOGI("start");
179 
180     IF_FALSE_LOGE_AND_RETURN(connectionName_ == connectionName);
181     IF_FALSE_LOGE_AND_RETURN(request != nullptr);
182     IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
183 
184     int32_t msgType;
185     bool getMsgTypeRet = request->GetInt32Value(Attributes::ATTR_MSG_TYPE, msgType);
186     IF_FALSE_LOGE_AND_RETURN(getMsgTypeRet);
187 
188     int32_t resultCode = ResultCode::GENERAL_ERROR;
189     switch (msgType) {
190         case MessageType::EXECUTOR_SEND_DATA:
191             resultCode = ProcSendDataMsg(*request);
192             break;
193         case MessageType::EXECUTOR_FINISH:
194             resultCode = ProcFinishMsg(*request);
195             break;
196         default:
197             IAM_LOGE("unsupported message type: %{public}d", msgType);
198             break;
199     }
200 
201     IF_FALSE_LOGE_AND_RETURN(resultCode == ResultCode::SUCCESS);
202     bool setResultCodeRet = reply->SetInt32Value(Attributes::ATTR_RESULT_CODE, ResultCode::SUCCESS);
203     IF_FALSE_LOGE_AND_RETURN(setResultCodeRet);
204 
205     IAM_LOGI("success");
206 }
207 
OnConnectStatus(const std::string & connectionName,ConnectStatus connectStatus)208 void RemoteExecutorProxy::OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus)
209 {
210 }
211 
OnMessengerReady(const std::shared_ptr<ExecutorMessenger> & messenger,const std::vector<uint8_t> & publicKey,const std::vector<uint64_t> & templateIdList)212 void RemoteExecutorProxy::OnMessengerReady(const std::shared_ptr<ExecutorMessenger> &messenger,
213     const std::vector<uint8_t> &publicKey, const std::vector<uint64_t> &templateIdList)
214 {
215     std::lock_guard<std::recursive_mutex> lock(mutex_);
216     IAM_LOGI("start");
217 
218     messenger_ = messenger;
219     IAM_LOGI("success");
220 }
221 
OnBeginExecute(uint64_t scheduleId,const std::vector<uint8_t> & publicKey,const Attributes & command)222 int32_t RemoteExecutorProxy::OnBeginExecute(uint64_t scheduleId, const std::vector<uint8_t> &publicKey,
223     const Attributes &command)
224 {
225     std::lock_guard<std::recursive_mutex> lock(mutex_);
226     IAM_LOGI("start, scheduleId: %{public}s", GET_MASKED_STRING(scheduleId).c_str());
227 
228     std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>(command.Serialize());
229     IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, GENERAL_ERROR);
230 
231     bool setMessageTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, MessageType::BEGIN_EXECUTE);
232     IF_FALSE_LOGE_AND_RETURN_VAL(setMessageTypeRet, GENERAL_ERROR);
233 
234     bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
235     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleIdRet, GENERAL_ERROR);
236 
237     std::vector<uint8_t> collectorMessage;
238     bool getCollectorMessageRet = request->GetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, collectorMessage);
239     IF_FALSE_LOGE_AND_RETURN_VAL(getCollectorMessageRet, GENERAL_ERROR);
240 
241     bool setScheduleDataRet = request->SetUint8ArrayValue(Attributes::ATTR_SCHEDULE_DATA, collectorMessage);
242     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleDataRet, GENERAL_ERROR);
243 
244     MsgCallback msgCallback = [self = weak_from_this(), scheduleId](const std::shared_ptr<Attributes> &reply) {
245         IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
246 
247         auto sharedSelf = self.lock();
248         IF_FALSE_LOGE_AND_RETURN(sharedSelf != nullptr);
249         int32_t resultCode;
250         bool getResultCodeRet = reply->GetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
251         IF_FALSE_LOGE_AND_RETURN(getResultCodeRet);
252         if (resultCode != ResultCode::SUCCESS) {
253             IAM_LOGE("scheduleId %{public}s begin execute failed", GET_MASKED_STRING(scheduleId).c_str());
254             sharedSelf->OnErrorFinish(scheduleId);
255             return;
256         }
257         IAM_LOGI("scheduleId %{public}s begin execute success", GET_MASKED_STRING(scheduleId).c_str());
258     };
259 
260     ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
261         REMOTE_SERVICE_ENDPOINT_NAME, request, msgCallback);
262     IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == ResultCode::SUCCESS, GENERAL_ERROR);
263 
264     IAM_LOGI("success, scheduleId %{public}s", GET_MASKED_STRING(scheduleId).c_str());
265     return ResultCode::SUCCESS;
266 }
267 
OnEndExecute(uint64_t scheduleId,const Attributes & command)268 int32_t RemoteExecutorProxy::OnEndExecute(uint64_t scheduleId, const Attributes &command)
269 {
270     std::lock_guard<std::recursive_mutex> lock(mutex_);
271     IAM_LOGI("start, scheduleId: %{public}s", GET_MASKED_STRING(scheduleId).c_str());
272 
273     std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>(command.Serialize());
274     IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, GENERAL_ERROR);
275 
276     bool setMessageTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, MessageType::END_EXECUTE);
277     IF_FALSE_LOGE_AND_RETURN_VAL(setMessageTypeRet, GENERAL_ERROR);
278 
279     bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
280     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleIdRet, GENERAL_ERROR);
281 
282     MsgCallback msgCallback = [](const std::shared_ptr<Attributes> &) { IAM_LOGI("message sent"); };
283 
284     ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
285         REMOTE_SERVICE_ENDPOINT_NAME, request, msgCallback);
286     IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == ResultCode::SUCCESS, GENERAL_ERROR);
287 
288     IAM_LOGI("success, scheduleId %{public}s", GET_MASKED_STRING(scheduleId).c_str());
289     return ResultCode::SUCCESS;
290 }
291 
OnSendData(uint64_t scheduleId,const Attributes & data)292 int32_t RemoteExecutorProxy::OnSendData(uint64_t scheduleId, const Attributes &data)
293 {
294     std::lock_guard<std::recursive_mutex> lock(mutex_);
295     IAM_LOGI("start");
296 
297     std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>(data.Serialize());
298     IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, GENERAL_ERROR);
299 
300     bool setMessageTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, MessageType::SEND_DATA_TO_EXECUTOR);
301     IF_FALSE_LOGE_AND_RETURN_VAL(setMessageTypeRet, GENERAL_ERROR);
302 
303     bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
304     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleIdRet, GENERAL_ERROR);
305 
306     MsgCallback msgCallback = [weakThis = weak_from_this(), scheduleId](const std::shared_ptr<Attributes> &reply) {
307         int32_t resultCode;
308         IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
309         bool getResultCodeRet = reply->GetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
310         IF_FALSE_LOGE_AND_RETURN(getResultCodeRet);
311 
312         if (resultCode != ResultCode::SUCCESS) {
313             IAM_LOGE("send data to executor failed");
314             auto sharedThis = weakThis.lock();
315             IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
316             sharedThis->OnErrorFinish(scheduleId);
317             return;
318         }
319     };
320 
321     ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
322         EXECUTOR_STUB_ENDPOINT_NAME, request, msgCallback);
323     IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == ResultCode::SUCCESS, GENERAL_ERROR);
324 
325     IAM_LOGI("success");
326     return ResultCode::SUCCESS;
327 }
328 
ProcSendDataMsg(Attributes & data)329 int32_t RemoteExecutorProxy::ProcSendDataMsg(Attributes &data)
330 {
331     std::lock_guard<std::recursive_mutex> lock(mutex_);
332     IAM_LOGI("start");
333 
334     uint64_t scheduleId;
335     bool getScheduleIdRet = data.GetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
336     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleIdRet, GENERAL_ERROR);
337 
338     int32_t dstRole;
339     bool getDstRoleRet = data.GetInt32Value(Attributes::ATTR_DEST_ROLE, dstRole);
340     IF_FALSE_LOGE_AND_RETURN_VAL(getDstRoleRet, GENERAL_ERROR);
341 
342     auto msg = AuthMessage::As(data.Serialize());
343     IF_FALSE_LOGE_AND_RETURN_VAL(msg != nullptr, GENERAL_ERROR);
344 
345     IAM_LOGI("scheduleId %{public}s send data", GET_MASKED_STRING(scheduleId).c_str());
346     IF_FALSE_LOGE_AND_RETURN_VAL(messenger_ != nullptr, GENERAL_ERROR);
347     int32_t ret = messenger_->SendData(scheduleId, static_cast<ExecutorRole>(dstRole), msg);
348     IF_FALSE_LOGE_AND_RETURN_VAL(ret == SUCCESS, GENERAL_ERROR);
349 
350     IAM_LOGI("success");
351     return ret;
352 }
353 
ProcFinishMsg(Attributes & data)354 int32_t RemoteExecutorProxy::ProcFinishMsg(Attributes &data)
355 {
356     std::lock_guard<std::recursive_mutex> lock(mutex_);
357     IAM_LOGI("start");
358 
359     uint64_t scheduleId;
360     bool getScheduleIdRet = data.GetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
361     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleIdRet, GENERAL_ERROR);
362 
363     int32_t resultCode;
364     bool getResultCodeRet = data.GetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
365     IF_FALSE_LOGE_AND_RETURN_VAL(getResultCodeRet, GENERAL_ERROR);
366 
367     IF_FALSE_LOGE_AND_RETURN_VAL(messenger_ != nullptr, GENERAL_ERROR);
368 
369     IAM_LOGI("scheduleId %{public}s proc finish code %{public}d", GET_MASKED_STRING(scheduleId).c_str(), resultCode);
370     int32_t ret = messenger_->Finish(scheduleId, static_cast<ResultCode>(resultCode), data);
371     IF_FALSE_LOGE_AND_RETURN_VAL(ret == SUCCESS, GENERAL_ERROR);
372     IAM_LOGI("success");
373     return ret;
374 }
375 
OnErrorFinish(uint64_t scheduleId)376 void RemoteExecutorProxy::OnErrorFinish(uint64_t scheduleId)
377 {
378     IAM_LOGI("start");
379     std::lock_guard<std::recursive_mutex> lock(mutex_);
380 
381     Attributes request;
382 
383     bool setScheduleIdRet = request.SetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
384     IF_FALSE_LOGE_AND_RETURN(setScheduleIdRet);
385 
386     bool setResultCodeRet = request.SetInt32Value(Attributes::ATTR_RESULT_CODE, ResultCode::GENERAL_ERROR);
387     IF_FALSE_LOGE_AND_RETURN(setResultCodeRet);
388 
389     ProcFinishMsg(request);
390     IAM_LOGI("success");
391 }
392 } // namespace UserAuth
393 } // namespace UserIam
394 } // namespace OHOS