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