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