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_mgr.h"
17
18 #include <inttypes.h>
19 #include "callback_manager.h"
20 #include "device_auth_defines.h"
21 #include "hc_dev_info.h"
22 #include "hc_log.h"
23 #include "hc_mutex.h"
24 #include "hc_time.h"
25 #include "hc_vector.h"
26 #include "task_manager.h"
27 #include "critical_handler.h"
28 #include "string_util.h"
29
30 typedef struct {
31 DevSession *session;
32 int64_t createTime;
33 } SessionInfo;
34
35 typedef struct {
36 HcTaskBase base;
37 int64_t sessionId;
38 } StartSessionTask;
39
40 typedef struct {
41 HcTaskBase base;
42 int64_t sessionId;
43 CJson *receivedMsg;
44 } ProcSessionTask;
45
46 DECLARE_HC_VECTOR(SessionInfoList, SessionInfo)
47 IMPLEMENT_HC_VECTOR(SessionInfoList, SessionInfo, 1)
48
49 static SessionInfoList g_sessionInfoList;
50 static HcMutex g_sessionMutex;
51
GetSessionInfo(int64_t sessionId,SessionInfo ** returnObj)52 static int32_t GetSessionInfo(int64_t sessionId, SessionInfo **returnObj)
53 {
54 uint32_t index;
55 SessionInfo *ptr;
56 FOR_EACH_HC_VECTOR(g_sessionInfoList, index, ptr) {
57 DevSession *session = ptr->session;
58 if (session->id == sessionId) {
59 *returnObj = ptr;
60 return HC_SUCCESS;
61 }
62 }
63 return HC_ERR_SESSION_NOT_EXIST;
64 }
65
RemoveTimeoutSession(void)66 void RemoveTimeoutSession(void)
67 {
68 uint32_t index = 0;
69 while (index < g_sessionInfoList.size(&(g_sessionInfoList))) {
70 SessionInfo *sessionInfo = g_sessionInfoList.getp(&(g_sessionInfoList), index);
71 int64_t runningTime = HcGetIntervalTime(sessionInfo->createTime);
72 if (runningTime < TIME_OUT_VALUE) {
73 index++;
74 continue;
75 }
76 DevSession *session = sessionInfo->session;
77 LOGI("session timeout. [AppId]: %" LOG_PUB "s, [Id]: %" LOG_PUB PRId64, session->appId, session->id);
78 LOGI("session timeout. [TimeLimit(/s)]: %" LOG_PUB "d, [RunningTime(/s)]: %" LOG_PUB PRId64,
79 TIME_OUT_VALUE, runningTime);
80 ProcessErrorCallback(session->id, session->opCode, HC_ERR_TIME_OUT, NULL, &session->callback);
81 session->destroy(session);
82 g_sessionInfoList.eraseElement(&(g_sessionInfoList), sessionInfo, index);
83 }
84 }
85
CheckEnvForOpenSession(int64_t sessionId)86 static int32_t CheckEnvForOpenSession(int64_t sessionId)
87 {
88 SessionInfo *sessionInfo;
89 int32_t res = GetSessionInfo(sessionId, &sessionInfo);
90 if (res == HC_SUCCESS) {
91 LOGE("session has existed. [Id]: %" LOG_PUB PRId64, sessionId);
92 return HC_ERR_REQUEST_EXIST;
93 }
94 uint32_t curSessionNum = HC_VECTOR_SIZE(&g_sessionInfoList);
95 if (curSessionNum >= MAX_AUTH_SESSION_COUNT) {
96 LOGE("The number of sessions has reached the maximum limit. [CurNum]: %" LOG_PUB "u, [NumLimit]: %" LOG_PUB "d",
97 curSessionNum, MAX_AUTH_SESSION_COUNT);
98 return HC_ERR_SESSION_IS_FULL;
99 }
100 return HC_SUCCESS;
101 }
102
AddNewSessionToList(DevSession * session)103 static int32_t AddNewSessionToList(DevSession *session)
104 {
105 SessionInfo newSessionInfo;
106 newSessionInfo.session = session;
107 newSessionInfo.createTime = HcGetCurTime();
108 if (g_sessionInfoList.pushBackT(&g_sessionInfoList, newSessionInfo) == NULL) {
109 LOGE("push session to list fail.");
110 return HC_ERR_MEMORY_COPY;
111 }
112 return HC_SUCCESS;
113 }
114
InitDevSessionManager(void)115 int32_t InitDevSessionManager(void)
116 {
117 int32_t res = InitHcMutex(&g_sessionMutex, false);
118 if (res != HC_SUCCESS) {
119 LOGE("Init session mutex failed.");
120 return res;
121 }
122 g_sessionInfoList = CREATE_HC_VECTOR(SessionInfoList);
123 return HC_SUCCESS;
124 }
125
DestroyDevSessionManager(void)126 void DestroyDevSessionManager(void)
127 {
128 uint32_t index;
129 SessionInfo *ptr;
130 (void)LockHcMutex(&g_sessionMutex);
131 FOR_EACH_HC_VECTOR(g_sessionInfoList, index, ptr) {
132 ptr->session->destroy(ptr->session);
133 }
134 DESTROY_HC_VECTOR(SessionInfoList, &g_sessionInfoList);
135 UnlockHcMutex(&g_sessionMutex);
136 DestroyHcMutex(&g_sessionMutex);
137 }
138
IsSessionExist(int64_t sessionId)139 bool IsSessionExist(int64_t sessionId)
140 {
141 (void)LockHcMutex(&g_sessionMutex);
142 SessionInfo *sessionInfo;
143 int32_t res = GetSessionInfo(sessionId, &sessionInfo);
144 UnlockHcMutex(&g_sessionMutex);
145 return res == HC_SUCCESS;
146 }
147
OpenDevSession(int64_t sessionId,const char * appId,SessionInitParams * params)148 int32_t OpenDevSession(int64_t sessionId, const char *appId, SessionInitParams *params)
149 {
150 if ((appId == NULL) || (params == NULL)) {
151 LOGE("invalid params.");
152 return HC_ERR_INVALID_PARAMS;
153 }
154 (void)LockHcMutex(&g_sessionMutex);
155 RemoveTimeoutSession();
156 int32_t res = CheckEnvForOpenSession(sessionId);
157 if (res != HC_SUCCESS) {
158 UnlockHcMutex(&g_sessionMutex);
159 return res;
160 }
161 DevSession *session;
162 res = CreateDevSession(sessionId, appId, params, &session);
163 if (res != HC_SUCCESS) {
164 LOGE("create session fail. [AppId]: %" LOG_PUB "s, [Id]: %" LOG_PUB PRId64, appId, sessionId);
165 UnlockHcMutex(&g_sessionMutex);
166 return res;
167 }
168 res = AddNewSessionToList(session);
169 if (res != HC_SUCCESS) {
170 session->destroy(session);
171 UnlockHcMutex(&g_sessionMutex);
172 return res;
173 }
174 LOGI("create session success. [AppId]: %" LOG_PUB "s, [CurNum]: %" LOG_PUB "u, [Id]: %" LOG_PUB PRId64,
175 appId, HC_VECTOR_SIZE(&g_sessionInfoList), sessionId);
176 UnlockHcMutex(&g_sessionMutex);
177 return HC_SUCCESS;
178 }
179
StartDevSession(int64_t sessionId)180 int32_t StartDevSession(int64_t sessionId)
181 {
182 (void)LockHcMutex(&g_sessionMutex);
183 RemoveTimeoutSession();
184 SessionInfo *sessionInfo;
185 int32_t res = GetSessionInfo(sessionId, &sessionInfo);
186 if (res != HC_SUCCESS) {
187 LOGE("session not found. [Id]: %" LOG_PUB PRId64, sessionId);
188 UnlockHcMutex(&g_sessionMutex);
189 return res;
190 }
191 DevSession *session = sessionInfo->session;
192 res = session->start(session);
193 UnlockHcMutex(&g_sessionMutex);
194 return res;
195 }
196
ProcessDevSession(int64_t sessionId,const CJson * receviedMsg,bool * isFinish)197 int32_t ProcessDevSession(int64_t sessionId, const CJson *receviedMsg, bool *isFinish)
198 {
199 if ((receviedMsg == NULL) || (isFinish == NULL)) {
200 LOGE("invalid params.");
201 return HC_ERR_INVALID_PARAMS;
202 }
203 (void)LockHcMutex(&g_sessionMutex);
204 RemoveTimeoutSession();
205 SessionInfo *sessionInfo;
206 int32_t res = GetSessionInfo(sessionId, &sessionInfo);
207 if (res != HC_SUCCESS) {
208 LOGE("session not found. [Id]: %" LOG_PUB PRId64, sessionId);
209 UnlockHcMutex(&g_sessionMutex);
210 return res;
211 }
212 DevSession *session = sessionInfo->session;
213 res = session->process(session, receviedMsg, isFinish);
214 UnlockHcMutex(&g_sessionMutex);
215 return res;
216 }
217
CloseDevSession(int64_t sessionId)218 void CloseDevSession(int64_t sessionId)
219 {
220 (void)LockHcMutex(&g_sessionMutex);
221 RemoveTimeoutSession();
222 uint32_t index;
223 SessionInfo *ptr;
224 FOR_EACH_HC_VECTOR(g_sessionInfoList, index, ptr) {
225 DevSession *session = ptr->session;
226 if (session->id == sessionId) {
227 session->destroy(session);
228 HC_VECTOR_POPELEMENT(&g_sessionInfoList, ptr, index);
229 LOGI("close session success. [CurNum]: %" LOG_PUB "u, [Id]: %" LOG_PUB PRId64,
230 HC_VECTOR_SIZE(&g_sessionInfoList), sessionId);
231 UnlockHcMutex(&g_sessionMutex);
232 return;
233 }
234 }
235 LOGI("session not exist. [Id]: %" LOG_PUB PRId64, sessionId);
236 UnlockHcMutex(&g_sessionMutex);
237 }
238
CancelDevSession(int64_t sessionId,const char * appId)239 void CancelDevSession(int64_t sessionId, const char *appId)
240 {
241 if (appId == NULL) {
242 LOGE("appId is NULL.");
243 return;
244 }
245 (void)LockHcMutex(&g_sessionMutex);
246 RemoveTimeoutSession();
247 uint32_t index;
248 SessionInfo *ptr;
249 FOR_EACH_HC_VECTOR(g_sessionInfoList, index, ptr) {
250 DevSession *session = ptr->session;
251 if (session->id == sessionId && IsStrEqual(session->appId, appId)) {
252 session->destroy(session);
253 HC_VECTOR_POPELEMENT(&g_sessionInfoList, ptr, index);
254 LOGI("cancel session success. [CurNum]: %" LOG_PUB "u, [Id]: %" LOG_PUB PRId64,
255 HC_VECTOR_SIZE(&g_sessionInfoList), sessionId);
256 UnlockHcMutex(&g_sessionMutex);
257 return;
258 }
259 }
260 LOGI("session not exist. [Id]: %" LOG_PUB PRId64, sessionId);
261 UnlockHcMutex(&g_sessionMutex);
262 }
263
DoStartSession(HcTaskBase * task)264 static void DoStartSession(HcTaskBase *task)
265 {
266 LOGI("start session task begin.");
267 if (task == NULL) {
268 LOGE("The input task is NULL, can't start session!");
269 DecreaseCriticalCnt();
270 return;
271 }
272 StartSessionTask *realTask = (StartSessionTask *)task;
273 SET_LOG_MODE(TRACE_MODE);
274 SET_TRACE_ID(realTask->sessionId);
275 int32_t res = StartDevSession(realTask->sessionId);
276 if (res != HC_SUCCESS) {
277 LOGE("start session fail.[Res]: %" LOG_PUB "d", res);
278 CloseDevSession(realTask->sessionId);
279 }
280 DecreaseCriticalCnt();
281 }
282
DoProcSession(HcTaskBase * task)283 static void DoProcSession(HcTaskBase *task)
284 {
285 LOGI("proc session task begin.");
286 if (task == NULL) {
287 LOGE("The input task is NULL, can't start session!");
288 DecreaseCriticalCnt();
289 return;
290 }
291 ProcSessionTask *realTask = (ProcSessionTask *)task;
292 SET_LOG_MODE(TRACE_MODE);
293 SET_TRACE_ID(realTask->sessionId);
294 bool isFinish = false;
295 int32_t res = ProcessDevSession(realTask->sessionId, realTask->receivedMsg, &isFinish);
296 if (res != HC_SUCCESS) {
297 LOGE("ProcessDevSession fail. [Res]: %" LOG_PUB "d", res);
298 CloseDevSession(realTask->sessionId);
299 DecreaseCriticalCnt();
300 return;
301 }
302 LOGI("ProcessDevSession success. [State]: %" LOG_PUB "s", isFinish ? "FINISH" : "CONTINUE");
303 if (isFinish) {
304 CloseDevSession(realTask->sessionId);
305 }
306 DecreaseCriticalCnt();
307 }
308
InitStartSessionTask(StartSessionTask * task,int64_t sessionId)309 static void InitStartSessionTask(StartSessionTask *task, int64_t sessionId)
310 {
311 task->base.doAction = DoStartSession;
312 task->base.destroy = NULL;
313 task->sessionId = sessionId;
314 }
315
DestroyProcSessionTask(HcTaskBase * task)316 static void DestroyProcSessionTask(HcTaskBase *task)
317 {
318 ProcSessionTask *realTask = (ProcSessionTask *)task;
319 FreeJson(realTask->receivedMsg);
320 DecreaseCriticalCnt();
321 }
322
InitProcSessionTask(ProcSessionTask * task,int64_t sessionId,CJson * receivedMsg)323 static void InitProcSessionTask(ProcSessionTask *task, int64_t sessionId, CJson *receivedMsg)
324 {
325 task->base.doAction = DoProcSession;
326 task->base.destroy = DestroyProcSessionTask;
327 task->sessionId = sessionId;
328 task->receivedMsg = receivedMsg;
329 }
330
PushStartSessionTask(int64_t sessionId)331 int32_t PushStartSessionTask(int64_t sessionId)
332 {
333 StartSessionTask *task = (StartSessionTask *)HcMalloc(sizeof(StartSessionTask), 0);
334 if (task == NULL) {
335 LOGE("Failed to allocate memory for task!");
336 return HC_ERR_ALLOC_MEMORY;
337 }
338 InitStartSessionTask(task, sessionId);
339 if (PushTask((HcTaskBase*)task) != HC_SUCCESS) {
340 LOGE("push start session task fail.");
341 HcFree(task);
342 return HC_ERR_INIT_TASK_FAIL;
343 }
344 IncreaseCriticalCnt(ADD_ONE);
345 LOGI("push start session task success.");
346 return HC_SUCCESS;
347 }
348
PushProcSessionTask(int64_t sessionId,CJson * receivedMsg)349 int32_t PushProcSessionTask(int64_t sessionId, CJson *receivedMsg)
350 {
351 ProcSessionTask *task = (ProcSessionTask *)HcMalloc(sizeof(ProcSessionTask), 0);
352 if (task == NULL) {
353 LOGE("Failed to allocate memory for task!");
354 return HC_ERR_ALLOC_MEMORY;
355 }
356 InitProcSessionTask(task, sessionId, receivedMsg);
357 if (PushTask((HcTaskBase*)task) != HC_SUCCESS) {
358 LOGE("push start session task fail.");
359 HcFree(task);
360 return HC_ERR_INIT_TASK_FAIL;
361 }
362 IncreaseCriticalCnt(ADD_TWO);
363 LOGI("push start session task success.");
364 return HC_SUCCESS;
365 }