1 /*
2 * Copyright (C) 2021-2022 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 "session_manager.h"
17 #include "auth_session_client.h"
18 #include "auth_session_server.h"
19 #include "bind_session_client.h"
20 #include "bind_session_server.h"
21 #include "common_defs.h"
22 #include "device_auth.h"
23 #include "device_auth_defines.h"
24 #include "hc_dev_info.h"
25 #include "hc_log.h"
26 #include "hc_time.h"
27 #include "hc_vector.h"
28
29 typedef struct {
30 int64_t requestId;
31 int32_t type;
32 int64_t sessionId;
33 } RequestInfo;
34
35 DECLARE_HC_VECTOR(SessionManagerVec, void *);
36 IMPLEMENT_HC_VECTOR(SessionManagerVec, void *, 1)
37
38 DECLARE_HC_VECTOR(RequestInfoVec, RequestInfo);
39 IMPLEMENT_HC_VECTOR(RequestInfoVec, RequestInfo, 1)
40
41 static SessionManagerVec g_sessionManagerVec;
42 static RequestInfoVec g_requestVec;
43
44 typedef Session *(*CreateSessionFunc)(CJson *, const DeviceAuthCallback *);
45
46 typedef struct SessionManagerInfoStruct {
47 SessionTypeValue sessionType;
48 int requestType; /* only BIND_TYPE or AUTH_TYPE currently */
49 CreateSessionFunc createSessionFunc;
50 } SessionManagerInfo;
51
52 static const SessionManagerInfo SESSION_MANAGER_INFO[] = {
53 { TYPE_CLIENT_BIND_SESSION, BIND_TYPE, CreateClientBindSession },
54 { TYPE_SERVER_BIND_SESSION, BIND_TYPE, CreateServerBindSession },
55 { TYPE_CLIENT_AUTH_SESSION, AUTH_TYPE, CreateClientAuthSession },
56 { TYPE_SERVER_AUTH_SESSION, AUTH_TYPE, CreateServerAuthSession },
57 };
58
GetSessionId(int64_t requestId,int64_t * sessionId)59 static int32_t GetSessionId(int64_t requestId, int64_t *sessionId)
60 {
61 uint32_t index;
62 RequestInfo *requestInfo = NULL;
63 FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) {
64 if ((requestInfo != NULL) && (requestInfo->requestId == requestId)) {
65 *sessionId = requestInfo->sessionId;
66 return HC_SUCCESS;
67 }
68 }
69 return HC_ERR_REQUEST_NOT_FOUND;
70 }
71
GetSessionIdByType(int64_t requestId,int32_t type,int64_t * sessionId)72 static int32_t GetSessionIdByType(int64_t requestId, int32_t type, int64_t *sessionId)
73 {
74 uint32_t index;
75 RequestInfo *requestInfo = NULL;
76 FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) {
77 if ((requestInfo != NULL) && (requestInfo->requestId == requestId)) {
78 if (requestInfo->type != type) {
79 LOGE("RequestId is match but type not match");
80 return HC_ERR_REQUEST_NOT_FOUND;
81 }
82 *sessionId = requestInfo->sessionId;
83 return HC_SUCCESS;
84 }
85 }
86 return HC_ERR_REQUEST_NOT_FOUND;
87 }
88
DestroyRequest(int64_t requestId)89 static void DestroyRequest(int64_t requestId)
90 {
91 uint32_t index;
92 RequestInfo *request = NULL;
93 FOR_EACH_HC_VECTOR(g_requestVec, index, request) {
94 if ((request != NULL) && (request->requestId == requestId)) {
95 RequestInfo tempRequest;
96 HC_VECTOR_POPELEMENT(&g_requestVec, &tempRequest, index);
97 return;
98 }
99 }
100 }
101
InitSessionManager(void)102 void InitSessionManager(void)
103 {
104 g_sessionManagerVec = CREATE_HC_VECTOR(SessionManagerVec);
105 g_requestVec = CREATE_HC_VECTOR(RequestInfoVec);
106 }
107
DestroySessionManager(void)108 void DestroySessionManager(void)
109 {
110 uint32_t index;
111 void **session = NULL;
112 FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) {
113 if (session != NULL && (*session != NULL)) {
114 Session *temp = (Session *)(*session);
115 temp->destroy(temp);
116 }
117 }
118 DESTROY_HC_VECTOR(SessionManagerVec, &g_sessionManagerVec);
119 DESTROY_HC_VECTOR(RequestInfoVec, &g_requestVec);
120 }
121
IsRequestExist(int64_t requestId)122 bool IsRequestExist(int64_t requestId)
123 {
124 int64_t sessionId = 0;
125 return (GetSessionId(requestId, &sessionId) == HC_SUCCESS) ? true : false;
126 }
127
InformTimeOutAndDestroyRequest(const DeviceAuthCallback * callback,int64_t sessionId)128 static void InformTimeOutAndDestroyRequest(const DeviceAuthCallback *callback, int64_t sessionId)
129 {
130 if (callback == NULL || callback->onError == NULL) {
131 LOGD("Callback is null, can't inform timeout");
132 return;
133 }
134 int64_t requestId = 0;
135 uint32_t index;
136 RequestInfo *requestInfo = NULL;
137 FOR_EACH_HC_VECTOR(g_requestVec, index, requestInfo) {
138 if ((requestInfo != NULL) && (requestInfo->sessionId == sessionId)) {
139 requestId = requestInfo->requestId;
140 RequestInfo tempRequest;
141 HC_VECTOR_POPELEMENT(&g_requestVec, &tempRequest, index);
142 break;
143 }
144 }
145 LOGI("Begin to inform time out, requestId :%" PRId64, requestId);
146 callback->onError(requestId, AUTH_FORM_INVALID_TYPE, HC_ERR_TIME_OUT, NULL);
147 }
148
RemoveOverTimeSession(void)149 static void RemoveOverTimeSession(void)
150 {
151 uint32_t index = 0;
152 void **session = NULL;
153 while (index < g_sessionManagerVec.size(&(g_sessionManagerVec))) {
154 session = g_sessionManagerVec.getp(&(g_sessionManagerVec), index);
155 if (session == NULL || (*session == NULL)) {
156 index++;
157 continue;
158 }
159 Session *ptr = (Session *)(*session);
160 if (HcGetIntervalTime(ptr->createTime) < TIME_OUT_VALUE) {
161 index++;
162 } else {
163 InformTimeOutAndDestroyRequest(ptr->callback, ptr->sessionId);
164 ptr->destroy(ptr);
165 g_sessionManagerVec.eraseElement(&(g_sessionManagerVec), session, index);
166 }
167 }
168 }
169
ProcessSession(int64_t requestId,int32_t type,CJson * in)170 int32_t ProcessSession(int64_t requestId, int32_t type, CJson *in)
171 {
172 RemoveOverTimeSession();
173 int64_t sessionId = 0;
174 int32_t result = GetSessionIdByType(requestId, type, &sessionId);
175 if (result != HC_SUCCESS) {
176 LOGE("The corresponding session is not found!");
177 return result;
178 }
179 uint32_t index;
180 void **session = NULL;
181 FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) {
182 if (session != NULL && (*session != NULL)) {
183 Session *ptr = (Session *)(*session);
184 if (ptr->sessionId == sessionId) {
185 return ptr->process(ptr, in);
186 }
187 }
188 }
189 return HC_ERR_SESSION_NOT_EXIST;
190 }
191
CheckForCreateSession(int64_t requestId,CJson * params,const DeviceAuthCallback * callback)192 static int32_t CheckForCreateSession(int64_t requestId, CJson *params, const DeviceAuthCallback *callback)
193 {
194 if ((params == NULL) && (callback == NULL)) {
195 LOGE("The input params or callback is NULL!");
196 return HC_ERR_INVALID_PARAMS;
197 }
198 if (IsRequestExist(requestId)) {
199 LOGE("A request with the request ID already exists!");
200 return HC_ERR_REQUEST_EXIST;
201 }
202 return HC_SUCCESS;
203 }
204
CreateSession(int64_t requestId,SessionTypeValue sessionType,CJson * params,const DeviceAuthCallback * callback)205 int32_t CreateSession(int64_t requestId, SessionTypeValue sessionType, CJson *params,
206 const DeviceAuthCallback *callback)
207 {
208 RemoveOverTimeSession();
209 int32_t res = CheckForCreateSession(requestId, params, callback);
210 if (res != HC_SUCCESS) {
211 return res;
212 }
213 uint32_t vecSize = g_sessionManagerVec.size(&g_sessionManagerVec);
214 LOGI("Current session num: %d", vecSize);
215 if (vecSize >= MAX_SESSION_COUNT) {
216 LOGE("Session vector is full.");
217 return HC_ERR_SESSION_IS_FULL;
218 }
219 RequestInfo requestInfo;
220 requestInfo.requestId = requestId;
221 Session *session = NULL;
222 for (uint32_t i = 0; i < sizeof(SESSION_MANAGER_INFO) / sizeof(SessionManagerInfo); i++) {
223 if (SESSION_MANAGER_INFO[i].sessionType == sessionType) {
224 session = SESSION_MANAGER_INFO[i].createSessionFunc(params, callback);
225 requestInfo.type = SESSION_MANAGER_INFO[i].requestType;
226 break;
227 }
228 }
229 if (session == NULL) {
230 LOGE("Failed to create session! Session Type: %d", sessionType);
231 return HC_ERR_CREATE_SESSION_FAIL;
232 }
233
234 requestInfo.sessionId = session->sessionId;
235 g_sessionManagerVec.pushBackT(&g_sessionManagerVec, (void *)session);
236 g_requestVec.pushBack(&g_requestVec, &requestInfo);
237 session->createTime = HcGetCurTime();
238 if (session->createTime <= 0) {
239 session->createTime = 0;
240 LOGE("Failed to get cur time.");
241 }
242 return HC_SUCCESS;
243 }
244
CheckCancelPermission(int64_t requestId,const char * appId,int cancelType,Session * session)245 static bool CheckCancelPermission(int64_t requestId, const char *appId, int cancelType, Session *session)
246 {
247 int sessionType = session->type;
248 if ((sessionType == TYPE_CLIENT_BIND_SESSION) || (sessionType == TYPE_SERVER_BIND_SESSION)) {
249 if (cancelType != TYPE_CANCEL_BIND) {
250 LOGE("invalid cancel type, requestId: %" PRId64 ", appId: %s, cancelType: %d, sessionType: %d",
251 requestId, appId, cancelType, sessionType);
252 return false;
253 }
254 if ((session->appId == NULL) || (strcmp(appId, session->appId) != 0)) {
255 LOGE("invalid caller, requestId: %" PRId64 ", appId: %s, session appId: %s",
256 requestId, appId, session->appId);
257 return false;
258 }
259 } else if ((sessionType == TYPE_CLIENT_AUTH_SESSION) || (sessionType == TYPE_SERVER_AUTH_SESSION)) {
260 if (cancelType != TYPE_CANCEL_AUTH) {
261 LOGE("invalid cancel type, requestId: %" PRId64 ", appId: %s, cancelType: %d, sessionType: %d",
262 requestId, appId, cancelType, sessionType);
263 return false;
264 }
265 if ((session->appId == NULL) || (strcmp(appId, session->appId) != 0)) {
266 LOGE("invalid caller, requestId: %" PRId64 ", appId: %s, session appId: %s",
267 requestId, appId, session->appId);
268 return false;
269 }
270 } else {
271 LOGE("invalid session type: %d", sessionType);
272 return false;
273 }
274 return true;
275 }
276
DestroySessionByType(int64_t requestId,const char * appId,int cancelType)277 void DestroySessionByType(int64_t requestId, const char *appId, int cancelType)
278 {
279 LOGI("requestId: %" PRId64 ", appId: %s, cancelType: %d", requestId, appId, cancelType);
280 int64_t sessionId = 0;
281 if (GetSessionId(requestId, &sessionId) != HC_SUCCESS) {
282 LOGE("session not found, requestId: %" PRId64, requestId);
283 return;
284 }
285 uint32_t index;
286 void **session = NULL;
287 FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) {
288 if ((session != NULL) && (*session != NULL) && (((Session *)(*session))->sessionId == sessionId)) {
289 if (!CheckCancelPermission(requestId, appId, cancelType, (Session *)(*session))) {
290 LOGE("destroy session failed, requestId: %" PRId64 ", appId: %s", requestId, appId);
291 return;
292 }
293 ((Session *)(*session))->destroy((Session *)(*session));
294 *session = NULL;
295 HC_VECTOR_POPELEMENT(&g_sessionManagerVec, session, index);
296 break;
297 }
298 }
299 LOGI("destroy session succeeded, requestId: %" PRId64 ", appId: %s", requestId, appId);
300 DestroyRequest(requestId);
301 }
302
DestroySession(int64_t requestId)303 void DestroySession(int64_t requestId)
304 {
305 int64_t sessionId = 0;
306 if (GetSessionId(requestId, &sessionId) != HC_SUCCESS) {
307 LOGI("The corresponding session is not found. Therefore, the destruction operation is not required!");
308 return;
309 }
310 uint32_t index;
311 void **session = NULL;
312 FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) {
313 if (session != NULL && (*session != NULL)) {
314 if (((Session *)(*session))->sessionId == sessionId) {
315 ((Session *)(*session))->destroy(((Session *)(*session)));
316 *session = NULL;
317 HC_VECTOR_POPELEMENT(&g_sessionManagerVec, session, index);
318 break;
319 }
320 }
321 }
322 DestroyRequest(requestId);
323 }
324
OnChannelOpened(int64_t requestId,int64_t channelId)325 void OnChannelOpened(int64_t requestId, int64_t channelId)
326 {
327 int64_t sessionId = 0;
328 if (GetSessionIdByType(requestId, BIND_TYPE, &sessionId) != HC_SUCCESS) {
329 LOGE("The corresponding session is not found!");
330 return;
331 }
332 uint32_t index;
333 void **session = NULL;
334 FOR_EACH_HC_VECTOR(g_sessionManagerVec, index, session) {
335 if (session == NULL || (*session == NULL) || (((Session *)(*session))->sessionId != sessionId)) {
336 continue;
337 }
338 int sessionType = ((Session *)(*session))->type;
339 if (sessionType == TYPE_CLIENT_BIND_SESSION) {
340 BindSession *realSession = (BindSession *)(*session);
341 realSession->onChannelOpened(*session, channelId, requestId);
342 return;
343 }
344 LOGE("The type of the found session is not as expected!");
345 return;
346 }
347 }
348