• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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