1 /*
2  * Copyright (C) 2021 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 "callback_manager.h"
17 #include "channel_manager.h"
18 #include "device_auth_defines.h"
19 #include "hc_log.h"
20 #include "hc_mutex.h"
21 #include "hc_types.h"
22 #include "hc_vector.h"
23 #include "securec.h"
24 
25 typedef struct {
26     char *appId;
27     DeviceAuthCallback *callback;
28 } CallbackEntry;
29 
30 DECLARE_HC_VECTOR(GMCallbackEntryVec, CallbackEntry);
31 IMPLEMENT_HC_VECTOR(GMCallbackEntryVec, CallbackEntry, 1)
32 static GMCallbackEntryVec g_callbackVec;
33 static HcMutex *g_callbackMutex = NULL;
34 
UpdateCallbackIfExist(const char * appId,const DeviceAuthCallback * callback)35 static int32_t UpdateCallbackIfExist(const char *appId, const DeviceAuthCallback *callback)
36 {
37     uint32_t index;
38     CallbackEntry *entry = NULL;
39     g_callbackMutex->lock(g_callbackMutex);
40     FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) {
41         if (strcmp(entry->appId, appId) == 0) {
42             if (memcpy_s(entry->callback, sizeof(DeviceAuthCallback),
43                 callback, sizeof(DeviceAuthCallback)) != EOK) {
44                 g_callbackMutex->unlock(g_callbackMutex);
45                 LOGE("Failed to copy service callback!");
46                 return HC_ERR_MEMORY_COPY;
47             }
48             g_callbackMutex->unlock(g_callbackMutex);
49             LOGI("Successfully updated a callback! [AppId]: %s", appId);
50             return HC_SUCCESS;
51         }
52     }
53     g_callbackMutex->unlock(g_callbackMutex);
54     return HC_ERR_CALLBACK_NOT_FOUND;
55 }
56 
AddCallbackIfNotExist(const char * appId,const DeviceAuthCallback * callback)57 static int32_t AddCallbackIfNotExist(const char *appId, const DeviceAuthCallback *callback)
58 {
59     uint32_t appIdLen = HcStrlen(appId) + 1;
60     char *copyAppId = (char *)HcMalloc(appIdLen, 0);
61     if (copyAppId == NULL) {
62         LOGE("Failed to allocate copyAppId memory!");
63         return HC_ERR_ALLOC_MEMORY;
64     }
65     if (strcpy_s(copyAppId, appIdLen, appId) != EOK) {
66         LOGE("Failed to copy appId!");
67         HcFree(copyAppId);
68         return HC_ERR_MEMORY_COPY;
69     }
70     DeviceAuthCallback *copyCallback = (DeviceAuthCallback *)HcMalloc(sizeof(DeviceAuthCallback), 0);
71     if (copyCallback == NULL) {
72         LOGE("Failed to allocate copyCallback memory!");
73         HcFree(copyAppId);
74         return HC_ERR_ALLOC_MEMORY;
75     }
76     if (memcpy_s(copyCallback, sizeof(DeviceAuthCallback), callback, sizeof(DeviceAuthCallback)) != EOK) {
77         LOGE("Failed to copy service callback!");
78         HcFree(copyAppId);
79         HcFree(copyCallback);
80         return HC_ERR_MEMORY_COPY;
81     }
82     CallbackEntry entry;
83     entry.appId = copyAppId;
84     entry.callback = copyCallback;
85     g_callbackMutex->lock(g_callbackMutex);
86     if (g_callbackVec.pushBack(&g_callbackVec, &entry) == NULL) {
87         LOGE("Failed to push callback to vector!");
88         HcFree(copyAppId);
89         HcFree(copyCallback);
90         g_callbackMutex->unlock(g_callbackMutex);
91         return HC_ERR_MEMORY_COPY;
92     }
93     g_callbackMutex->unlock(g_callbackMutex);
94     LOGI("Successfully added a callback! [AppId]: %s", appId);
95     return HC_SUCCESS;
96 }
97 
ProcessTransmitCallback(int64_t reqId,const uint8_t * data,uint32_t dataLen,const DeviceAuthCallback * callback)98 bool ProcessTransmitCallback(int64_t reqId, const uint8_t *data, uint32_t dataLen, const DeviceAuthCallback *callback)
99 {
100     if ((callback != NULL) && (callback->onTransmit != NULL)) {
101         LOGI("[Service][In]: ProcessTransmitCallback! [DataLen]: %u, [ReqId]: %" PRId64, dataLen, reqId);
102         bool res = callback->onTransmit(reqId, data, dataLen);
103         LOGI("[Service][Out]: ProcessTransmitCallback!");
104         return res;
105     }
106     LOGE("[OnTransmit]: Currently, the service callback is NULL! [ReqId]: %" PRId64, reqId);
107     return false;
108 }
109 
ProcessSessionKeyCallback(int64_t reqId,const uint8_t * sessionKey,uint32_t sessionKeyLen,const DeviceAuthCallback * callback)110 void ProcessSessionKeyCallback(int64_t reqId, const uint8_t *sessionKey, uint32_t sessionKeyLen,
111     const DeviceAuthCallback *callback)
112 {
113     if ((callback != NULL) && (callback->onSessionKeyReturned != NULL)) {
114         LOGI("[Service][In]: ProcessSessionKeyCallback! [ReqId]: %" PRId64, reqId);
115         callback->onSessionKeyReturned(reqId, sessionKey, sessionKeyLen);
116         LOGI("[Service][Out]: ProcessSessionKeyCallback!");
117         return;
118     }
119     LOGE("[OnSessionKeyReturned]: Currently, the service callback is NULL! [ReqId]: %" PRId64, reqId);
120 }
121 
ProcessFinishCallback(int64_t reqId,int operationCode,const char * returnData,const DeviceAuthCallback * callback)122 void ProcessFinishCallback(int64_t reqId, int operationCode, const char *returnData,
123     const DeviceAuthCallback *callback)
124 {
125     if ((callback != NULL) && (callback->onFinish != NULL)) {
126         LOGI("[Service][In]: ProcessFinishCallback! [ReqId]: %" PRId64, reqId);
127         callback->onFinish(reqId, operationCode, returnData);
128         LOGI("[Service][Out]: ProcessFinishCallback!");
129         return;
130     }
131     LOGE("[OnFinish]: Currently, the service callback is NULL! [ReqId]: %" PRId64, reqId);
132 }
133 
ProcessErrorCallback(int64_t reqId,int operationCode,int errorCode,const char * errorReturn,const DeviceAuthCallback * callback)134 void ProcessErrorCallback(int64_t reqId, int operationCode, int errorCode, const char *errorReturn,
135     const DeviceAuthCallback *callback)
136 {
137     if ((callback != NULL) && (callback->onError != NULL)) {
138         LOGI("[Service][In]: ProcessErrorCallback! [ReqId]: %" PRId64, reqId);
139         callback->onError(reqId, operationCode, errorCode, errorReturn);
140         LOGI("[Service][Out]: ProcessErrorCallback!");
141         return;
142     }
143     LOGE("[OnError]: Currently, the service callback is NULL! [ReqId]: %" PRId64, reqId);
144 }
145 
ProcessRequestCallback(int64_t reqId,int operationCode,const char * reqParams,const DeviceAuthCallback * callback)146 char *ProcessRequestCallback(int64_t reqId, int operationCode, const char *reqParams,
147     const DeviceAuthCallback *callback)
148 {
149     if ((callback != NULL) && (callback->onRequest != NULL)) {
150         LOGI("[Service][In]: ProcessRequestCallback! [ReqId]: %" PRId64, reqId);
151         char *returnData = callback->onRequest(reqId, operationCode, reqParams);
152         LOGI("[Service][Out]: ProcessRequestCallback!");
153         return returnData;
154     }
155     LOGE("[OnRequest]: Currently, the service callback is NULL! [ReqId]: %" PRId64, reqId);
156     return NULL;
157 }
158 
GetGMCallbackByAppId(const char * appId)159 const DeviceAuthCallback *GetGMCallbackByAppId(const char *appId)
160 {
161     uint32_t index;
162     CallbackEntry *entry = NULL;
163     g_callbackMutex->lock(g_callbackMutex);
164     FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) {
165         if (strcmp(entry->appId, appId) == 0) {
166             g_callbackMutex->unlock(g_callbackMutex);
167             return entry->callback;
168         }
169     }
170     g_callbackMutex->unlock(g_callbackMutex);
171     return NULL;
172 }
173 
RegGroupManagerCallback(const char * appId,const DeviceAuthCallback * callback)174 int32_t RegGroupManagerCallback(const char *appId, const DeviceAuthCallback *callback)
175 {
176     if ((appId == NULL) || (callback == NULL)) {
177         LOGE("The input parameters contains NULL value!");
178         return HC_ERR_INVALID_PARAMS;
179     }
180     if (UpdateCallbackIfExist(appId, callback) == HC_SUCCESS) {
181         return HC_SUCCESS;
182     }
183     return AddCallbackIfNotExist(appId, callback);
184 }
185 
UnRegGroupManagerCallback(const char * appId)186 int32_t UnRegGroupManagerCallback(const char *appId)
187 {
188     SET_LOG_MODE(NORMAL_MODE);
189     if (appId == NULL) {
190         LOGE("The input appId is NULL!");
191         return HC_ERR_INVALID_PARAMS;
192     }
193     uint32_t index;
194     CallbackEntry *entry = NULL;
195     g_callbackMutex->lock(g_callbackMutex);
196     FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) {
197         if (strcmp(entry->appId, appId) == 0) {
198             HcFree(entry->appId);
199             HcFree(entry->callback);
200             CallbackEntry tempEntry;
201             HC_VECTOR_POPELEMENT(&g_callbackVec, &tempEntry, index);
202             g_callbackMutex->unlock(g_callbackMutex);
203             LOGI("Successfully removed a callback. [AppId]: %s", appId);
204             return HC_SUCCESS;
205         }
206     }
207     g_callbackMutex->unlock(g_callbackMutex);
208     LOGI("The callback does not exist! [AppId]: %s", appId);
209     return HC_SUCCESS;
210 }
211 
InitCallbackManager(void)212 int32_t InitCallbackManager(void)
213 {
214     if (g_callbackMutex == NULL) {
215         g_callbackMutex = (HcMutex *)HcMalloc(sizeof(HcMutex), 0);
216         if (g_callbackMutex == NULL) {
217             LOGE("Failed to allocate broadcast mutex memory!");
218             return HC_ERR_ALLOC_MEMORY;
219         }
220         if (InitHcMutex(g_callbackMutex) != HC_SUCCESS) {
221             LOGE("Init mutex failed!");
222             HcFree(g_callbackMutex);
223             g_callbackMutex = NULL;
224             return HC_ERROR;
225         }
226     }
227     g_callbackVec = CREATE_HC_VECTOR(GMCallbackEntryVec);
228     return HC_SUCCESS;
229 }
230 
DestroyCallbackManager(void)231 void DestroyCallbackManager(void)
232 {
233     uint32_t index;
234     CallbackEntry *entry = NULL;
235     g_callbackMutex->lock(g_callbackMutex);
236     FOR_EACH_HC_VECTOR(g_callbackVec, index, entry) {
237         HcFree(entry->appId);
238         HcFree(entry->callback);
239     }
240     DESTROY_HC_VECTOR(GMCallbackEntryVec, &g_callbackVec);
241     g_callbackMutex->unlock(g_callbackMutex);
242     DestroyHcMutex(g_callbackMutex);
243     HcFree(g_callbackMutex);
244     g_callbackMutex = NULL;
245 }