1 /*
2  * Copyright (C) 2023 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 "compatible_bind_sub_session.h"
17 
18 #include "callback_manager.h"
19 #include "channel_manager.h"
20 #include "compatible_bind_sub_session_common.h"
21 #include "compatible_bind_sub_session_util.h"
22 #include "das_module_defines.h"
23 #include "dev_auth_module_manager.h"
24 #include "group_operation_common.h"
25 #include "hc_dev_info.h"
26 #include "hc_log.h"
27 #include "hc_time.h"
28 #include "hc_types.h"
29 #include "hitrace_adapter.h"
30 #include "performance_dumper.h"
31 #include "hisysevent_adapter.h"
32 
CheckInvitePeer(const CJson * jsonParams)33 static int32_t CheckInvitePeer(const CJson *jsonParams)
34 {
35     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
36     if (groupId == NULL) {
37         LOGE("Failed to get groupId from jsonParams!");
38         return HC_ERR_JSON_GET;
39     }
40     const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
41     if (appId == NULL) {
42         LOGE("Failed to get appId from jsonParams!");
43         return HC_ERR_JSON_GET;
44     }
45     int32_t osAccountId;
46     if (GetIntFromJson(jsonParams, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
47         LOGE("Failed to get osAccountId from jsonParams!");
48         return HC_ERR_JSON_GET;
49     }
50 
51     uint32_t groupType = PEER_TO_PEER_GROUP;
52     int32_t result;
53     if (((result = CheckGroupExist(osAccountId, groupId)) != HC_SUCCESS) ||
54         ((result = GetGroupTypeFromDb(osAccountId, groupId, &groupType)) != HC_SUCCESS) ||
55         ((result = AssertGroupTypeMatch(groupType, PEER_TO_PEER_GROUP)) != HC_SUCCESS) ||
56         ((result = CheckPermForGroup(osAccountId, MEMBER_INVITE, appId, groupId)) != HC_SUCCESS) ||
57         ((result = CheckDeviceNumLimit(osAccountId, groupId, NULL)) != HC_SUCCESS)) {
58         return result;
59     }
60     return HC_SUCCESS;
61 }
62 
CheckJoinPeer(const CJson * jsonParams)63 static int32_t CheckJoinPeer(const CJson *jsonParams)
64 {
65     int32_t groupType = PEER_TO_PEER_GROUP;
66     if (GetIntFromJson(jsonParams, FIELD_GROUP_TYPE, &groupType) != HC_SUCCESS) {
67         LOGE("Failed to get groupType from jsonParams!");
68         return HC_ERR_JSON_GET;
69     }
70     return AssertGroupTypeMatch(groupType, PEER_TO_PEER_GROUP);
71 }
72 
CheckClientStatus(int operationCode,const CJson * jsonParams)73 static int32_t CheckClientStatus(int operationCode, const CJson *jsonParams)
74 {
75     switch (operationCode) {
76         case MEMBER_INVITE:
77             return CheckInvitePeer(jsonParams);
78         case MEMBER_JOIN:
79             return CheckJoinPeer(jsonParams);
80         default:
81             LOGE("Invalid operation!");
82             return HC_ERR_CASE;
83     }
84 }
85 
GetDuplicateAppId(const CJson * params,char ** returnAppId)86 static int32_t GetDuplicateAppId(const CJson *params, char **returnAppId)
87 {
88     const char *appId = GetStringFromJson(params, FIELD_APP_ID);
89     if (appId == NULL) {
90         LOGE("Failed to get appId from json!");
91         return HC_ERR_JSON_GET;
92     }
93     uint32_t appIdLen = HcStrlen(appId);
94     *returnAppId = (char *)HcMalloc(appIdLen + 1, 0);
95     if (*returnAppId == NULL) {
96         LOGE("Failed to allocate return appId memory!");
97         return HC_ERR_ALLOC_MEMORY;
98     }
99     if (memcpy_s(*returnAppId, appIdLen + 1, appId, appIdLen) != EOK) {
100         LOGE("Failed to copy appId!");
101         HcFree(*returnAppId);
102         *returnAppId = NULL;
103         return HC_ERR_MEMORY_COPY;
104     }
105     return HC_SUCCESS;
106 }
107 
CreateBaseBindSubSession(int32_t sessionType,int32_t opCode,const CJson * params,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)108 static int32_t CreateBaseBindSubSession(int32_t sessionType, int32_t opCode, const CJson *params,
109     const DeviceAuthCallback *callback, CompatibleBaseSubSession **session)
110 {
111     int64_t reqId = DEFAULT_REQUEST_ID;
112     if (GetInt64FromJson(params, FIELD_REQUEST_ID, &reqId) != HC_SUCCESS) {
113         LOGE("Failed to get requestId from params!");
114         return HC_ERR_JSON_GET;
115     }
116 
117     int32_t osAccountId = 0;
118     if (GetIntFromJson(params, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
119         LOGE("Failed to get osAccountId from params!");
120         return HC_ERR_JSON_GET;
121     }
122 
123     CompatibleBindSubSession *subSession = (CompatibleBindSubSession *)HcMalloc(sizeof(CompatibleBindSubSession), 0);
124     if (subSession == NULL) {
125         LOGE("Failed to allocate session memory!");
126         return HC_ERR_ALLOC_MEMORY;
127     }
128 
129     int32_t result = GetDuplicateAppId(params, &(subSession->base.appId));
130     if (result != HC_SUCCESS) {
131         LOGE("Failed to get appId!");
132         HcFree(subSession);
133         return result;
134     }
135     subSession->base.type = sessionType;
136     subSession->base.callback = callback;
137     subSession->base.curTaskId = 0;
138     subSession->base.status = STATUS_INITIAL;
139     subSession->params = NULL;
140     subSession->osAccountId = osAccountId;
141     subSession->opCode = opCode;
142     subSession->moduleType = DAS_MODULE;
143     subSession->reqId = reqId;
144     subSession->channelType = NO_CHANNEL;
145     subSession->channelId = DEFAULT_CHANNEL_ID;
146     *session = (CompatibleBaseSubSession *)subSession;
147     return HC_SUCCESS;
148 }
149 
GenerateKeyPairIfNeeded(int32_t osAccountId,int isClient,int32_t opCode,CJson * jsonParams)150 static int32_t GenerateKeyPairIfNeeded(int32_t osAccountId, int isClient, int32_t opCode, CJson *jsonParams)
151 {
152     if (!IsCreateGroupNeeded(isClient, opCode)) {
153         LOGI("no need to generate local keypair.");
154         return HC_SUCCESS;
155     }
156     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
157     if (groupId == NULL) {
158         LOGE("Failed to get groupId from jsonParams!");
159         return HC_ERR_JSON_GET;
160     }
161     DEV_AUTH_START_TRACE(TRACE_TAG_CREATE_KEY_PAIR);
162     int32_t result = ProcessKeyPair(osAccountId, CREATE_KEY_PAIR, jsonParams, groupId);
163     DEV_AUTH_FINISH_TRACE();
164     if (result != HC_SUCCESS) {
165         LOGE("Failed to create keypair!");
166     }
167     return result;
168 }
169 
CheckServerStatusIfNotInvite(int32_t osAccountId,int operationCode,const CJson * jsonParams)170 static int32_t CheckServerStatusIfNotInvite(int32_t osAccountId, int operationCode, const CJson *jsonParams)
171 {
172     if (operationCode == MEMBER_INVITE) {
173         return HC_SUCCESS;
174     }
175     const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
176     if (groupId == NULL) {
177         LOGE("Failed to get groupId from jsonParams!");
178         return HC_ERR_JSON_GET;
179     }
180     const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
181     if (appId == NULL) {
182         LOGE("Failed to get appId from jsonParams!");
183         return HC_ERR_JSON_GET;
184     }
185     const char *peerUdid = GetStringFromJson(jsonParams, FIELD_CONN_DEVICE_ID);
186     if (peerUdid == NULL) {
187         LOGE("Failed to get peerUdid from jsonParams!");
188         return HC_ERR_JSON_GET;
189     }
190     int32_t result = CheckGroupExist(osAccountId, groupId);
191     if (result != HC_SUCCESS) {
192         return result;
193     }
194     if (operationCode == MEMBER_JOIN) {
195         /* The client sends a join request, which is equivalent to the server performing an invitation operation. */
196         result = CheckPermForGroup(osAccountId, MEMBER_INVITE, appId, groupId);
197         if (result != HC_SUCCESS) {
198             return result;
199         }
200         result = CheckDeviceNumLimit(osAccountId, groupId, peerUdid);
201     }
202     return result;
203 }
204 
CheckAcceptRequest(const CJson * context)205 static int32_t CheckAcceptRequest(const CJson *context)
206 {
207     uint32_t confirmation = REQUEST_REJECTED;
208     (void)GetUnsignedIntFromJson(context, FIELD_CONFIRMATION, &confirmation);
209     if (confirmation != REQUEST_ACCEPTED) {
210         LOGE("The service rejects this request!");
211         return HC_ERR_REQ_REJECTED;
212     }
213     LOGI("The service accepts this request!");
214     return HC_SUCCESS;
215 }
216 
GenerateServerBindParams(CompatibleBindSubSession * session,CJson * jsonParams)217 static int32_t GenerateServerBindParams(CompatibleBindSubSession *session, CJson *jsonParams)
218 {
219     int32_t res = CheckAcceptRequest(jsonParams);
220     if (res != HC_SUCCESS) {
221         return res;
222     }
223     res = CheckServerStatusIfNotInvite(session->osAccountId, session->opCode, jsonParams);
224     if (res != HC_SUCCESS) {
225         return res;
226     }
227     res = GenerateBaseBindParams(session->osAccountId, SERVER, jsonParams, session);
228     if (res != HC_SUCCESS) {
229         return res;
230     }
231     return GenerateKeyPairIfNeeded(session->osAccountId, SERVER, session->opCode, jsonParams);
232 }
233 
CheckPeerStatus(const CJson * params,bool * isNeedInform)234 static int32_t CheckPeerStatus(const CJson *params, bool *isNeedInform)
235 {
236     int32_t errorCode = HC_SUCCESS;
237     if (GetIntFromJson(params, FIELD_GROUP_ERROR_MSG, &errorCode) == HC_SUCCESS) {
238         LOGE("An error occurs in the peer device! [ErrorCode]: %d", errorCode);
239         *isNeedInform = false;
240         return errorCode;
241     }
242     return HC_SUCCESS;
243 }
244 
TryAddPeerUserTypeToParams(const CJson * jsonParams,CompatibleBindSubSession * session)245 static int32_t TryAddPeerUserTypeToParams(const CJson *jsonParams, CompatibleBindSubSession *session)
246 {
247     int32_t peerUserType = DEVICE_TYPE_ACCESSORY;
248     int32_t res = GetIntFromJson(jsonParams, FIELD_PEER_USER_TYPE, &peerUserType);
249     if (res == HC_SUCCESS && AddIntToJson(session->params, FIELD_PEER_USER_TYPE, peerUserType) != HC_SUCCESS) {
250         LOGE("Failed to add peerUserType to params!");
251         return HC_ERR_JSON_ADD;
252     }
253     return HC_SUCCESS;
254 }
255 
InteractWithPeer(const CompatibleBindSubSession * session,CJson * sendData)256 static int32_t InteractWithPeer(const CompatibleBindSubSession *session, CJson *sendData)
257 {
258     int32_t res = AddInfoToBindData(false, session, sendData);
259     if (res != HC_SUCCESS) {
260         LOGE("Failed to generate sendData!");
261         return res;
262     }
263     return TransmitBindSessionData(session, sendData);
264 }
265 
SendBindDataToPeer(CompatibleBindSubSession * session,CJson * out)266 static int32_t SendBindDataToPeer(CompatibleBindSubSession *session, CJson *out)
267 {
268     CJson *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
269     if (sendData == NULL) {
270         LOGE("Failed to get sendToPeer from out!");
271         return HC_ERR_JSON_GET;
272     }
273     int32_t result = InteractWithPeer(session, sendData);
274     FreeJson(sendData);
275     return result;
276 }
277 
ReportV1BindCallEvent(const CompatibleBindSubSession * session)278 static void ReportV1BindCallEvent(const CompatibleBindSubSession *session)
279 {
280 #ifdef DEV_AUTH_HIVIEW_ENABLE
281     DevAuthCallEvent eventData;
282     eventData.appId = session->base.appId;
283     eventData.funcName = ADD_MEMBER_EVENT;
284     eventData.osAccountId = session->osAccountId;
285     eventData.callResult = DEFAULT_CALL_RESULT;
286     eventData.processCode = PROCESS_BIND_V1;
287     eventData.credType = DEFAULT_CRED_TYPE;
288     eventData.groupType = PEER_TO_PEER_GROUP;
289     eventData.executionTime = GET_TOTAL_CONSUME_TIME_BY_REQ_ID(session->reqId);
290     eventData.extInfo = DEFAULT_EXT_INFO;
291     DEV_AUTH_REPORT_CALL_EVENT(eventData);
292     return;
293 #endif
294     (void)session;
295     return;
296 }
297 
InformSelfBindSuccess(const char * peerAuthId,const char * peerUdid,const char * groupId,const CompatibleBindSubSession * session,CJson * out)298 static int32_t InformSelfBindSuccess(const char *peerAuthId, const char *peerUdid, const char *groupId,
299     const CompatibleBindSubSession *session, CJson *out)
300 {
301     uint8_t sessionKey[DEFAULT_RETURN_KEY_LENGTH] = { 0 };
302     if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, DEFAULT_RETURN_KEY_LENGTH) == HC_SUCCESS) {
303         UPDATE_PERFORM_DATA_BY_INPUT_INDEX(session->reqId, ON_SESSION_KEY_RETURN_TIME, HcGetCurTimeInMillis());
304         ProcessSessionKeyCallback(session->reqId, sessionKey, DEFAULT_RETURN_KEY_LENGTH, session->base.callback);
305         (void)memset_s(sessionKey, DEFAULT_RETURN_KEY_LENGTH, 0, DEFAULT_RETURN_KEY_LENGTH);
306         ClearSensitiveStringInJson(out, FIELD_SESSION_KEY);
307     }
308 
309     char *jsonDataStr = NULL;
310     int32_t result = GenerateBindSuccessData(peerAuthId, peerUdid, groupId, &jsonDataStr);
311     if (result != HC_SUCCESS) {
312         LOGE("Failed to generate the data to be sent to the service!");
313         return result;
314     }
315     UPDATE_PERFORM_DATA_BY_INPUT_INDEX(session->reqId, ON_FINISH_TIME, HcGetCurTimeInMillis());
316     ProcessFinishCallback(session->reqId, session->opCode, jsonDataStr, session->base.callback);
317     FreeJsonString(jsonDataStr);
318     ReportV1BindCallEvent(session);
319     return HC_SUCCESS;
320 }
321 
SetGroupId(const CJson * params,TrustedGroupEntry * groupParams)322 static int32_t SetGroupId(const CJson *params, TrustedGroupEntry *groupParams)
323 {
324     const char *groupId = GetStringFromJson(params, FIELD_GROUP_ID);
325     if (groupId == NULL) {
326         LOGE("Failed to get groupId from params!");
327         return HC_ERR_JSON_GET;
328     }
329     if (!StringSetPointer(&groupParams->id, groupId)) {
330         LOGE("Failed to copy groupId!");
331         return HC_ERR_MEMORY_COPY;
332     }
333     return HC_SUCCESS;
334 }
335 
SetGroupName(const CJson * params,TrustedGroupEntry * groupParams)336 static int32_t SetGroupName(const CJson *params, TrustedGroupEntry *groupParams)
337 {
338     const char *groupName = GetStringFromJson(params, FIELD_GROUP_NAME);
339     if (groupName == NULL) {
340         LOGE("Failed to get groupName from params!");
341         return HC_ERR_JSON_GET;
342     }
343     if (!StringSetPointer(&groupParams->name, groupName)) {
344         LOGE("Failed to copy groupName!");
345         return HC_ERR_MEMORY_COPY;
346     }
347     return HC_SUCCESS;
348 }
349 
SetGroupOwner(const char * ownerAppId,TrustedGroupEntry * groupParams)350 static int32_t SetGroupOwner(const char *ownerAppId, TrustedGroupEntry *groupParams)
351 {
352     HcString ownerName = CreateString();
353     if (!StringSetPointer(&ownerName, ownerAppId)) {
354         LOGE("Failed to copy groupOwner!");
355         DeleteString(&ownerName);
356         return HC_ERR_MEMORY_COPY;
357     }
358     if (groupParams->managers.pushBackT(&groupParams->managers, ownerName) == NULL) {
359         LOGE("Failed to push owner to vec!");
360         DeleteString(&ownerName);
361         return HC_ERR_MEMORY_COPY;
362     }
363     return HC_SUCCESS;
364 }
365 
SetGroupType(TrustedGroupEntry * groupParams)366 static int32_t SetGroupType(TrustedGroupEntry *groupParams)
367 {
368     groupParams->type = PEER_TO_PEER_GROUP;
369     return HC_SUCCESS;
370 }
371 
SetGroupVisibility(const CJson * params,TrustedGroupEntry * groupParams)372 static int32_t SetGroupVisibility(const CJson *params, TrustedGroupEntry *groupParams)
373 {
374     int32_t groupVisibility = GROUP_VISIBILITY_PUBLIC;
375     (void)GetIntFromJson(params, FIELD_GROUP_VISIBILITY, &groupVisibility);
376     groupParams->visibility = groupVisibility;
377     return HC_SUCCESS;
378 }
379 
SetGroupExpireTime(const CJson * params,TrustedGroupEntry * groupParams)380 static int32_t SetGroupExpireTime(const CJson *params, TrustedGroupEntry *groupParams)
381 {
382     int32_t expireTime = DEFAULT_EXPIRE_TIME;
383     (void)GetIntFromJson(params, FIELD_EXPIRE_TIME, &expireTime);
384     groupParams->expireTime = expireTime;
385     return HC_SUCCESS;
386 }
387 
GenerateGroupParams(const CompatibleBindSubSession * session,TrustedGroupEntry * groupParams)388 static int32_t GenerateGroupParams(const CompatibleBindSubSession *session, TrustedGroupEntry *groupParams)
389 {
390     int32_t result;
391     if (((result = SetGroupId(session->params, groupParams)) != HC_SUCCESS) ||
392         ((result = SetGroupName(session->params, groupParams)) != HC_SUCCESS) ||
393         ((result = SetGroupOwner(session->base.appId, groupParams)) != HC_SUCCESS) ||
394         ((result = SetGroupType(groupParams)) != HC_SUCCESS) ||
395         ((result = SetGroupVisibility(session->params, groupParams)) != HC_SUCCESS) ||
396         ((result = SetGroupExpireTime(session->params, groupParams)) != HC_SUCCESS)) {
397         return result;
398     }
399     return HC_SUCCESS;
400 }
401 
AddGroupToDatabase(const CompatibleBindSubSession * session)402 static int32_t AddGroupToDatabase(const CompatibleBindSubSession *session)
403 {
404     TrustedGroupEntry *groupParams = CreateGroupEntry();
405     if (groupParams == NULL) {
406         LOGE("Failed to allocate groupParams memory!");
407         return HC_ERR_ALLOC_MEMORY;
408     }
409     int32_t result = GenerateGroupParams(session, groupParams);
410     if (result != HC_SUCCESS) {
411         LOGE("Failed to generate groupParams!");
412         DestroyGroupEntry(groupParams);
413         return result;
414     }
415     result = AddGroup(session->osAccountId, groupParams);
416     DestroyGroupEntry(groupParams);
417     if (result != HC_SUCCESS) {
418         LOGE("Failed to add the group to the database!");
419         return result;
420     }
421     return HC_SUCCESS;
422 }
423 
GenerateDevAuthParams(const char * authId,const char * udid,const char * groupId,int userType,TrustedDeviceEntry * devAuthParams)424 static void GenerateDevAuthParams(const char *authId, const char *udid, const char *groupId,
425     int userType, TrustedDeviceEntry *devAuthParams)
426 {
427     devAuthParams->devType = userType;
428     devAuthParams->source = SELF_CREATED;
429     StringSetPointer(&(devAuthParams->authId), authId);
430     StringSetPointer(&(devAuthParams->udid), udid);
431     StringSetPointer(&(devAuthParams->groupId), groupId);
432     StringSetPointer(&(devAuthParams->serviceType), groupId);
433 }
434 
AddTrustDevToDatabase(int32_t osAccountId,const char * authId,const char * udid,const char * groupId,int userType)435 static int32_t AddTrustDevToDatabase(int32_t osAccountId, const char *authId, const char *udid, const char *groupId,
436     int userType)
437 {
438     TrustedDeviceEntry *devAuthParams = CreateDeviceEntry();
439     if (devAuthParams == NULL) {
440         LOGE("Failed to allocate devAuthParams memory!");
441         return HC_ERR_ALLOC_MEMORY;
442     }
443     GenerateDevAuthParams(authId, udid, groupId, userType, devAuthParams);
444     int32_t result = AddTrustedDevice(osAccountId, devAuthParams);
445     DestroyDeviceEntry(devAuthParams);
446     if (result != HC_SUCCESS) {
447         LOGE("Failed to add the trusted devices to the database!");
448         return result;
449     }
450     return HC_SUCCESS;
451 }
452 
AddGroupAndLocalDevIfNotExist(const char * groupId,const CompatibleBindSubSession * session)453 static int32_t AddGroupAndLocalDevIfNotExist(const char *groupId, const CompatibleBindSubSession *session)
454 {
455     if (IsGroupExistByGroupId(session->osAccountId, groupId)) {
456         return HC_SUCCESS;
457     }
458     char udid[INPUT_UDID_LEN] = { 0 };
459     int32_t result = HcGetUdid((uint8_t *)udid, INPUT_UDID_LEN);
460     if (result != HC_SUCCESS) {
461         LOGE("Failed to get local udid! res: %d", result);
462         return result;
463     }
464     result = AddGroupToDatabase(session);
465     if (result != HC_SUCCESS) {
466         return result;
467     }
468     const char *authId = GetStringFromJson(session->params, FIELD_AUTH_ID);
469     if (authId == NULL) {
470         LOGI("No authId is found. The default value is udid!");
471         authId = udid;
472     }
473     int32_t userType = DEVICE_TYPE_ACCESSORY;
474     (void)GetIntFromJson(session->params, FIELD_USER_TYPE, &userType);
475     return AddTrustDevToDatabase(session->osAccountId, authId, udid, groupId, userType);
476 }
477 
AddPeerDevToGroup(const char * peerAuthId,const char * peerUdid,const char * groupId,const CompatibleBindSubSession * session)478 static int32_t AddPeerDevToGroup(const char *peerAuthId, const char *peerUdid,
479     const char *groupId, const CompatibleBindSubSession *session)
480 {
481     int32_t peerUserType = DEVICE_TYPE_ACCESSORY;
482     (void)GetIntFromJson(session->params, FIELD_PEER_USER_TYPE, &peerUserType);
483     int32_t result = AddTrustDevToDatabase(session->osAccountId, peerAuthId, peerUdid, groupId, peerUserType);
484     if (result != HC_SUCCESS) {
485         LOGE("Failed to add the peer trusted device information! RequestId: %" PRId64, session->reqId);
486         return result;
487     }
488     LOGI("The peer trusted device is added to the database successfully! RequestId: %" PRId64, session->reqId);
489     return HC_SUCCESS;
490 }
491 
AddGroupAndDev(const char * peerAuthId,const char * peerUdid,const char * groupId,const CompatibleBindSubSession * session)492 static int32_t AddGroupAndDev(const char *peerAuthId, const char *peerUdid, const char *groupId,
493     const CompatibleBindSubSession *session)
494 {
495     int32_t result = AddGroupAndLocalDevIfNotExist(groupId, session);
496     if (result != HC_SUCCESS) {
497         return result;
498     }
499     result = AddPeerDevToGroup(peerAuthId, peerUdid, groupId, session);
500     if (result != HC_SUCCESS) {
501         return result;
502     }
503     return SaveOsAccountDb(session->osAccountId);
504 }
505 
HandleBindSuccess(const char * peerAuthId,const char * peerUdid,const char * groupId,const CompatibleBindSubSession * session,CJson * out)506 static int32_t HandleBindSuccess(const char *peerAuthId, const char *peerUdid, const char *groupId,
507     const CompatibleBindSubSession *session, CJson *out)
508 {
509     DEV_AUTH_START_TRACE(TRACE_TAG_ADD_TRUSTED_DEVICE);
510     int32_t result = AddGroupAndDev(peerAuthId, peerUdid, groupId, session);
511     DEV_AUTH_FINISH_TRACE();
512     if (result != HC_SUCCESS) {
513         return result;
514     }
515     return InformSelfBindSuccess(peerAuthId, peerUdid, groupId, session, out);
516 }
517 
OnBindFinish(const CompatibleBindSubSession * session,const CJson * jsonParams,CJson * out)518 static int32_t OnBindFinish(const CompatibleBindSubSession *session, const CJson *jsonParams, CJson *out)
519 {
520     const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_PEER_DEVICE_ID);
521     if (peerAuthId == NULL) {
522         peerAuthId = GetStringFromJson(session->params, FIELD_PEER_AUTH_ID);
523         if (peerAuthId == NULL) {
524             LOGE("Failed to get peerAuthId from jsonParams and params!");
525             return HC_ERR_JSON_GET;
526         }
527     }
528     const char *peerUdid = GetStringFromJson(jsonParams, FIELD_CONN_DEVICE_ID);
529     if (peerUdid == NULL) {
530         peerUdid = GetStringFromJson(session->params, FIELD_PEER_UDID);
531         if (peerUdid == NULL) {
532             LOGE("Failed to get peerUdid from jsonParams and params!");
533             return HC_ERR_JSON_GET;
534         }
535     }
536     const char *groupId = GetStringFromJson(session->params, FIELD_GROUP_ID);
537     if (groupId == NULL) {
538         LOGE("Failed to get groupId from session params!");
539         return HC_ERR_JSON_GET;
540     }
541     return HandleBindSuccess(peerAuthId, peerUdid, groupId, session, out);
542 }
543 
OnSessionFinish(const CompatibleBindSubSession * session,CJson * jsonParams,CJson * out)544 static int32_t OnSessionFinish(const CompatibleBindSubSession *session, CJson *jsonParams, CJson *out)
545 {
546     int32_t result;
547     CJson *sendData = GetObjFromJson(out, FIELD_SEND_TO_PEER);
548     /* The last packet may need to be sent. */
549     if (sendData != NULL) {
550         result = InteractWithPeer(session, sendData);
551         if (result != HC_SUCCESS) {
552             return result;
553         }
554     }
555     result = OnBindFinish(session, jsonParams, out);
556     if (result != HC_SUCCESS) {
557         LOGE("An error occurred when processing different end operations!");
558         return result;
559     }
560     LOGI("The session completed successfully! [ReqId]: %" PRId64, session->reqId);
561     NotifyBindResult((ChannelType)session->channelType, session->channelId);
562     CloseChannel((ChannelType)session->channelType, session->channelId);
563     return HC_SUCCESS;
564 }
565 
InformPeerModuleError(CJson * out,const CompatibleBindSubSession * session)566 static void InformPeerModuleError(CJson *out, const CompatibleBindSubSession *session)
567 {
568     CJson *errorData = GetObjFromJson(out, FIELD_SEND_TO_PEER);
569     if (errorData == NULL) {
570         return;
571     }
572     if (AddStringToJson(errorData, FIELD_APP_ID, session->base.appId) != HC_SUCCESS) {
573         LOGE("Failed to add appId to errorData!");
574         return;
575     }
576     if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, session->reqId) != HC_SUCCESS) {
577         LOGE("Failed to add requestId to errorData!");
578         return;
579     }
580     if (AddInfoToBindData(false, session, errorData) != HC_SUCCESS) {
581         LOGE("Failed to add info to error data!");
582         return;
583     }
584     if (TransmitBindSessionData(session, errorData) != HC_SUCCESS) {
585         LOGE("An error occurred when notifying the peer service!");
586     } else {
587         LOGI("Succeeded in notifying the peer device that an error occurred at the local end!");
588     }
589 }
590 
ProcessModule(const CompatibleBindSubSession * session,const CJson * in,CJson * out,int32_t * status)591 static int32_t ProcessModule(const CompatibleBindSubSession *session, const CJson *in, CJson *out, int32_t *status)
592 {
593     LOGI("Start to process module task! [ModuleType]: %d", session->moduleType);
594     DEV_AUTH_START_TRACE(TRACE_TAG_PROCESS_AUTH_TASK);
595     int32_t res = ProcessTask(session->base.curTaskId, in, out, status, session->moduleType);
596     DEV_AUTH_FINISH_TRACE();
597     if (res != HC_SUCCESS) {
598         LOGE("Failed to process module task! res: %d", res);
599         return res;
600     }
601     LOGI("Process module task successfully!");
602     return HC_SUCCESS;
603 }
604 
ProcessBindTaskInner(CompatibleBindSubSession * session,CJson * in,int32_t * status,bool * isNeedInform)605 static int32_t ProcessBindTaskInner(CompatibleBindSubSession *session, CJson *in, int32_t *status, bool *isNeedInform)
606 {
607     int32_t result;
608     if (((result = CheckPeerStatus(in, isNeedInform)) != HC_SUCCESS) ||
609         ((result = TryAddPeerUserTypeToParams(in, session))) != HC_SUCCESS) {
610         return result;
611     }
612 
613     CJson *out = CreateJson();
614     if (out == NULL) {
615         LOGE("Failed to allocate out memory!");
616         return HC_ERR_JSON_CREATE;
617     }
618     result = ProcessModule(session, in, out, status);
619     if (result != HC_SUCCESS) {
620         *isNeedInform = false;
621         InformPeerModuleError(out, session);
622         FreeJson(out);
623         return result;
624     }
625     if (*status == IGNORE_MSG) {
626         LOGI("The msg is ignored!");
627     } else if (*status == CONTINUE) {
628         DeleteAllItem(in);
629         result = SendBindDataToPeer(session, out);
630     } else {
631         DEV_AUTH_START_TRACE(TRACE_TAG_ON_SESSION_FINISH);
632         result = OnSessionFinish(session, in, out);
633         DEV_AUTH_FINISH_TRACE();
634     }
635     FreeJson(out);
636     return result;
637 }
638 
ProcessBindTask(CompatibleBindSubSession * session,CJson * in,int32_t * status)639 static int32_t ProcessBindTask(CompatibleBindSubSession *session, CJson *in, int32_t *status)
640 {
641     bool isNeedInform = true;
642     int32_t result = ProcessBindTaskInner(session, in, status, &isNeedInform);
643     if (result != HC_SUCCESS) {
644         LOGE("Failed to process bind task!");
645         InformPeerGroupErrorIfNeeded(isNeedInform, result, session);
646         return result;
647     }
648     LOGI("Process bind session successfully! [ReqId]: %" PRId64, session->reqId);
649     if (*status == FINISH) {
650         return FINISH;
651     }
652     return HC_SUCCESS;
653 }
654 
GenerateClientModuleParams(CompatibleBindSubSession * session,CJson * moduleParams)655 static int32_t GenerateClientModuleParams(CompatibleBindSubSession *session, CJson *moduleParams)
656 {
657     if (AddIntToJson(moduleParams, FIELD_OPERATION_CODE, OP_BIND) != HC_SUCCESS) {
658         LOGE("Failed to add operationCode to moduleParams!");
659         return HC_ERR_JSON_ADD;
660     }
661     return GenerateBaseModuleParams(true, session, moduleParams);
662 }
663 
GetClientModuleReturnData(CompatibleBindSubSession * session,CJson * out,int32_t * status)664 static int32_t GetClientModuleReturnData(CompatibleBindSubSession *session, CJson *out, int32_t *status)
665 {
666     CJson *moduleParams = CreateJson();
667     if (moduleParams == NULL) {
668         LOGE("Failed to allocate moduleParams memory!");
669         return HC_ERR_JSON_CREATE;
670     }
671 
672     int32_t result = GenerateClientModuleParams(session, moduleParams);
673     if (result != HC_SUCCESS) {
674         LOGE("Failed to generate all params sent to the module!");
675         FreeJson(moduleParams);
676         return result;
677     }
678 
679     result = CreateAndProcessBindTask(session, moduleParams, out, status);
680     FreeJson(moduleParams);
681     return result;
682 }
683 
CreateAndProcessClientBindTask(CompatibleBindSubSession * session,CJson ** sendData,int32_t * status)684 static int32_t CreateAndProcessClientBindTask(CompatibleBindSubSession *session, CJson **sendData, int32_t *status)
685 {
686     CJson *out = CreateJson();
687     if (out == NULL) {
688         LOGE("Failed to allocate out memory!");
689         return HC_ERR_JSON_CREATE;
690     }
691     int32_t result = GetClientModuleReturnData(session, out, status);
692     if (result != HC_SUCCESS) {
693         FreeJson(out);
694         return result;
695     }
696 
697     *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
698     FreeJson(out);
699     if (*sendData == NULL) {
700         LOGE("Failed to get sendToPeer from out!");
701         return HC_ERR_JSON_GET;
702     }
703 
704     result = AddInfoToBindData(false, session, *sendData);
705     if (result != HC_SUCCESS) {
706         LOGE("Failed to add information to sendData!");
707         FreeJson(*sendData);
708         *sendData = NULL;
709     }
710     return result;
711 }
712 
AddConfirmationToParams(CJson * moduleParams)713 static int32_t AddConfirmationToParams(CJson *moduleParams)
714 {
715     if (AddIntToJson(moduleParams, FIELD_CONFIRMATION, REQUEST_ACCEPTED) != HC_SUCCESS) {
716         LOGE("Failed to add confirmation to moduleParams!");
717         return HC_ERR_JSON_ADD;
718     }
719     return HC_SUCCESS;
720 }
721 
AddRecvModuleDataToParams(CJson * jsonParams,CJson * moduleParams)722 static int32_t AddRecvModuleDataToParams(CJson *jsonParams, CJson *moduleParams)
723 {
724     int32_t message = ERR_MESSAGE;
725     if (GetIntFromJson(jsonParams, FIELD_MESSAGE, &message) != HC_SUCCESS) {
726         LOGE("Failed to get message from in!");
727         return HC_ERR_JSON_GET;
728     }
729     int32_t authForm = AUTH_FORM_INVALID_TYPE;
730     (void)GetIntFromJson(jsonParams, FIELD_AUTH_FORM, &authForm);
731     CJson *payload = GetObjFromJson(jsonParams, FIELD_PAYLOAD);
732     if (payload == NULL) {
733         LOGE("Failed to get payload from in!");
734         return HC_ERR_JSON_GET;
735     }
736     if (AddIntToJson(moduleParams, FIELD_MESSAGE, message) != HC_SUCCESS) {
737         LOGE("Failed to add message to moduleParams!");
738         return HC_ERR_JSON_ADD;
739     }
740     if (AddIntToJson(moduleParams, FIELD_AUTH_FORM, authForm) != HC_SUCCESS) {
741         LOGE("Failed to add authForm to moduleParams!");
742         return HC_ERR_JSON_ADD;
743     }
744     if (AddObjToJson(moduleParams, FIELD_PAYLOAD, payload) != HC_SUCCESS) {
745         LOGE("Failed to add payload to moduleParams!");
746         return HC_ERR_JSON_ADD;
747     }
748     return HC_SUCCESS;
749 }
750 
GenerateServerModuleParams(CompatibleBindSubSession * session,CJson * jsonParams,CJson * moduleParams)751 static int32_t GenerateServerModuleParams(CompatibleBindSubSession *session, CJson *jsonParams, CJson *moduleParams)
752 {
753     int32_t result;
754     if (((result = GenerateBaseModuleParams(false, session, moduleParams)) != HC_SUCCESS) ||
755         ((result = AddConfirmationToParams(moduleParams)) != HC_SUCCESS) ||
756         ((result = AddRecvModuleDataToParams(jsonParams, moduleParams)) != HC_SUCCESS)) {
757         return result;
758     }
759     return HC_SUCCESS;
760 }
761 
GetServerModuleReturnData(CompatibleBindSubSession * session,CJson * jsonParams,CJson * out,bool * isNeedInform,int32_t * status)762 static int32_t GetServerModuleReturnData(CompatibleBindSubSession *session, CJson *jsonParams, CJson *out,
763     bool *isNeedInform, int32_t *status)
764 {
765     CJson *moduleParams = CreateJson();
766     if (moduleParams == NULL) {
767         LOGE("Failed to allocate moduleParams memory!");
768         return HC_ERR_JSON_CREATE;
769     }
770 
771     int32_t result = GenerateServerModuleParams(session, jsonParams, moduleParams);
772     if (result != HC_SUCCESS) {
773         LOGE("Failed to generate all params sent to the module!");
774         FreeJson(moduleParams);
775         return result;
776     }
777     /* Release the memory in advance to reduce the memory usage. */
778     DeleteAllItem(jsonParams);
779 
780     result = CreateAndProcessBindTask(session, moduleParams, out, status);
781     FreeJson(moduleParams);
782     if (result != HC_SUCCESS) {
783         *isNeedInform = false;
784         InformPeerModuleError(out, session);
785     }
786     return result;
787 }
788 
PrepareServerData(CompatibleBindSubSession * session,CJson * jsonParams,CJson ** sendData,bool * isNeedInform,int32_t * status)789 static int32_t PrepareServerData(CompatibleBindSubSession *session, CJson *jsonParams, CJson **sendData,
790     bool *isNeedInform, int32_t *status)
791 {
792     CJson *out = CreateJson();
793     if (out == NULL) {
794         LOGE("Failed to allocate out memory!");
795         return HC_ERR_JSON_CREATE;
796     }
797 
798     int32_t result = GetServerModuleReturnData(session, jsonParams, out, isNeedInform, status);
799     if (result != HC_SUCCESS) {
800         FreeJson(out);
801         return result;
802     }
803 
804     *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
805     FreeJson(out);
806     if (*sendData == NULL) {
807         LOGE("Failed to get sendToPeer from out!");
808         return HC_ERR_JSON_GET;
809     }
810 
811     result = AddInfoToBindData((session->opCode == MEMBER_JOIN), session, *sendData);
812     if (result != HC_SUCCESS) {
813         LOGE("Failed to add information to sendData!");
814         FreeJson(*sendData);
815         *sendData = NULL;
816     }
817     return result;
818 }
819 
PrepareAndSendServerData(CompatibleBindSubSession * session,CJson * jsonParams,bool * isNeedInform,int32_t * status)820 static int32_t PrepareAndSendServerData(CompatibleBindSubSession *session, CJson *jsonParams,
821     bool *isNeedInform, int32_t *status)
822 {
823     CJson *sendData = NULL;
824     int32_t result = PrepareServerData(session, jsonParams, &sendData, isNeedInform, status);
825     if (result != HC_SUCCESS) {
826         return result;
827     }
828 
829     result = TransmitBindSessionData(session, sendData);
830     FreeJson(sendData);
831     return result;
832 }
833 
InitChannel(const CJson * params,CompatibleBindSubSession * session)834 static int32_t InitChannel(const CJson *params, CompatibleBindSubSession *session)
835 {
836     if (GetByteFromJson(params, FIELD_CHANNEL_ID, (uint8_t *)&session->channelId, sizeof(int64_t)) != HC_SUCCESS) {
837         LOGE("Failed to get channelId!");
838         return HC_ERR_JSON_GET;
839     }
840     if (GetIntFromJson(params, FIELD_CHANNEL_TYPE, &session->channelType) != HC_SUCCESS) {
841         LOGE("Failed to get channel type!");
842         return HC_ERR_JSON_GET;
843     }
844     return HC_SUCCESS;
845 }
846 
CreateClientBindSubSession(CJson * jsonParams,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)847 int32_t CreateClientBindSubSession(CJson *jsonParams, const DeviceAuthCallback *callback,
848     CompatibleBaseSubSession **session)
849 {
850     int64_t requestId = DEFAULT_REQUEST_ID;
851     if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &requestId) != HC_SUCCESS) {
852         LOGE("Failed to get requestId from params!");
853         return HC_ERR_JSON_GET;
854     }
855 
856     int32_t opCode = MEMBER_INVITE;
857     if (GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &opCode) != HC_SUCCESS) {
858         LOGE("Failed to get opCode from params!");
859         return HC_ERR_JSON_GET;
860     }
861 
862     int32_t result = CheckClientStatus(opCode, jsonParams);
863     if (result != HC_SUCCESS) {
864         LOGE("Failed to check client status!");
865         return result;
866     }
867 
868     result = CreateBaseBindSubSession(TYPE_CLIENT_BIND_SUB_SESSION, opCode, jsonParams, callback, session);
869     if (result != HC_SUCCESS) {
870         return result;
871     }
872 
873     CompatibleBindSubSession *subSession = (CompatibleBindSubSession *)(*session);
874     result = GenerateKeyPairIfNeeded(subSession->osAccountId, CLIENT, opCode, jsonParams);
875     if (result != HC_SUCCESS) {
876         DestroyCompatibleBindSubSession(*session);
877         *session = NULL;
878         return result;
879     }
880     result = InitChannel(jsonParams, subSession);
881     if (result != HC_SUCCESS) {
882         DestroyCompatibleBindSubSession(*session);
883         *session = NULL;
884         return result;
885     }
886     result = GenerateBaseBindParams(subSession->osAccountId, CLIENT, jsonParams, subSession);
887     if (result != HC_SUCCESS) {
888         DestroyCompatibleBindSubSession(*session);
889         *session = NULL;
890     }
891     return result;
892 }
893 
CreateServerBindSubSession(CJson * jsonParams,const DeviceAuthCallback * callback,CompatibleBaseSubSession ** session)894 int32_t CreateServerBindSubSession(CJson *jsonParams, const DeviceAuthCallback *callback,
895     CompatibleBaseSubSession **session)
896 {
897     int64_t reqId = DEFAULT_REQUEST_ID;
898     if (GetInt64FromJson(jsonParams, FIELD_REQUEST_ID, &reqId) != HC_SUCCESS) {
899         LOGE("Failed to get requestId from params!");
900         return HC_ERR_JSON_GET;
901     }
902     int32_t opCode = MEMBER_INVITE;
903     if (GetIntFromJson(jsonParams, FIELD_GROUP_OP, &opCode) != HC_SUCCESS) {
904         LOGE("Failed to get operation code from params!");
905         return HC_ERR_JSON_GET;
906     }
907     int32_t result = CreateBaseBindSubSession(TYPE_SERVER_BIND_SUB_SESSION, opCode, jsonParams, callback, session);
908     if (result != HC_SUCCESS) {
909         InformPeerProcessError(reqId, jsonParams, callback, result);
910         return result;
911     }
912     CompatibleBindSubSession *subSession = (CompatibleBindSubSession *)(*session);
913     result = InitChannel(jsonParams, subSession);
914     if (result != HC_SUCCESS) {
915         InformPeerGroupErrorIfNeeded(true, result, subSession);
916         DestroyCompatibleBindSubSession(*session);
917         *session = NULL;
918         return result;
919     }
920     result = GenerateServerBindParams(subSession, jsonParams);
921     if (result != HC_SUCCESS) {
922         InformPeerGroupErrorIfNeeded(true, result, subSession);
923         DestroyCompatibleBindSubSession(*session);
924         *session = NULL;
925     }
926     return result;
927 }
928 
ProcessClientBindSubSession(CompatibleBaseSubSession * session,CJson * in,CJson ** out,int32_t * status)929 int32_t ProcessClientBindSubSession(CompatibleBaseSubSession *session, CJson *in, CJson **out, int32_t *status)
930 {
931     CompatibleBindSubSession *subSession = (CompatibleBindSubSession *)session;
932     if (session->status == STATUS_PROCESSING) {
933         return ProcessBindTask(subSession, in, status);
934     } else {
935         session->status = STATUS_PROCESSING;
936         return CreateAndProcessClientBindTask(subSession, out, status);
937     }
938 }
939 
ProcessServerBindSubSession(CompatibleBaseSubSession * session,CJson * in,int32_t * status)940 int32_t ProcessServerBindSubSession(CompatibleBaseSubSession *session, CJson *in, int32_t *status)
941 {
942     CompatibleBindSubSession *subSession = (CompatibleBindSubSession *)session;
943     if (session->status == STATUS_PROCESSING) {
944         return ProcessBindTask(subSession, in, status);
945     } else {
946         session->status = STATUS_PROCESSING;
947         bool isNeedInform = true;
948         int32_t result = PrepareAndSendServerData(subSession, in, &isNeedInform, status);
949         if (result != HC_SUCCESS) {
950             InformPeerGroupErrorIfNeeded(isNeedInform, result, subSession);
951         }
952         return result;
953     }
954 }
955 
DestroyCompatibleBindSubSession(CompatibleBaseSubSession * session)956 void DestroyCompatibleBindSubSession(CompatibleBaseSubSession *session)
957 {
958     if (session == NULL) {
959         return;
960     }
961     CompatibleBindSubSession *realSession = (CompatibleBindSubSession *)session;
962     DestroyTask(realSession->base.curTaskId, realSession->moduleType);
963     HcFree(realSession->base.appId);
964     realSession->base.appId = NULL;
965     FreeJson(realSession->params);
966     realSession->params = NULL;
967     HcFree(realSession);
968 }