• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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