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