1 /*
2  * Copyright (C) 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 "pool.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_algorithm.h"
21 #include "adaptor_log.h"
22 #include "adaptor_memory.h"
23 
24 #define MAX_DUPLICATE_CHECK 100
25 #ifdef IAM_TEST_ENABLE
26 #define IAM_STATIC
27 #else
28 #define IAM_STATIC static
29 #endif
30 
31 // Resource pool list, which caches registered executor information.
32 IAM_STATIC LinkedList *g_poolList = NULL;
33 
DestroyExecutorInfo(void * data)34 IAM_STATIC void DestroyExecutorInfo(void *data)
35 {
36     if (data == NULL) {
37         LOG_ERROR("data is null");
38         return;
39     }
40     Free(data);
41 }
42 
IsExecutorIdMatchById(const void * data,const void * condition)43 IAM_STATIC bool IsExecutorIdMatchById(const void *data, const void *condition)
44 {
45     if ((condition == NULL) || (data == NULL)) {
46         LOG_ERROR("input para is null");
47         return false;
48     }
49     uint64_t executorIndex = *(const uint64_t *)condition;
50     const ExecutorInfoHal *executorInfo = (const ExecutorInfoHal *)data;
51     return (executorInfo->executorIndex == executorIndex);
52 }
53 
IsExecutorNodeMatch(const void * data,const void * condition)54 IAM_STATIC bool IsExecutorNodeMatch(const void *data, const void *condition)
55 {
56     if ((condition == NULL) || (data == NULL)) {
57         LOG_ERROR("get null data");
58         return false;
59     }
60     const ExecutorInfoHal *executorIndex = (const ExecutorInfoHal *)condition;
61     const ExecutorInfoHal *executorInfo = (const ExecutorInfoHal *)data;
62     return (executorInfo->executorRole == executorIndex->executorRole &&
63         executorInfo->authType == executorIndex->authType &&
64         executorInfo->executorSensorHint == executorIndex->executorSensorHint) &&
65         memcmp(executorInfo->deviceUdid, executorIndex->deviceUdid, UDID_LEN) == 0;
66 }
67 
IsInit(void)68 IAM_STATIC bool IsInit(void)
69 {
70     return g_poolList != NULL;
71 }
72 
InitResourcePool(void)73 ResultCode InitResourcePool(void)
74 {
75     if (!IsInit()) {
76         g_poolList = CreateLinkedList(DestroyExecutorInfo);
77     }
78     if (g_poolList == NULL) {
79         return RESULT_GENERAL_ERROR;
80     }
81     return RESULT_SUCCESS;
82 }
83 
DestroyResourcePool(void)84 void DestroyResourcePool(void)
85 {
86     DestroyLinkedList(g_poolList);
87     g_poolList = NULL;
88 }
89 
IsExecutorValid(const ExecutorInfoHal * executorInfo)90 IAM_STATIC bool IsExecutorValid(const ExecutorInfoHal *executorInfo)
91 {
92     if (executorInfo == NULL) {
93         LOG_ERROR("get null data");
94         return false;
95     }
96     return true;
97 }
98 
IsExecutorIdDuplicate(uint64_t executorIndex)99 IAM_STATIC bool IsExecutorIdDuplicate(uint64_t executorIndex)
100 {
101     LinkedListNode *temp = g_poolList->head;
102     ExecutorInfoHal *executorInfo = NULL;
103     while (temp != NULL) {
104         executorInfo = (ExecutorInfoHal *)temp->data;
105         if (executorInfo != NULL && executorInfo->executorIndex == executorIndex) {
106             return true;
107         }
108         temp = temp->next;
109     }
110 
111     return false;
112 }
113 
GenerateValidExecutorId(uint64_t * executorIndex)114 IAM_STATIC ResultCode GenerateValidExecutorId(uint64_t *executorIndex)
115 {
116     if (g_poolList == NULL) {
117         LOG_ERROR("g_poolList is null");
118         return RESULT_BAD_PARAM;
119     }
120 
121     for (uint32_t i = 0; i < MAX_DUPLICATE_CHECK; ++i) {
122         uint64_t tempRandom;
123         if (SecureRandom((uint8_t *)&tempRandom, sizeof(uint64_t)) != RESULT_SUCCESS) {
124             LOG_ERROR("get random failed");
125             return RESULT_GENERAL_ERROR;
126         }
127         if (!IsExecutorIdDuplicate(tempRandom)) {
128             *executorIndex = tempRandom;
129             return RESULT_SUCCESS;
130         }
131     }
132 
133     LOG_ERROR("a rare failure");
134     return RESULT_GENERAL_ERROR;
135 }
136 
QueryRepeatExecutor(ExecutorInfoHal * executorInfo)137 IAM_STATIC LinkedList *QueryRepeatExecutor(ExecutorInfoHal *executorInfo)
138 {
139     ExecutorCondition condition = {};
140     SetExecutorConditionAuthType(&condition, executorInfo->authType);
141     SetExecutorConditionSensorHint(&condition, executorInfo->executorSensorHint);
142     SetExecutorConditionExecutorRole(&condition, executorInfo->executorRole);
143     const Uint8Array udid = { executorInfo->deviceUdid, UDID_LEN };
144     SetExecutorConditionDeviceUdid(&condition, udid);
145     return QueryExecutor(&condition);
146 }
147 
RegisterExecutorToPool(ExecutorInfoHal * executorInfo)148 ResultCode RegisterExecutorToPool(ExecutorInfoHal *executorInfo)
149 {
150     if (!IsInit()) {
151         LOG_ERROR("pool not init");
152         return RESULT_NEED_INIT;
153     }
154     if (!IsExecutorValid(executorInfo)) {
155         LOG_ERROR("get invalid executorInfo");
156         return RESULT_BAD_PARAM;
157     }
158     LinkedList *executors = QueryRepeatExecutor(executorInfo);
159     if (executors == NULL) {
160         LOG_ERROR("query executor failed");
161         return RESULT_NO_MEMORY;
162     }
163     ResultCode result = RESULT_UNKNOWN;
164     if (executors->getSize(executors) != 0) {
165         if (executors->head == NULL || executors->head->data == NULL) {
166             LOG_ERROR("list node is invalid");
167             goto EXIT;
168         }
169         executorInfo->executorIndex = ((ExecutorInfoHal *)(executors->head->data))->executorIndex;
170         if (g_poolList->remove(g_poolList, (void *)executorInfo, IsExecutorNodeMatch, true) != RESULT_SUCCESS) {
171             LOG_INFO("remove executor failed");
172             goto EXIT;
173         }
174     } else {
175         result = GenerateValidExecutorId(&executorInfo->executorIndex);
176         if (result != RESULT_SUCCESS) {
177             LOG_ERROR("get executorId failed");
178             goto EXIT;
179         }
180     }
181     ExecutorInfoHal *executorCopy = CopyExecutorInfo(executorInfo);
182     if (executorCopy == NULL) {
183         LOG_ERROR("copy executor failed");
184         result = RESULT_BAD_COPY;
185         goto EXIT;
186     }
187     result = g_poolList->insert(g_poolList, (void *)executorCopy);
188     if (result != RESULT_SUCCESS) {
189         LOG_ERROR("insert failed");
190         DestroyExecutorInfo(executorCopy);
191     }
192 
193 EXIT:
194     DestroyLinkedList(executors);
195     return result;
196 }
197 
UnregisterExecutorToPool(uint64_t executorIndex)198 ResultCode UnregisterExecutorToPool(uint64_t executorIndex)
199 {
200     if (!IsInit()) {
201         LOG_ERROR("pool not init");
202         return RESULT_NEED_INIT;
203     }
204     return g_poolList->remove(g_poolList, (void *)&executorIndex, IsExecutorIdMatchById, true);
205 }
206 
CopyExecutorInfo(ExecutorInfoHal * src)207 ExecutorInfoHal *CopyExecutorInfo(ExecutorInfoHal *src)
208 {
209     if (src == NULL) {
210         LOG_ERROR("get null data");
211         return NULL;
212     }
213     ExecutorInfoHal *dest = (ExecutorInfoHal *)Malloc(sizeof(ExecutorInfoHal));
214     if (dest == NULL) {
215         LOG_ERROR("no memory");
216         return NULL;
217     }
218     if (memcpy_s(dest, sizeof(ExecutorInfoHal), src, sizeof(ExecutorInfoHal)) != EOK) {
219         LOG_ERROR("copy executor info failed");
220         Free(dest);
221         return NULL;
222     }
223     return dest;
224 }
225 
IsExecutorMatch(const ExecutorCondition * condition,const ExecutorInfoHal * credentialInfo)226 IAM_STATIC bool IsExecutorMatch(const ExecutorCondition *condition, const ExecutorInfoHal *credentialInfo)
227 {
228     if ((condition->conditonFactor & EXECUTOR_CONDITION_INDEX) != 0 &&
229         condition->executorIndex != credentialInfo->executorIndex) {
230         return false;
231     }
232     if ((condition->conditonFactor & EXECUTOR_CONDITION_AUTH_TYPE) != 0 &&
233         condition->authType != credentialInfo->authType) {
234         return false;
235     }
236     if ((condition->conditonFactor & EXECUTOR_CONDITION_SENSOR_HINT) != 0 &&
237         condition->executorSensorHint != INVALID_SENSOR_HINT &&
238         condition->executorSensorHint != credentialInfo->executorSensorHint) {
239         return false;
240     }
241     if ((condition->conditonFactor & EXECUTOR_CONDITION_ROLE) != 0 &&
242         condition->executorRole != credentialInfo->executorRole) {
243         return false;
244     }
245     if ((condition->conditonFactor & EXECUTOR_CONDITION_MATCHER) != 0 &&
246         condition->executorMatcher != credentialInfo->executorMatcher) {
247         return false;
248     }
249     if ((condition->conditonFactor & EXECUTOR_CONDITION_UDID) != 0 &&
250         memcmp(condition->deviceUdid, credentialInfo->deviceUdid, UDID_LEN) != 0) {
251         return false;
252     }
253     return true;
254 }
255 
QueryExecutor(const ExecutorCondition * condition)256 LinkedList *QueryExecutor(const ExecutorCondition *condition)
257 {
258     if (!IsInit()) {
259         LOG_ERROR("pool not init");
260         return NULL;
261     }
262     LinkedList *result = CreateLinkedList(DestroyExecutorInfo);
263     if (result == NULL) {
264         LOG_ERROR("create result list failed");
265         return NULL;
266     }
267     LinkedListIterator *iterator = g_poolList->createIterator(g_poolList);
268     if (iterator == NULL) {
269         LOG_ERROR("create iterator failed");
270         DestroyLinkedList(result);
271         return NULL;
272     }
273 
274     while (iterator->hasNext(iterator)) {
275         ExecutorInfoHal *executorInfo = (ExecutorInfoHal *)iterator->next(iterator);
276         if (!IsExecutorValid(executorInfo)) {
277             LOG_ERROR("get invalid executor info");
278             continue;
279         }
280         if (!IsExecutorMatch(condition, executorInfo)) {
281             continue;
282         }
283         ExecutorInfoHal *copy = CopyExecutorInfo(executorInfo);
284         if (copy == NULL) {
285             LOG_ERROR("copy executor info failed");
286             continue;
287         }
288         if (result->insert(result, copy) != RESULT_SUCCESS) {
289             LOG_ERROR("insert executor info failed");
290             DestroyExecutorInfo(copy);
291             continue;
292         }
293     }
294     g_poolList->destroyIterator(iterator);
295     return result;
296 }
297 
QueryCollecterMatcher(uint32_t authType,uint32_t executorSensorHint,uint32_t * matcher)298 ResultCode QueryCollecterMatcher(uint32_t authType, uint32_t executorSensorHint, uint32_t *matcher)
299 {
300     if (!IsInit()) {
301         LOG_ERROR("pool not init");
302         return RESULT_NEED_INIT;
303     }
304     if (matcher == NULL) {
305         LOG_ERROR("matcher is null");
306         return RESULT_BAD_PARAM;
307     }
308     LinkedListIterator *iterator = g_poolList->createIterator(g_poolList);
309     if (iterator == NULL) {
310         LOG_ERROR("create iterator failed");
311         return RESULT_NO_MEMORY;
312     }
313 
314     while (iterator->hasNext(iterator)) {
315         ExecutorInfoHal *executorInfo = (ExecutorInfoHal *)(iterator->next(iterator));
316         if (!IsExecutorValid(executorInfo)) {
317             LOG_ERROR("get invalid executor info");
318             continue;
319         }
320         if (executorInfo->authType == authType && executorInfo->executorSensorHint == executorSensorHint &&
321             (executorInfo->executorRole == COLLECTOR || executorInfo->executorRole == ALL_IN_ONE)) {
322             *matcher = executorInfo->executorMatcher;
323             g_poolList->destroyIterator(iterator);
324             return RESULT_SUCCESS;
325         }
326     }
327     LOG_ERROR("can't found executor, sensor hint is %{public}u", executorSensorHint);
328     g_poolList->destroyIterator(iterator);
329     return RESULT_NOT_FOUND;
330 }
331 
332 
QueryCredentialExecutorIndex(uint32_t authType,uint32_t executorSensorHint)333 uint64_t QueryCredentialExecutorIndex(uint32_t authType, uint32_t executorSensorHint)
334 {
335     if (!IsInit()) {
336         LOG_ERROR("pool not init");
337         return INVALID_EXECUTOR_INDEX;
338     }
339     LinkedListIterator *iterator = g_poolList->createIterator(g_poolList);
340     if (iterator == NULL) {
341         LOG_ERROR("create iterator failed");
342         return INVALID_EXECUTOR_INDEX;
343     }
344 
345     while (iterator->hasNext(iterator)) {
346         ExecutorInfoHal *executorInfo = (ExecutorInfoHal *)(iterator->next(iterator));
347         if (!IsExecutorValid(executorInfo)) {
348             LOG_ERROR("get invalid executor info");
349             continue;
350         }
351         if (executorInfo->authType == authType && executorInfo->executorSensorHint == executorSensorHint &&
352             executorInfo->executorRole == ALL_IN_ONE) {
353             g_poolList->destroyIterator(iterator);
354             return executorInfo->executorIndex;
355         }
356     }
357     LOG_ERROR("can't found executor, sensor hint is %{public}u", executorSensorHint);
358     g_poolList->destroyIterator(iterator);
359     return INVALID_EXECUTOR_INDEX;
360 }
361 
362 
SetExecutorConditionExecutorIndex(ExecutorCondition * condition,uint64_t executorIndex)363 void SetExecutorConditionExecutorIndex(ExecutorCondition *condition, uint64_t executorIndex)
364 {
365     if (condition == NULL) {
366         LOG_ERROR("condition is null");
367         return;
368     }
369     condition->executorIndex = executorIndex;
370     condition->conditonFactor |= EXECUTOR_CONDITION_INDEX;
371 }
372 
SetExecutorConditionAuthType(ExecutorCondition * condition,uint32_t authType)373 void SetExecutorConditionAuthType(ExecutorCondition *condition, uint32_t authType)
374 {
375     if (condition == NULL) {
376         LOG_ERROR("condition is null");
377         return;
378     }
379     condition->authType = authType;
380     condition->conditonFactor |= EXECUTOR_CONDITION_AUTH_TYPE;
381 }
382 
SetExecutorConditionSensorHint(ExecutorCondition * condition,uint32_t executorSensorHint)383 void SetExecutorConditionSensorHint(ExecutorCondition *condition, uint32_t executorSensorHint)
384 {
385     if (condition == NULL) {
386         LOG_ERROR("condition is null");
387         return;
388     }
389     condition->executorSensorHint = executorSensorHint;
390     condition->conditonFactor |= EXECUTOR_CONDITION_SENSOR_HINT;
391 }
392 
SetExecutorConditionExecutorRole(ExecutorCondition * condition,uint32_t executorRole)393 void SetExecutorConditionExecutorRole(ExecutorCondition *condition, uint32_t executorRole)
394 {
395     if (condition == NULL) {
396         LOG_ERROR("condition is null");
397         return;
398     }
399     condition->executorRole = executorRole;
400     condition->conditonFactor |= EXECUTOR_CONDITION_ROLE;
401 }
402 
SetExecutorConditionExecutorMatcher(ExecutorCondition * condition,uint32_t executorMatcher)403 void SetExecutorConditionExecutorMatcher(ExecutorCondition *condition, uint32_t executorMatcher)
404 {
405     if (condition == NULL) {
406         LOG_ERROR("condition is null");
407         return;
408     }
409     condition->executorMatcher = executorMatcher;
410     condition->conditonFactor |= EXECUTOR_CONDITION_MATCHER;
411 }
412 
SetExecutorConditionDeviceUdid(ExecutorCondition * condition,Uint8Array deviceUdid)413 void SetExecutorConditionDeviceUdid(ExecutorCondition *condition, Uint8Array deviceUdid)
414 {
415     if (condition == NULL || IS_ARRAY_NULL(deviceUdid)) {
416         LOG_ERROR("condition is null");
417         return;
418     }
419     if (memcpy_s(condition->deviceUdid, UDID_LEN, deviceUdid.data, deviceUdid.len) != EOK) {
420         LOG_ERROR("copy udid failed");
421         return;
422     }
423     condition->conditonFactor |= EXECUTOR_CONDITION_UDID;
424 }