1 /*
2 * Copyright (c) 2021 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 <sstream>
17 #include "nlohmann/json.hpp"
18
19 #include "parameter.h"
20
21 #include "dm_ability_manager.h"
22 #include "response_session.h"
23 #include "constants.h"
24 #include "msg_codec.h"
25 #include "device_manager_log.h"
26 #include "device_manager_errno.h"
27 #include "encrypt_utils.h"
28 #include "ipc_server_adapter.h"
29 #include "softbus_adapter.h"
30 #include "softbus_session.h"
31 #include "hichain_connector.h"
32 #include "pthread.h"
33 #include "ipc_server_adapter.h"
34 #include "dm_device_info.h"
35 #include "ipc_server_listener_adapter.h"
36
37 namespace OHOS {
38 namespace DistributedHardware {
39 namespace {
40 const int32_t SESSION_CANCEL_TIMEOUT = 0;
41 const int32_t SESSION_MSG_RECEIVE_TIMEOUT = 5;
42 const int32_t SESSION_WAIT_MEMBER_JOIN_TIMEOUT = 120;
43 const int32_t CANCEL_PICODE_DISPLAY = 1;
44 const int32_t DEVICE_ID_HALF = 2;
45 }
46
ResponseSession()47 ResponseSession::ResponseSession()
48 {
49 mSessionStatus_ = ResponseSessionStatus::SESSION_INIT;
50 sem_init(&mSem_, 0, 0);
51 mRequestId_ = -1;
52 mGroupId_ = "";
53 mGroupName_ = "";
54 mReqDeviceId_ = "";
55 mMsgRequestAuthPtr_ = nullptr;
56 mChannelId_ = -1;
57 mPincode_ = -1;
58 }
59
GetRequestId()60 int64_t ResponseSession::GetRequestId()
61 {
62 return mRequestId_;
63 }
64
SendResponseMessage(int32_t reply)65 int32_t ResponseSession::SendResponseMessage(int32_t reply)
66 {
67 DMLOG(DM_LOG_INFO, "ResponseSession::SendResponseMessage in, reply:%d", reply);
68 std::string msg;
69 if (reply == SESSION_REPLY_ACCEPT) {
70 msg = MsgCodec::EncodeAcceptRespAuth(reply, mRequestId_, mGroupId_, mGroupName_, mReqDeviceId_);
71 } else {
72 msg = MsgCodec::EncodeRefuseRespAuth(reply, mReqDeviceId_);
73 }
74
75 int32_t ret = SoftbusSession::GetInstance().SendMsg(mChannelId_, msg);
76 if (ret != SUCCESS) {
77 DMLOG(DM_LOG_INFO, "SendResponseMessage failed ret:%d, reply:%d", ret, reply);
78 return ret;
79 }
80 DMLOG(DM_LOG_INFO, "SendResponseMessage successed, reply:%d", reply);
81 return SUCCESS;
82 }
83
OnUserOperate(int32_t action)84 void ResponseSession::OnUserOperate(int32_t action)
85 {
86 switch (action) {
87 case FaAction::USER_OPERATION_TYPE_ALLOW_AUTH: {
88 OnUserConfirm();
89 break;
90 }
91 case FaAction::USER_OPERATION_TYPE_CANCEL_AUTH: {
92 OnUserReject(ERROR_USER_REJECT);
93 break;
94 }
95 case FaAction::USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT: {
96 OnUserReject(SESSION_REPLY_AUTH_CONFIRM_TIMEOUT);
97 break;
98 }
99 case FaAction::USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY: {
100 DMLOG(DM_LOG_ERROR, "cancle pincode display");
101 Release();
102 break;
103 }
104 default: {
105 DMLOG(DM_LOG_ERROR, "action %d not support", action);
106 break;
107 }
108 }
109 }
110
DecodeReqMsg(std::string & message)111 int32_t ResponseSession::DecodeReqMsg(std::string &message)
112 {
113 std::shared_ptr<MsgRequestAuth> authMsg = MsgCodec::DecodeRequestAuth(message, mMsgRequestAuthPtr_);
114 if (authMsg == nullptr) {
115 DMLOG(DM_LOG_ERROR, "DecodeRequestAuth error, authMsg(nullptr)");
116 return FAIL;
117 }
118
119 if (authMsg->GetMsgSlice() == FAIL) {
120 DMLOG(DM_LOG_ERROR, "DecodeRequestAuth error, GetMsgSlice() FAIL");
121 return FAIL;
122 }
123
124 mMsgRequestAuthPtr_ = authMsg;
125 return SUCCESS;
126 }
127
IsMyChannelId(long long channelId)128 bool ResponseSession::IsMyChannelId(long long channelId)
129 {
130 if (mSessionStatus_ == ResponseSessionStatus::SESSION_INIT) {
131 return true;
132 }
133
134 return channelId == mChannelId_ && mChannelId_ > 0;
135 }
136
OnReceiveTimeOut(void * data)137 void OnReceiveTimeOut(void *data)
138 {
139 DMLOG(DM_LOG_ERROR, "OnReceiveTimeOut TimeOut called");
140 ResponseSession *respSess = (ResponseSession*)data;
141 if (respSess == nullptr || respSess->GetStatus() == ResponseSessionStatus::SESSION_INIT) {
142 DMLOG(DM_LOG_ERROR, "respSess Status is INIT");
143 return;
144 }
145
146 respSess->Release();
147 }
148
OnMemberJoinTimeOut(void * data)149 void OnMemberJoinTimeOut(void *data)
150 {
151 DMLOG(DM_LOG_ERROR, "OnMemberJoinTimeOut TimeOut caled");
152 ResponseSession *respSess = (ResponseSession*)data;
153 if (respSess == nullptr || respSess->GetStatus() == ResponseSessionStatus::SESSION_INIT) {
154 DMLOG(DM_LOG_ERROR, "respSess Status is INIT");
155 return;
156 }
157
158 respSess->SendResponseMessage(SESSION_REPLY_TIMEOUT);
159 respSess->CancelDisplay();
160 respSess->Release();
161 }
162
OnReceiveMsg(long long channelId,std::string & message)163 void ResponseSession::OnReceiveMsg(long long channelId, std::string &message)
164 {
165 int32_t ret = DecodeReqMsg(message);
166 if (ret != SUCCESS) {
167 DMLOG(DM_LOG_ERROR, "DecodeReqMsg failed");
168 return;
169 }
170
171 if (!mReceiveTimerPtr_) {
172 std::string mReceiveTimerName = "mReceiveTimer";
173 mReceiveTimerPtr_ = std::make_shared<DmTimer>(mReceiveTimerName);
174 }
175
176 mReceiveTimerPtr_->Start(SESSION_MSG_RECEIVE_TIMEOUT, OnReceiveTimeOut, this);
177 if (mMsgRequestAuthPtr_->GetMsgCnt() != mMsgRequestAuthPtr_->GetMsgSlice()) {
178 return;
179 }
180
181 mReceiveTimerPtr_->Stop(SESSION_CANCEL_TIMEOUT);
182 mReqDeviceId_ = mMsgRequestAuthPtr_->GetRequestDeviceId();
183 mChannelId_ = channelId;
184 mPincode_ = GeneratePincode();
185 if (StartFaService() != SUCCESS) {
186 OnUserReject(ERROR_FA_START_FAIL);
187 return;
188 }
189
190 mSessionStatus_ = ResponseSessionStatus::SESSION_WAITTING_USER_CONFIRM;
191 if (!mMemberJoinTimerPtr_) {
192 std::string mMemberJoinTimerName = "mMemberJoinTimer";
193 mMemberJoinTimerPtr_ = std::make_shared<DmTimer>(mMemberJoinTimerName);
194 }
195
196 mMemberJoinTimerPtr_->Start(SESSION_WAIT_MEMBER_JOIN_TIMEOUT, OnMemberJoinTimeOut, this);
197 }
198
GetPinCodeByReqId(int64_t requestId)199 int32_t ResponseSession::GetPinCodeByReqId(int64_t requestId)
200 {
201 if (requestId != mRequestId_) {
202 DMLOG(DM_LOG_ERROR, "ResponseSession:: GetPinCodeByReqId FAIL : requestId(not match)");
203 return FAIL;
204 }
205 return mPincode_;
206 }
207
BuildAuthenticationInfo(DmAuthParam & authParam)208 void ResponseSession::BuildAuthenticationInfo(DmAuthParam &authParam)
209 {
210 DMLOG(DM_LOG_INFO, "ResponseSession::BuildAuthenticationInfo in");
211 authParam.direction = (int32_t)DmAbilityManager::GetInstance().GetAbilityRole();
212 if (mMsgRequestAuthPtr_ == nullptr) {
213 DMLOG(DM_LOG_ERROR, "ResponseSession::BuildAuthenticationInfo mMsgRequestAuthPtr_ is nullptr");
214 return;
215 }
216
217 authParam.packageName = mMsgRequestAuthPtr_->mTargetPkg_;
218 authParam.appName = mMsgRequestAuthPtr_->mAppName_;
219 authParam.appDescription = mMsgRequestAuthPtr_->mAppDescription_;
220 authParam.authType = mMsgRequestAuthPtr_->mAuthType_;
221 authParam.business = BUSINESS_FA_MIRGRATION; // currently, only support BUSINESS_FA_MIRGRATION
222 authParam.pincode = mPincode_;
223
224 if (mMsgRequestAuthPtr_ != nullptr) {
225 authParam.imageinfo = mMsgRequestAuthPtr_->mImageInfo_;
226 }
227 }
228
StartFaService()229 int32_t ResponseSession::StartFaService()
230 {
231 DMLOG(DM_LOG_INFO, "ResponseSession::StartFaService in");
232 AbilityStatus status = DmAbilityManager::GetInstance().StartAbility(AbilityRole::ABILITY_ROLE_PASSIVE);
233 if (status != AbilityStatus::ABILITY_STATUS_SUCCESS) {
234 DMLOG(DM_LOG_ERROR, "ResponseSession::StartFaService timeout");
235 return FAIL;
236 }
237 return SUCCESS;
238 }
239
OnGroupCreated(int64_t requestId,const std::string & groupId)240 void ResponseSession::OnGroupCreated(int64_t requestId, const std::string &groupId)
241 {
242 DMLOG(DM_LOG_INFO, "ResponseSession OnGroupCreated in requestId= %lld groupId = %s ", requestId, groupId.c_str());
243
244 if (requestId != mRequestId_ || groupId.length() == 0) {
245 DMLOG(DM_LOG_ERROR, "ResponseSession::OnGroupCreated failed, requestId %lld, requestId %lld, groupId %s",
246 requestId, mRequestId_, groupId.c_str());
247 SendResponseMessage(SESSION_REPLY_CREAT_GROUP_FAILED);
248 CancelDisplay();
249 mSessionStatus_ = ResponseSessionStatus::SESSION_INIT;
250 return;
251 }
252
253 // save requestId for peer to join, need to be checked in HiChain OnRequest and OnFinish(AddMemberToGroup) callback
254 mRequestId_ = HichainConnector::GetInstance().GenRequestId();
255 mGroupId_ = groupId;
256 int32_t ret = SendResponseMessage(SESSION_REPLY_ACCEPT);
257 if (ret != SUCCESS) {
258 CancelDisplay();
259 mSessionStatus_ = ResponseSessionStatus::SESSION_INIT;
260 return;
261 }
262
263 DMLOG(DM_LOG_INFO, "Send Accept Resoponse success, wait for peer to AddMemberToGroup");
264 mSessionStatus_ = ResponseSessionStatus::SESSION_WAITTING_PIN_CODE;
265 }
266
OnMemberJoin(int64_t requestId,int32_t status)267 void ResponseSession::OnMemberJoin(int64_t requestId, int32_t status)
268 {
269 DMLOG(DM_LOG_INFO, "ResponseSession::OnMemberJoin, result: %d", status);
270 CancelDisplay();
271 mMemberJoinTimerPtr_->Stop(SESSION_CANCEL_TIMEOUT);
272 Release();
273 }
274
GenerateGroupName()275 std::string ResponseSession::GenerateGroupName()
276 {
277 char localDeviceId[DEVICE_UUID_LENGTH] = {0};
278 GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
279 std::string sLocalDeviceID = localDeviceId;
280 std::string groupName = mMsgRequestAuthPtr_->mTargetPkg_ + mMsgRequestAuthPtr_->mHostPkg_ +
281 sLocalDeviceID.substr(0, sLocalDeviceID.size() / DEVICE_ID_HALF);
282 return groupName;
283 }
284
OnUserConfirm()285 void ResponseSession::OnUserConfirm()
286 {
287 DMLOG(DM_LOG_INFO, "ResponseSession::OnUserConfirm in");
288 mGroupName_ = GenerateGroupName();
289 HichainConnector::GetInstance().RegisterConnectorCallback(shared_from_this());
290
291 // save requestId for CreateGroup, need to be checked in callback: OnGroupCreated
292 mRequestId_ = HichainConnector::GetInstance().GenRequestId();
293 int32_t ret = HichainConnector::GetInstance().CreateGroup(mRequestId_, mGroupName_);
294 if (ret != SUCCESS) {
295 CancelDisplay();
296 mSessionStatus_ = ResponseSessionStatus::SESSION_INIT;
297 return;
298 }
299 mSessionStatus_ = ResponseSessionStatus::SESSION_WAITTING_GROUP_CREATED;
300 }
301
OnUserReject(int32_t errorCode)302 void ResponseSession::OnUserReject(int32_t errorCode)
303 {
304 DMLOG(DM_LOG_INFO, "ResponseSession::OnUserReject in, errcode %d", errorCode);
305 SendResponseMessage(errorCode);
306 Release();
307 }
308
Release()309 void ResponseSession::Release()
310 {
311 DMLOG(DM_LOG_INFO, "ResponseSession::Release in");
312 mSessionStatus_ = ResponseSessionStatus::SESSION_INIT;
313 mRequestId_ = -1;
314 mGroupId_ = "";
315 mGroupName_ = "";
316 mReqDeviceId_ = "";
317 mMsgRequestAuthPtr_ = nullptr;
318 mChannelId_ = -1;
319 mPincode_ = -1;
320 }
321
CancelDisplay()322 void ResponseSession::CancelDisplay()
323 {
324 DMLOG(DM_LOG_INFO, "Cancel PinCode Display in");
325 nlohmann::json jsonObj;
326 jsonObj[CANCEL_DISPLAY_KEY] = CANCEL_PICODE_DISPLAY;
327 std::string paramJson = jsonObj.dump();
328 std::string pkgName = "com.ohos.devicemanagerui";
329 IpcServerListenerAdapter::GetInstance().OnFaCall(pkgName, paramJson);
330 DMLOG(DM_LOG_INFO, "Cancel PinCode Display success");
331 }
332
GetStatus()333 int32_t ResponseSession::GetStatus()
334 {
335 return mSessionStatus_;
336 }
337
GeneratePincode()338 int32_t ResponseSession::GeneratePincode()
339 {
340 return EncryptUtils::GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE);
341 }
342 } // namespace DistributedHardware
343 } // namespace OHOS
344