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