• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 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 "dev_session_fwk.h"
17 
18 #include <inttypes.h>
19 #include <time.h>
20 #include "alg_loader.h"
21 #include "callback_manager.h"
22 #include "channel_manager.h"
23 #include "identity_common.h"
24 #include "common_defs.h"
25 #include "compatible_sub_session.h"
26 #include "compatible_bind_sub_session_util.h"
27 #include "compatible_auth_sub_session_util.h"
28 #include "group_data_manager.h"
29 #include "dev_session_v2.h"
30 #include "hc_dev_info.h"
31 #include "hc_log.h"
32 #include "hc_time.h"
33 #include "hc_types.h"
34 #include "performance_dumper.h"
35 #include "hisysevent_common.h"
36 
StartV1Session(SessionImpl * impl,CJson ** sendMsg)37 static int32_t StartV1Session(SessionImpl *impl, CJson **sendMsg)
38 {
39     bool isBind = true;
40     bool isDeviceLevel = false;
41     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
42     (void)GetBoolFromJson(impl->context, FIELD_IS_DEVICE_LEVEL, &isDeviceLevel);
43     SubSessionTypeValue subSessionType = isBind ? TYPE_CLIENT_BIND_SUB_SESSION : TYPE_CLIENT_AUTH_SUB_SESSION;
44     int32_t res = CreateCompatibleSubSession(subSessionType, impl->context, &impl->base.callback,
45         &impl->compatibleSubSession);
46     if (res != HC_SUCCESS) {
47         if (isDeviceLevel && res == HC_ERR_NO_CANDIDATE_GROUP) {
48             LOGI("create compatibleSubSession fail. no candidate group");
49         } else {
50             LOGE("create compatibleSubSession fail. [Res]: %" LOG_PUB "d", res);
51         }
52         return res;
53     }
54     int32_t status;
55     res = ProcessCompatibleSubSession(impl->compatibleSubSession, impl->context, sendMsg, &status);
56     if (res != HC_SUCCESS) {
57         LOGE("process compatibleSubSession fail. [Res]: %" LOG_PUB "d", res);
58         DestroyCompatibleSubSession(impl->compatibleSubSession);
59         impl->compatibleSubSession = NULL;
60         return res;
61     }
62     return HC_SUCCESS;
63 }
64 
DestroySession(DevSession * self)65 static void DestroySession(DevSession *self)
66 {
67     if (self == NULL) {
68         LOGD("self is NULL.");
69         return;
70     }
71     SessionImpl *impl = (SessionImpl *)self;
72     HcFree(impl->base.appId);
73     FreeJson(impl->context);
74     ClearFreeUint8Buff(&impl->salt);
75     ClearFreeUint8Buff(&impl->sessionKey);
76     ClearIdentityInfoVec(&impl->credList);
77     DestroyEventList(&impl->eventList);
78     uint32_t index;
79     AuthSubSession **ptr;
80     FOR_EACH_HC_VECTOR(impl->authSubSessionList, index, ptr) {
81         AuthSubSession *authSubSesion = *ptr;
82         authSubSesion->destroy(authSubSesion);
83     }
84     DestroyAuthSubSessionList(&impl->authSubSessionList);
85     if (impl->expandSubSession != NULL) {
86         impl->expandSubSession->destroy(impl->expandSubSession);
87     }
88     if (impl->compatibleSubSession != NULL) {
89         DestroyCompatibleSubSession(impl->compatibleSubSession);
90         impl->compatibleSubSession = NULL;
91     }
92     HcFree(impl);
93 }
94 
DecodeEvent(const CJson * inputEvent)95 static int32_t DecodeEvent(const CJson *inputEvent)
96 {
97     if (inputEvent == NULL) {
98         return SESSION_UNKNOWN_EVENT;
99     }
100     int32_t eventType;
101     if (GetIntFromJson(inputEvent, FIELD_TYPE, &eventType) != HC_SUCCESS) {
102         LOGE("get eventType from inputEvent fail.");
103         return SESSION_UNKNOWN_EVENT;
104     }
105     if (START_EVENT <= eventType && eventType <= SESSION_UNKNOWN_EVENT) {
106         return eventType;
107     }
108     LOGE("unknown event.");
109     return SESSION_UNKNOWN_EVENT;
110 }
111 
PackSendMsg(SessionImpl * impl,CJson * sessionMsg,CJson * sendMsg)112 static int32_t PackSendMsg(SessionImpl *impl, CJson *sessionMsg, CJson *sendMsg)
113 {
114     if (AddInt64StringToJson(sendMsg, FIELD_REQUEST_ID, impl->base.id) != HC_SUCCESS) {
115         LOGE("add requestId to json fail!");
116         return HC_ERR_JSON_ADD;
117     }
118     if (AddStringToJson(sendMsg, FIELD_APP_ID, impl->base.appId) != HC_SUCCESS) {
119         LOGE("add appId to json fail.");
120         return HC_ERR_JSON_ADD;
121     }
122     if (AddObjToJson(sendMsg, FIELD_MSG, sessionMsg) != HC_SUCCESS) {
123         LOGE("add sessionMsg to json fail.");
124         return HC_ERR_JSON_ADD;
125     }
126     return HC_SUCCESS;
127 }
128 
SendJsonMsg(const SessionImpl * impl,const CJson * sendMsg)129 static int32_t SendJsonMsg(const SessionImpl *impl, const CJson *sendMsg)
130 {
131     char *sendMsgStr = PackJsonToString(sendMsg);
132     if (sendMsgStr == NULL) {
133         LOGE("convert sendMsg to sendMsgStr fail.");
134         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
135     }
136     UPDATE_PERFORM_DATA_BY_SELF_INDEX(impl->base.id, HcGetCurTimeInMillis());
137     int32_t res = HcSendMsg(impl->channelType, impl->base.id, impl->channelId, &impl->base.callback, sendMsgStr);
138     FreeJsonString(sendMsgStr);
139     return res;
140 }
141 
SendSessionMsg(SessionImpl * impl,CJson * sessionMsg)142 static int32_t SendSessionMsg(SessionImpl *impl, CJson *sessionMsg)
143 {
144     if (GetItemNum(sessionMsg) == 0) {
145         return HC_SUCCESS;
146     }
147     CJson *sendMsg = CreateJson();
148     if (sendMsg == NULL) {
149         LOGE("allocate sendMsg fail.");
150         return HC_ERR_ALLOC_MEMORY;
151     }
152     int32_t res = PackSendMsg(impl, sessionMsg, sendMsg);
153     if (res != HC_SUCCESS) {
154         LOGE("pack send msg fail.");
155         FreeJson(sendMsg);
156         return res;
157     }
158     res = SendJsonMsg(impl, sendMsg);
159     FreeJson(sendMsg);
160     return res;
161 }
162 
ProcEventList(SessionImpl * impl)163 static int32_t ProcEventList(SessionImpl *impl)
164 {
165     CJson *sessionMsg = CreateJsonArray();
166     if (sessionMsg == NULL) {
167         LOGE("allocate sessionMsg memory fail.");
168         return HC_ERR_ALLOC_MEMORY;
169     }
170     int32_t res = HC_SUCCESS;
171     uint32_t index;
172     SessionEvent *eventPtr = NULL;
173     SessionEvent event;
174     FOR_EACH_HC_VECTOR(impl->eventList, index, eventPtr) {
175         if ((eventPtr != NULL) && (SESSION_FAIL_EVENT == eventPtr->type)) {
176             res = SessionSwitchState(impl, eventPtr, sessionMsg);
177             HC_VECTOR_POPELEMENT(&impl->eventList, &event, index);
178             break;
179         }
180     }
181     while ((HC_SUCCESS == res) && (HC_VECTOR_SIZE(&impl->eventList) > 0)) {
182         HC_VECTOR_POPELEMENT(&impl->eventList, &event, 0);
183         res = SessionSwitchState(impl, &event, sessionMsg);
184     }
185     if (res != HC_SUCCESS) {
186         (void)SendSessionMsg(impl, sessionMsg);
187         FreeJson(sessionMsg);
188         return res;
189     }
190     res = SendSessionMsg(impl, sessionMsg);
191     FreeJson(sessionMsg);
192     return res;
193 }
194 
AddSessionInfo(SessionImpl * impl,CJson * sendMsg)195 static int32_t AddSessionInfo(SessionImpl *impl, CJson *sendMsg)
196 {
197     if (AddIntToJson(sendMsg, FIELD_OP_CODE, impl->base.opCode) != HC_SUCCESS) {
198         LOGE("add opCode to json fail.");
199         return HC_ERR_JSON_ADD;
200     }
201     return HC_SUCCESS;
202 }
203 
StartV2Session(SessionImpl * impl,CJson * sendMsg)204 static int32_t StartV2Session(SessionImpl *impl, CJson *sendMsg)
205 {
206     CJson *sessionMsg = CreateJsonArray();
207     if (sessionMsg == NULL) {
208         LOGE("allocate sessionMsg fail.");
209         return HC_ERR_ALLOC_MEMORY;
210     }
211     SessionEvent startEvent = { START_EVENT, NULL };
212     int32_t res = SessionSwitchState(impl, &startEvent, sessionMsg);
213     if (res != HC_SUCCESS) {
214         FreeJson(sessionMsg);
215         return res;
216     }
217     res = PackSendMsg(impl, sessionMsg, sendMsg);
218     FreeJson(sessionMsg);
219     if (res != HC_SUCCESS) {
220         LOGE("pack send msg fail.");
221         return res;
222     }
223     return AddSessionInfo(impl, sendMsg);
224 }
225 
IsMetaNode(const CJson * context)226 static bool IsMetaNode(const CJson *context)
227 {
228     return GetStringFromJson(context, FIELD_META_NODE_TYPE) != NULL;
229 }
230 
ReportBehaviorEvent(const SessionImpl * impl,bool isProcessEnd,bool isBehaviorEnd,int32_t res)231 static void ReportBehaviorEvent(const SessionImpl *impl, bool isProcessEnd, bool isBehaviorEnd, int32_t res)
232 {
233 #ifdef DEV_AUTH_HIVIEW_ENABLE
234     bool isBind = true;
235     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
236     char *funcName = isBind ? ADD_MEMBER_EVENT : AUTH_DEV_EVENT;
237     DevAuthBizScene scene = GetBizScene(isBind, impl->isClient);
238     DevAuthBehaviorEvent eventData = { 0 };
239     DevAuthBizState state = BIZ_STATE_PROCESS;
240     if (isBehaviorEnd) {
241         state = BIZ_STATE_END;
242     }
243     BuildBehaviorEventData(&eventData, funcName, scene, state, BIZ_STAGE_PROCESS);
244     char anonymousLocalUdid[ANONYMOUS_UDID_LEN + 1] = { 0 };
245     char anonymousPeerUdid[ANONYMOUS_UDID_LEN + 1] = { 0 };
246     if (isBind) {
247         eventData.hostPkg = ADD_MEMBER_HOST_PKG_NAME;
248         eventData.toCallPkg = ADD_MEMBER_TO_CALL_PKG_NAME;
249     } else {
250         eventData.hostPkg = AUTH_DEVICE_HOST_PKG_NAME;
251         char selfUdid[INPUT_UDID_LEN] = { 0 };
252         (void)HcGetUdid((uint8_t *)selfUdid, INPUT_UDID_LEN);
253         if (GetAnonymousString(selfUdid, anonymousLocalUdid, ANONYMOUS_UDID_LEN) == HC_SUCCESS) {
254             eventData.localUdid = anonymousLocalUdid;
255         }
256         const char *peerUdid = GetStringFromJson(impl->context, FIELD_PEER_CONN_DEVICE_ID);
257         if (GetAnonymousString(peerUdid, anonymousPeerUdid, ANONYMOUS_UDID_LEN) == HC_SUCCESS) {
258             eventData.peerUdid = anonymousPeerUdid;
259         }
260     }
261     char concurrentId[MAX_REQUEST_ID_LEN] = { 0 };
262     (void)sprintf_s(concurrentId, sizeof(concurrentId), "%" PRId64, impl->base.id);
263     eventData.concurrentId = concurrentId;
264     if (isProcessEnd || isBehaviorEnd) {
265         if (res == HC_SUCCESS) {
266             eventData.stageRes = STAGE_RES_SUCCESS;
267         } else {
268             BuildStageRes(&eventData, res);
269             eventData.errorCode = res;
270         }
271     }
272     DevAuthReportBehaviorEvent(&eventData);
273 #else
274     (void)impl;
275     (void)isProcessEnd;
276     (void)isBehaviorEnd;
277     (void)res;
278 #endif
279 }
280 
ReportBindAndAuthCallEvent(const SessionImpl * impl,int32_t callResult,bool isV1Session)281 static void ReportBindAndAuthCallEvent(const SessionImpl *impl, int32_t callResult, bool isV1Session)
282 {
283 #ifdef DEV_AUTH_HIVIEW_ENABLE
284     DevAuthCallEvent eventData;
285     eventData.appId = impl->base.appId;
286     (void)GetIntFromJson(impl->context, FIELD_OS_ACCOUNT_ID, &eventData.osAccountId);
287     eventData.callResult = callResult;
288     eventData.credType = DEFAULT_CRED_TYPE;
289     bool isBind = true;
290     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
291     if (isBind) {
292         eventData.funcName = ADD_MEMBER_EVENT;
293         eventData.processCode = isV1Session ? PROCESS_BIND_V1 : PROCESS_BIND_V2;
294         eventData.groupType = PEER_TO_PEER_GROUP;
295     } else {
296         eventData.funcName = AUTH_DEV_EVENT;
297         eventData.processCode = isV1Session ? PROCESS_AUTH_V1 : PROCESS_AUTH_V2;
298         eventData.groupType =
299             (impl->base.opCode == AUTH_FORM_ACCOUNT_UNRELATED) ? PEER_TO_PEER_GROUP : IDENTICAL_ACCOUNT_GROUP;
300     }
301     eventData.executionTime = GET_TOTAL_CONSUME_TIME_BY_REQ_ID(impl->base.id);
302     eventData.extInfo = DEFAULT_EXT_INFO;
303     DEV_AUTH_REPORT_CALL_EVENT(eventData);
304     return;
305 #endif
306     (void)impl;
307     (void)callResult;
308     (void)isV1Session;
309     return;
310 }
311 
ReportBindAndAuthFaultEvent(const SessionImpl * impl,int32_t errorCode,bool isV1Session)312 static void ReportBindAndAuthFaultEvent(const SessionImpl *impl, int32_t errorCode, bool isV1Session)
313 {
314 #ifdef DEV_AUTH_HIVIEW_ENABLE
315     DevAuthFaultEvent eventData;
316     eventData.appId = impl->base.appId;
317     eventData.reqId = impl->base.id;
318     eventData.errorCode = errorCode;
319     eventData.faultInfo = DEFAULT_FAULT_INFO;
320     bool isBind = true;
321     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
322     if (isBind) {
323         eventData.funcName = ADD_MEMBER_EVENT;
324         eventData.processCode = isV1Session ? PROCESS_BIND_V1 : PROCESS_BIND_V2;
325     } else {
326         eventData.funcName = AUTH_DEV_EVENT;
327         eventData.processCode = isV1Session ? PROCESS_AUTH_V1 : PROCESS_AUTH_V2;
328     }
329     DEV_AUTH_REPORT_FAULT_EVENT(eventData);
330     return;
331 #endif
332     (void)impl;
333     (void)errorCode;
334     (void)isV1Session;
335     return;
336 }
337 
OnDevSessionError(const SessionImpl * impl,int32_t errorCode,const char * errorReturn,bool isV1Session)338 static void OnDevSessionError(const SessionImpl *impl, int32_t errorCode, const char *errorReturn, bool isV1Session)
339 {
340     ReportBehaviorEvent(impl, false, true, errorCode);
341     ProcessErrorCallback(impl->base.id, impl->base.opCode, errorCode, errorReturn, &impl->base.callback);
342     CloseChannel(impl->channelType, impl->channelId);
343     ReportBindAndAuthFaultEvent(impl, errorCode, isV1Session);
344     ReportBindAndAuthCallEvent(impl, errorCode, isV1Session);
345 }
346 
StartSession(DevSession * self)347 static int32_t StartSession(DevSession *self)
348 {
349     if (self == NULL) {
350         LOGE("self is NULL.");
351         return HC_ERR_INVALID_PARAMS;
352     }
353     SessionImpl *impl = (SessionImpl *)self;
354     ReportBehaviorEvent(impl, false, false, HC_SUCCESS);
355     int32_t res;
356     do {
357         CJson *sendMsg = NULL;
358         /* auth with credentials directly no need to start the v1 session. */
359         bool isDirectAuth = false;
360         bool isDeviceLevel = false;
361         (void)GetBoolFromJson(impl->context, FIELD_IS_DIRECT_AUTH, &isDirectAuth);
362         if (!isDirectAuth && !impl->isCredAuth) {
363             (void)GetBoolFromJson(impl->context, FIELD_IS_DEVICE_LEVEL, &isDeviceLevel);
364             res = StartV1Session(impl, &sendMsg);
365             if ((res != HC_SUCCESS)
366                 && (res != HC_ERR_NO_CANDIDATE_GROUP || !isDeviceLevel)) {
367                 // if it's device level auth and no group founded,
368                 // we also need try auth with credentails directly.
369                 LOGE("start v1 session event fail.");
370                 break;
371             }
372         }
373         sendMsg = (sendMsg == NULL ? CreateJson() : sendMsg);
374         if (sendMsg == NULL) {
375             LOGE("allocate sendMsg fail.");
376             return HC_ERR_ALLOC_MEMORY;
377         }
378         if (IsSupportSessionV2() && !IsMetaNode(impl->context)) {
379             res = StartV2Session(impl, sendMsg);
380             if (res != HC_SUCCESS) {
381                 LOGE("start v2 session event fail.");
382                 FreeJson(sendMsg);
383                 break;
384             }
385         }
386         res = SendJsonMsg(impl, sendMsg);
387         FreeJson(sendMsg);
388         if (res != HC_SUCCESS) {
389             LOGE("send msg fail.");
390             break;
391         }
392     } while (0);
393     ReportBehaviorEvent(impl, true, false, res);
394     if (res != HC_SUCCESS) {
395         OnDevSessionError(impl, res, NULL, false);
396     }
397     return res;
398 }
399 
ParseAllRecvEvent(SessionImpl * impl,const CJson * receviedMsg)400 static int32_t ParseAllRecvEvent(SessionImpl *impl, const CJson *receviedMsg)
401 {
402     CJson *sessionMsg = GetObjFromJson(receviedMsg, FIELD_MSG);
403     if (sessionMsg == NULL) {
404         LOGE("get sessionMsg from receviedMsg fail.");
405         return HC_ERR_JSON_GET;
406     }
407     int32_t eventNum = GetItemNum(sessionMsg);
408     if (eventNum <= 0) {
409         LOGE("There are no events in the received session message.");
410         return HC_ERR_BAD_MESSAGE;
411     }
412     for (int32_t i = 0; i < eventNum; i++) {
413         CJson *inputEventJson = GetItemFromArray(sessionMsg, i);
414         if (inputEventJson == NULL) {
415             LOGE("get inputEventJson from sessionMsg fail.");
416             return HC_ERR_JSON_GET;
417         }
418         int32_t eventType = DecodeEvent(inputEventJson);
419         CJson *eventData = GetObjFromJson(inputEventJson, FIELD_DATA);
420         if (eventData == NULL) {
421             LOGE("get eventData fail.");
422             return HC_ERR_JSON_GET;
423         }
424         SessionEvent event = { eventType, eventData };
425         if (HC_VECTOR_PUSHBACK(&impl->eventList, &event) == NULL) {
426             LOGE("push event fail.");
427             return HC_ERR_ALLOC_MEMORY;
428         }
429         LOGI("push event success. [Type]: %" LOG_PUB "d", eventType);
430     }
431     return HC_SUCCESS;
432 }
433 
IsV1SessionMsg(const CJson * receviedMsg)434 static bool IsV1SessionMsg(const CJson *receviedMsg)
435 {
436     return (GetObjFromJson(receviedMsg, FIELD_MSG) == NULL);
437 }
438 
AddChannelInfoToParams(SessionImpl * impl,CJson * receviedMsg)439 static int32_t AddChannelInfoToParams(SessionImpl *impl, CJson *receviedMsg)
440 {
441     int32_t channelType;
442     if (GetIntFromJson(impl->context, FIELD_CHANNEL_TYPE, &channelType) != HC_SUCCESS) {
443         LOGE("get channelType from context fail.");
444         return HC_ERR_JSON_GET;
445     }
446     int64_t channelId;
447     if (GetByteFromJson(impl->context, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) {
448         LOGE("get channelId from context fail.");
449         return HC_ERR_JSON_GET;
450     }
451     if (AddIntToJson(receviedMsg, FIELD_CHANNEL_TYPE, channelType) != HC_SUCCESS) {
452         LOGE("add channelType to params fail.");
453         return HC_ERR_JSON_ADD;
454     }
455     if (AddByteToJson(receviedMsg, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) {
456         LOGE("add channelId to params fail.");
457         return HC_ERR_JSON_ADD;
458     }
459     return HC_SUCCESS;
460 }
461 
CombindServerBindParams(SessionImpl * impl,CJson * receviedMsg)462 static int32_t CombindServerBindParams(SessionImpl *impl, CJson *receviedMsg)
463 {
464     int32_t osAccountId;
465     if (GetIntFromJson(impl->context, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
466         LOGE("get osAccountId from context fail.");
467         return HC_ERR_JSON_GET;
468     }
469     if (AddIntToJson(receviedMsg, FIELD_OS_ACCOUNT_ID, osAccountId) != HC_SUCCESS) {
470         LOGE("add osAccountId to receviedMsg fail.");
471         return HC_ERR_JSON_ADD;
472     }
473     int32_t protocolExpandVal = INVALID_PROTOCOL_EXPAND_VALUE;
474     (void)GetIntFromJson(impl->context, FIELD_PROTOCOL_EXPAND, &protocolExpandVal);
475     if (AddIntToJson(receviedMsg, FIELD_PROTOCOL_EXPAND, protocolExpandVal) != HC_SUCCESS) {
476         LOGE("Failed to add protocol expand val to receviedMsg!");
477         return HC_ERR_JSON_ADD;
478     }
479     return CombineConfirmData(impl->opCode, impl->context, receviedMsg);
480 }
481 
CombindServerAuthParams(SessionImpl * impl,CJson * receviedMsg)482 static int32_t CombindServerAuthParams(SessionImpl *impl, CJson *receviedMsg)
483 {
484     if (AddInt64StringToJson(receviedMsg, FIELD_REQUEST_ID, impl->base.id) != HC_SUCCESS) {
485         LOGE("add requestId to receviedMsg fail.");
486         return HC_ERR_JSON_ADD;
487     }
488     if (AddIntToJson(receviedMsg, FIELD_OPERATION_CODE, AUTHENTICATE) != HC_SUCCESS) {
489         LOGE("add operationCode to receviedMsg fail.");
490         return HC_ERR_JSON_ADD;
491     }
492     return CombineAuthConfirmData(impl->context, receviedMsg);
493 }
494 
AddConfirmationToParams(const CJson * context,CJson * receviedMsg)495 static int32_t AddConfirmationToParams(const CJson *context, CJson *receviedMsg)
496 {
497     uint32_t confirmation = REQUEST_REJECTED;
498     (void)GetUnsignedIntFromJson(context, FIELD_CONFIRMATION, &confirmation);
499     if (AddIntToJson(receviedMsg, FIELD_CONFIRMATION, (int32_t)confirmation) != HC_SUCCESS) {
500         LOGE("add confirmation to receviedMsg fail.");
501         return HC_ERR_JSON_ADD;
502     }
503     return HC_SUCCESS;
504 }
505 
CombineServerParams(SessionImpl * impl,bool isBind,CJson * receviedMsg)506 static int32_t CombineServerParams(SessionImpl *impl, bool isBind, CJson *receviedMsg)
507 {
508     int32_t res = AddChannelInfoToParams(impl, receviedMsg);
509     if (res != HC_SUCCESS) {
510         return res;
511     }
512     res = AddConfirmationToParams(impl->context, receviedMsg);
513     if (res != HC_SUCCESS) {
514         return res;
515     }
516     return isBind ? CombindServerBindParams(impl, receviedMsg) : CombindServerAuthParams(impl, receviedMsg);
517 }
518 
InitServerV1Session(SessionImpl * impl,const CJson * receviedMsg)519 static int32_t InitServerV1Session(SessionImpl *impl, const CJson *receviedMsg)
520 {
521     bool isBind = true;
522     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
523     int32_t res = CombineServerParams(impl, isBind, (CJson *)receviedMsg);
524     if (res != HC_SUCCESS) {
525         return res;
526     }
527     SubSessionTypeValue subSessionType = isBind ? TYPE_SERVER_BIND_SUB_SESSION : TYPE_SERVER_AUTH_SUB_SESSION;
528     res = CreateCompatibleSubSession(subSessionType, (CJson *)receviedMsg, &impl->base.callback,
529         &impl->compatibleSubSession);
530     if (res != HC_SUCCESS) {
531         LOGE("create compatibleSubSession fail. [Res]: %" LOG_PUB "d", res);
532         return res;
533     }
534     return HC_SUCCESS;
535 }
536 
ProcV1SessionMsg(SessionImpl * impl,const CJson * receviedMsg,bool * isFinish)537 static int32_t ProcV1SessionMsg(SessionImpl *impl, const CJson *receviedMsg, bool *isFinish)
538 {
539     CJson *out = NULL;
540     int32_t status;
541     int32_t res = ProcessCompatibleSubSession(impl->compatibleSubSession, (CJson *)receviedMsg, &out, &status);
542     if (res != HC_SUCCESS) {
543         DestroyCompatibleSubSession(impl->compatibleSubSession);
544         impl->compatibleSubSession = NULL;
545         if (status == FINISH) {
546             LOGI("process compatibleSubSession finish.");
547             *isFinish = true;
548             return HC_SUCCESS;
549         } else {
550             LOGE("process compatibleSubSession fail. [Res]: %" LOG_PUB "d", res);
551             return res;
552         }
553     }
554     *isFinish = false;
555     return HC_SUCCESS;
556 }
557 
HasNextAuthGroup(const CJson * receviedMsg)558 static inline bool HasNextAuthGroup(const CJson *receviedMsg)
559 {
560     return GetStringFromJson(receviedMsg, FIELD_ALTERNATIVE) != NULL;
561 }
562 
GenerateErrorReturn(const CJson * receviedMsg,char ** errorReturn)563 static void GenerateErrorReturn(const CJson *receviedMsg, char **errorReturn)
564 {
565     const char *pkInfoStr = GetStringFromJson(receviedMsg, FIELD_AUTH_PK_INFO);
566     if (pkInfoStr == NULL) {
567         LOGI("receviedMsg without authPkInfo.");
568         return;
569     }
570     CJson *pkInfoJson = CreateJsonFromString(pkInfoStr);
571     if (pkInfoJson == NULL) {
572         LOGE("create json from string failed.");
573         return;
574     }
575 
576     const char *deviceId = GetStringFromJson(pkInfoJson, FIELD_DEVICE_ID);
577     if (deviceId == NULL) {
578         LOGI("receviedMsg without devcieId.");
579         FreeJson(pkInfoJson);
580         return;
581     }
582     CJson *message = CreateJson();
583     if (message == NULL) {
584         LOGE("create json failed.");
585         FreeJson(pkInfoJson);
586         return;
587     }
588     if (AddStringToJson(message, FIELD_AUTH_ID, deviceId) != HC_SUCCESS) {
589         LOGE("add string to json failed.");
590         FreeJson(message);
591         FreeJson(pkInfoJson);
592         return;
593     }
594 
595     *errorReturn = PackJsonToString(message);
596     if (*errorReturn == NULL) {
597         LOGE("Pack authId Json To String fail.");
598     }
599     FreeJson(message);
600     FreeJson(pkInfoJson);
601 }
602 
OnV1SessionError(SessionImpl * impl,int32_t errorCode,const CJson * receviedMsg)603 static void OnV1SessionError(SessionImpl *impl, int32_t errorCode, const CJson *receviedMsg)
604 {
605     bool isSingleCred = false;
606     (void)GetBoolFromJson(impl->context, FIELD_IS_SINGLE_CRED, &isSingleCred);
607     if (HasNextAuthGroup(receviedMsg) && !isSingleCred) {
608         return;
609     }
610     char *errorReturn = NULL;
611     GenerateErrorReturn(receviedMsg, &errorReturn);
612     OnDevSessionError(impl, errorCode, errorReturn, true);
613     FreeJsonString(errorReturn);
614 }
615 
ProcV1Session(SessionImpl * impl,const CJson * receviedMsg,bool * isFinish)616 static int32_t ProcV1Session(SessionImpl *impl, const CJson *receviedMsg, bool *isFinish)
617 {
618     ReportBehaviorEvent(impl, false, false, HC_SUCCESS);
619     int32_t res;
620     if (impl->compatibleSubSession == NULL) {
621         res = InitServerV1Session(impl, receviedMsg);
622         if (res != HC_SUCCESS) {
623             ReportBehaviorEvent(impl, true, false, res);
624             OnV1SessionError(impl, res, receviedMsg);
625             return res;
626         }
627     }
628     res = ProcV1SessionMsg(impl, receviedMsg, isFinish);
629     ReportBehaviorEvent(impl, true, false, res);
630     if (*isFinish) {
631         ReportBehaviorEvent(impl, false, true, HC_SUCCESS);
632     }
633     if (res != HC_SUCCESS) {
634         OnV1SessionError(impl, res, receviedMsg);
635     }
636     return res;
637 }
638 
GetSessionReturnData(const SessionImpl * impl)639 static char *GetSessionReturnData(const SessionImpl *impl)
640 {
641     CJson *returnData = CreateJson();
642     if (returnData == NULL) {
643         LOGW("allocate returnData memory fail.");
644         return NULL;
645     }
646     if (!impl->isCredAuth) {
647         const char *groupId = GetStringFromJson(impl->context, FIELD_GROUP_ID);
648         if (groupId == NULL) {
649             LOGW("get groupId from context fail.");
650             FreeJson(returnData);
651             return NULL;
652         }
653         if (AddStringToJson(returnData, FIELD_GROUP_ID, groupId) != HC_SUCCESS) {
654             LOGW("add groupId to returnData fail.");
655             FreeJson(returnData);
656             return NULL;
657         }
658     }
659     char *returnDataStr = PackJsonToString(returnData);
660     FreeJson(returnData);
661     if (returnDataStr == NULL) {
662         LOGW("pack returnData to returnDataStr fail.");
663     }
664     return returnDataStr;
665 }
666 
OnDevSessionFinish(const SessionImpl * impl)667 static void OnDevSessionFinish(const SessionImpl *impl)
668 {
669     ReportBehaviorEvent(impl, false, true, HC_SUCCESS);
670     UPDATE_PERFORM_DATA_BY_INPUT_INDEX(impl->base.id, ON_SESSION_KEY_RETURN_TIME, HcGetCurTimeInMillis());
671     ProcessSessionKeyCallback(impl->base.id, impl->sessionKey.val, impl->sessionKey.length, &impl->base.callback);
672 
673     char *returnData = GetSessionReturnData(impl);
674     UPDATE_PERFORM_DATA_BY_INPUT_INDEX(impl->base.id, ON_FINISH_TIME, HcGetCurTimeInMillis());
675     ProcessFinishCallback(impl->base.id, impl->base.opCode, returnData, &impl->base.callback);
676     FreeJsonString(returnData);
677 
678     bool isBind = true;
679     (void)GetBoolFromJson(impl->context, FIELD_IS_BIND, &isBind);
680     if (isBind) {
681         NotifyBindResult(impl->channelType, impl->channelId);
682     }
683     ReportBindAndAuthCallEvent(impl, HC_SUCCESS, false);
684     CloseChannel(impl->channelType, impl->channelId);
685 }
686 
ProcV2Session(SessionImpl * impl,const CJson * receviedMsg,bool * isFinish)687 static int32_t ProcV2Session(SessionImpl *impl, const CJson *receviedMsg, bool *isFinish)
688 {
689     ReportBehaviorEvent(impl, false, false, HC_SUCCESS);
690     if (impl->compatibleSubSession != NULL) {
691         DestroyCompatibleSubSession(impl->compatibleSubSession);
692         impl->compatibleSubSession = NULL;
693     }
694     int32_t res;
695     do {
696         res = ParseAllRecvEvent(impl, receviedMsg);
697         if (res != HC_SUCCESS) {
698             break;
699         }
700         res = ProcEventList(impl);
701     } while (0);
702     ReportBehaviorEvent(impl, true, false, res);
703     if (res != HC_SUCCESS) {
704         OnDevSessionError(impl, res, NULL, false);
705         return res;
706     }
707     if (impl->curState == SESSION_FINISH_STATE) {
708         *isFinish = true;
709         OnDevSessionFinish(impl);
710     } else {
711         *isFinish = false;
712     }
713     return HC_SUCCESS;
714 }
715 
ProcessSession(DevSession * self,const CJson * receviedMsg,bool * isFinish)716 static int32_t ProcessSession(DevSession *self, const CJson *receviedMsg, bool *isFinish)
717 {
718     if ((self == NULL) || (receviedMsg == NULL) || (isFinish == NULL)) {
719         LOGE("invalid params.");
720         return HC_ERR_INVALID_PARAMS;
721     }
722     SessionImpl *impl = (SessionImpl *)self;
723     if (!IsSupportSessionV2() || IsV1SessionMsg(receviedMsg)) {
724         return ProcV1Session(impl, receviedMsg, isFinish);
725     } else {
726         return ProcV2Session(impl, receviedMsg, isFinish);
727     }
728 }
729 
BuildDevSessionByContext(const CJson * context,SessionImpl * session)730 static int32_t BuildDevSessionByContext(const CJson *context, SessionImpl *session)
731 {
732     int32_t opCode;
733     if (GetIntFromJson(context, FIELD_OPERATION_CODE, &opCode) != HC_SUCCESS) {
734         LOGE("get opCode from context fail.");
735         return HC_ERR_JSON_GET;
736     }
737     int32_t channelType;
738     if (GetIntFromJson(context, FIELD_CHANNEL_TYPE, &channelType) != HC_SUCCESS) {
739         LOGE("get channelType from context fail.");
740         return HC_ERR_JSON_GET;
741     }
742     int64_t channelId;
743     if (GetByteFromJson(context, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) {
744         LOGE("get channelId from context fail.");
745         return HC_ERR_JSON_GET;
746     }
747     bool isClient;
748     if (GetBoolFromJson(context, FIELD_IS_CLIENT, &isClient) != HC_SUCCESS) {
749         LOGE("get isClient from context fail.");
750         return HC_ERR_JSON_GET;
751     }
752     bool isCredAuth = false;
753     (void)GetBoolFromJson(context, FIELD_IS_CRED_AUTH, &isCredAuth);
754     session->base.opCode = opCode;
755     session->channelType = channelType;
756     session->channelId = channelId;
757     session->isClient = isClient;
758     session->isCredAuth = isCredAuth;
759     return HC_SUCCESS;
760 }
761 
BuildDevSession(int64_t sessionId,const char * appId,SessionInitParams * params,SessionImpl * session)762 static int32_t BuildDevSession(int64_t sessionId, const char *appId, SessionInitParams *params, SessionImpl *session)
763 {
764     int32_t res = BuildDevSessionByContext(params->context, session);
765     if (res != HC_SUCCESS) {
766         return res;
767     }
768     res = DeepCopyString(appId, &session->base.appId);
769     if (res != HC_SUCCESS) {
770         LOGE("copy appId fail.");
771         return res;
772     }
773     CJson *copyContext = DuplicateJson(params->context);
774     if (copyContext == NULL) {
775         LOGE("copy context fail.");
776         HcFree(session->base.appId);
777         return HC_ERR_ALLOC_MEMORY;
778     }
779     session->base.id = sessionId;
780     session->base.start = StartSession;
781     session->base.process = ProcessSession;
782     session->base.destroy = DestroySession;
783     session->context = copyContext;
784     session->base.callback = params->callback;
785     session->curState = session->isClient ? INIT_CLIENT_STATE : INIT_SERVER_STATE;
786     session->restartState = session->curState;
787     session->credCurIndex = 0;
788     session->credTotalNum = 0;
789     session->credList = CreateIdentityInfoVec();
790     session->eventList = CreateEventList();
791     session->authSubSessionList = CreateAuthSubSessionList();
792     return HC_SUCCESS;
793 }
794 
CreateDevSession(int64_t sessionId,const char * appId,SessionInitParams * params,DevSession ** returnObj)795 int32_t CreateDevSession(int64_t sessionId, const char *appId, SessionInitParams *params, DevSession **returnObj)
796 {
797     if (appId == NULL || params == NULL || returnObj == NULL) {
798         LOGE("invalid params.");
799         return HC_ERR_INVALID_PARAMS;
800     }
801     SessionImpl *session = (SessionImpl *)HcMalloc(sizeof(SessionImpl), 0);
802     if (session == NULL) {
803         LOGE("allocate session memory fail.");
804         return HC_ERR_ALLOC_MEMORY;
805     }
806     int32_t res = BuildDevSession(sessionId, appId, params, session);
807     if (res != HC_SUCCESS) {
808         HcFree(session);
809         return res;
810     }
811     *returnObj = (DevSession *)session;
812     return HC_SUCCESS;
813 }
814