• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "securec.h"
10 #include "osal/osal_thread.h"
11 #include "osal/osal_time.h"
12 #include "osal/osal_mutex.h"
13 #include "utils/hdf_log.h"
14 #include "message_dispatcher.h"
15 #include "hdf_wlan_priority_queue.h"
16 #include "message_router_inner.h"
17 
18 #ifdef USERSPACE_CLIENT_SUPPORT
19 #define HDF_LOG_TAG UMsgEngine
20 #else
21 #define HDF_LOG_TAG KMsgEngine
22 #endif
23 
24 typedef struct {
25     INHERT_MESSAGE_DISPATCHER;
26     OSAL_DECLARE_THREAD(dispatcherThread);
27 } LocalMessageDispatcher;
28 
ReleaseMessageContext(MessageContext * context)29 void ReleaseMessageContext(MessageContext *context)
30 {
31     if (context == NULL) {
32         HDF_LOGE("%s: Input param is null!", __func__);
33         return;
34     }
35     if (context->rspData != NULL) {
36         HdfSbufRecycle(context->rspData);
37         context->rspData = NULL;
38     }
39 
40     if (context->crossNode ||
41         (context->requestType != MESSAGE_TYPE_SYNC_REQ && context->requestType != MESSAGE_TYPE_SYNC_RSP)) {
42         // Sync request message may use stack mem.Memory is managed by user
43         if (context->reqData != NULL) {
44             HdfSbufRecycle(context->reqData);
45             context->reqData = NULL;
46         }
47         OsalMemFree(context);
48     }
49     HDF_LOGD("%s: ReleaseMessageContext finished!", __func__);
50 }
51 
ReleaseMessageMapper(struct ServiceDef * mapper)52 void ReleaseMessageMapper(struct ServiceDef *mapper)
53 {
54     if (mapper == NULL) {
55         return;
56     }
57     if (mapper->messages != NULL) {
58         OsalMemFree(mapper->messages);
59         mapper->messages = NULL;
60     }
61     OsalMemFree(mapper);
62 }
63 
GetMsgDef(const struct ServiceDef * serviceDef,uint32_t commandId)64 struct MessageDef *GetMsgDef(const struct ServiceDef *serviceDef, uint32_t commandId)
65 {
66     struct MessageDef *msgDef = NULL;
67     if (serviceDef == NULL || serviceDef->messages == NULL) {
68         HDF_LOGE("%s:input is NULL!", __func__);
69         return NULL;
70     }
71     if (commandId >= serviceDef->messagesLength) {
72         HDF_LOGE("%s:commandId exceed service def!", __func__);
73         return NULL;
74     }
75 
76     msgDef = serviceDef->messages + commandId;
77     if (msgDef->handler == NULL) {
78         HDF_LOGE("%s:command has no handler!", __func__);
79         return NULL;
80     }
81     return msgDef;
82 }
83 
AppendToLocalDispatcher(MessageDispatcher * dispatcher,const uint8_t priority,MessageContext * context)84 ErrorCode AppendToLocalDispatcher(MessageDispatcher *dispatcher, const uint8_t priority, MessageContext *context)
85 {
86     if (context == NULL) {
87         HDF_LOGE("%s:Input context is NULL!", __func__);
88         return ME_ERROR_NULL_PTR;
89     }
90     if (dispatcher == NULL) {
91         HDF_LOGE("%s:Input dispatcher is NULL!", __func__);
92         return ME_ERROR_NULL_PTR;
93     }
94 
95     if (dispatcher->messageQueue == NULL) {
96         HDF_LOGE("MessageQueue is NULL.");
97         return ME_ERROR_NULL_PTR;
98     }
99 
100     if (dispatcher->status != ME_STATUS_RUNNING) {
101         HDF_LOGE("%s:Dispatcher is not running", __func__);
102         return ME_ERROR_DISPATCHER_NOT_RUNNING;
103     }
104     HDF_LOGD("%s:AppendToLocalDispatcher finished!", __func__);
105     return PushPriorityQueue(dispatcher->messageQueue, priority, context);
106 }
107 
SetToResponse(MessageContext * context)108 void SetToResponse(MessageContext *context)
109 {
110     ServiceId senderId;
111     if (context->requestType != MESSAGE_TYPE_ASYNC_REQ && context->requestType != MESSAGE_TYPE_SYNC_REQ) {
112         HDF_LOGE("Only sync and async message can send response!type=%u", context->requestType);
113         return;
114     }
115     senderId = context->senderId;
116     context->senderId = context->receiverId;
117     context->receiverId = senderId;
118     context->requestType = MESSAGE_RSP_START + context->requestType - MESSAGE_REQ_START;
119     HDF_LOGD("%s:SetToResponse finished", __func__);
120 }
121 
HandleAsyncResponse(MessageContext * context)122 static void HandleAsyncResponse(MessageContext *context)
123 {
124     if (context == NULL) {
125         return;
126     }
127 
128     if (context->callback != NULL) {
129         context->callback((RequestContext *)context, context->reqData, context->rspData, context->responseStatus);
130     }
131 
132     ReleaseMessageContext(context);
133 }
134 
HandleSyncResponse(MessageContext * context)135 static void HandleSyncResponse(MessageContext *context)
136 {
137     HDF_STATUS status;
138     if (context == NULL) {
139         HDF_LOGE("Input context is NULL!");
140         return;
141     }
142     status = OsalSemPost(&context->rspSemaphore);
143     if (status != HDF_SUCCESS) {
144         HDF_LOGE("Send semaphore failed!CMD=%u,Sender=%u,Receiver=%u", context->commandId, context->senderId,
145             context->receiverId);
146     }
147     return;
148 }
149 
HandleRequestMessage(MessageContext * context)150 static void HandleRequestMessage(MessageContext *context)
151 {
152     RemoteService *targetService = RefRemoteService(context->receiverId);
153     ErrorCode errCode = ME_SUCCESS;
154     RemoteService *rspService = NULL;
155     do {
156         if (targetService == NULL) {
157             HDF_LOGE("%s:Service %u is not available!", __func__, context->receiverId);
158             errCode = ME_ERROR_NULL_PTR;
159             break;
160         }
161 
162         if (targetService->ExecRequestMsg == NULL) {
163             HDF_LOGE("%s:Service %u has no ExecMsg method!", __func__, context->receiverId);
164             errCode = ME_ERROR_NULL_PTR;
165             break;
166         }
167         targetService->ExecRequestMsg(targetService, context);
168 
169         // Convert to response message
170         SetToResponse(context);
171 
172         if (context->requestType == MESSAGE_TYPE_ASYNC_RSP && context->callback == NULL) {
173             ReleaseMessageContext(context);
174             break;
175         }
176 
177         rspService = RefRemoteService(context->receiverId);
178         if (rspService == NULL) {
179             errCode = ME_ERROR_NO_SUCH_SERVICE;
180             break;
181         }
182         if (rspService->SendMessage == NULL) {
183             errCode = ME_ERROR_BAD_SERVICE;
184             break;
185         }
186         errCode = rspService->SendMessage(rspService, context);
187     } while (false);
188 
189     if (errCode != ME_SUCCESS) {
190         if (context->requestType == MESSAGE_TYPE_SYNC_RSP || context->requestType == MESSAGE_TYPE_SYNC_REQ) {
191             (void)OsalSemPost(&context->rspSemaphore);
192         } else {
193             ReleaseMessageContext(context);
194         }
195     }
196 
197     if (targetService != NULL && targetService->Disref != NULL) {
198         targetService->Disref(targetService);
199         targetService = NULL;
200     }
201 
202     if (rspService != NULL && rspService->Disref != NULL) {
203         rspService->Disref(rspService);
204         rspService = NULL;
205     }
206 }
207 
HandleMessage(MessageContext * context)208 static void HandleMessage(MessageContext *context)
209 {
210     if (context != NULL) {
211         switch (context->requestType) {
212             case MESSAGE_TYPE_SYNC_REQ:
213             case MESSAGE_TYPE_ASYNC_REQ:
214                 HandleRequestMessage(context);
215                 break;
216             case MESSAGE_TYPE_SYNC_RSP:
217                 HandleSyncResponse(context);
218                 break;
219             case MESSAGE_TYPE_ASYNC_RSP:
220                 HandleAsyncResponse(context);
221                 break;
222             default:
223                 HDF_LOGE("Unsupported message type %u", context->requestType);
224         }
225     }
226 }
227 
ReleaseAllMessage(MessageDispatcher * dispatcher)228 static void ReleaseAllMessage(MessageDispatcher *dispatcher)
229 {
230     MessageContext *context = NULL;
231     do {
232         HDF_LOGD("%s: ReleaseAllMessage starting...!", __func__);
233         context = PopPriorityQueue(dispatcher->messageQueue, 0);
234         ReleaseMessageContext(context);
235     } while (context != NULL);
236 }
237 
RunDispatcher(void * para)238 static int RunDispatcher(void *para)
239 {
240     MessageDispatcher *dispatcher = NULL;
241     MessageContext *context = NULL;
242     if (para == NULL) {
243         HDF_LOGE("Start dispatcher failed! cause:%s\n", "input para is NULL");
244         return ME_ERROR_NULL_PTR;
245     }
246     dispatcher = (MessageDispatcher *)para;
247     if (dispatcher->messageQueue == NULL) {
248         HDF_LOGE("Start dispatcher failed! cause:%s\n", "message queue is NULL");
249         return ME_ERROR_NULL_PTR;
250     }
251 
252     if (dispatcher->Ref != NULL) {
253         dispatcher = dispatcher->Ref(dispatcher);
254     }
255 
256     if (dispatcher->status != ME_STATUS_STARTTING) {
257         if (dispatcher->Disref != NULL) {
258             dispatcher->Disref(dispatcher);
259         }
260         HDF_LOGE("Start dispatcher failed! cause:%s\n", "dispatcher is not stopped");
261         return ME_ERROR_WRONG_STATUS;
262     } else {
263         dispatcher->status = ME_STATUS_RUNNING;
264     }
265     while (dispatcher->status == ME_STATUS_RUNNING) {
266         context = PopPriorityQueue(dispatcher->messageQueue, QUEUE_OPER_TIMEOUT);
267         if (context == NULL) {
268             continue;
269         }
270         HandleMessage(context);
271     }
272 
273     ReleaseAllMessage(dispatcher);
274     dispatcher->status = ME_STATUS_TODESTROY;
275     if (dispatcher->Disref != NULL) {
276         dispatcher->Disref(dispatcher);
277         dispatcher = NULL;
278     }
279 
280     HDF_LOGW("Dispatcher shutdown!");
281     return ME_SUCCESS;
282 }
283 
StartDispatcher(MessageDispatcher * dispatcher)284 static ErrorCode StartDispatcher(MessageDispatcher *dispatcher)
285 {
286     HDF_STATUS status;
287     ErrorCode errCode;
288     LocalMessageDispatcher *localDispatcher = NULL;
289     struct OsalThreadParam config;
290     if (dispatcher == NULL) {
291         return ME_ERROR_NULL_PTR;
292     }
293 
294     status = OsalMutexTimedLock(&dispatcher->mutex, HDF_WAIT_FOREVER);
295     if (status != HDF_SUCCESS) {
296         return ME_ERROR_OPER_MUTEX_FAILED;
297     }
298 
299     errCode = ME_SUCCESS;
300     do {
301         if (dispatcher->status != ME_STATUS_STOPPED) {
302             errCode = ME_ERROR_WRONG_STATUS;
303             break;
304         }
305         dispatcher->status = ME_STATUS_STARTTING;
306         config.name = "MessageDispatcher";
307         config.priority = OSAL_THREAD_PRI_DEFAULT;
308         config.stackSize = 0x2000;
309         localDispatcher = (LocalMessageDispatcher *)dispatcher;
310         status = OsalThreadCreate(&localDispatcher->dispatcherThread, RunDispatcher, localDispatcher);
311         if (status != HDF_SUCCESS) {
312             HDF_LOGE("%s:OsalThreadCreate failed!status=%d", __func__, status);
313             dispatcher->status = ME_STATUS_STOPPED;
314             errCode = ME_ERROR_CREATE_THREAD_FAILED;
315             break;
316         }
317 
318         status = OsalThreadStart(&localDispatcher->dispatcherThread, &config);
319         if (status != HDF_SUCCESS) {
320             HDF_LOGE("%s:OsalThreadStart failed!status=%d", __func__, status);
321             dispatcher->status = ME_STATUS_STOPPED;
322             OsalThreadDestroy(&localDispatcher->dispatcherThread);
323             errCode = ME_ERROR_CREATE_THREAD_FAILED;
324             break;
325         }
326     } while (false);
327 
328     status = OsalMutexUnlock(&dispatcher->mutex);
329     if (status != HDF_SUCCESS) {
330         HDF_LOGE("%s:Destroy mutex failed!", __func__);
331     }
332 
333     if (errCode != ME_SUCCESS) {
334         return errCode;
335     }
336 
337     do {
338         OsalMSleep(1);
339     } while (dispatcher->status == ME_STATUS_STARTTING);
340     return (dispatcher->status == ME_STATUS_RUNNING) ? ME_SUCCESS : ME_ERROR_WRONG_STATUS;
341 }
342 
ShutdownDispatcher(MessageDispatcher * dispatcher)343 static void ShutdownDispatcher(MessageDispatcher *dispatcher)
344 {
345     HDF_STATUS status;
346     if (dispatcher == NULL) {
347         HDF_LOGE("%s: Input param is null!", __func__);
348         return;
349     }
350     status = OsalMutexTimedLock(&dispatcher->mutex, HDF_WAIT_FOREVER);
351     if (status != HDF_SUCCESS) {
352         HDF_LOGE("Get lock failed!status=%d", status);
353         return;
354     }
355 
356     do {
357         if (dispatcher->status != ME_STATUS_RUNNING && dispatcher->status != ME_STATUS_STARTTING) {
358             HDF_LOGE("%s:wrong status.status=%d", __func__, dispatcher->status);
359             break;
360         }
361         dispatcher->status = ME_STATUS_STOPPING;
362     } while (false);
363 
364     status = OsalMutexUnlock(&dispatcher->mutex);
365     if (status != HDF_SUCCESS) {
366         HDF_LOGE("%s:Destroy mutex failed!", __func__);
367     }
368     HDF_LOGD("%s:ShutdownDispatcher successful!", __func__);
369 }
370 
371 IMPLEMENT_SHARED_OBJ(MessageDispatcher);
DestroyLocalDispatcher(MessageDispatcher * dispatcher)372 static void DestroyLocalDispatcher(MessageDispatcher *dispatcher)
373 {
374     int32_t ret;
375     if (dispatcher == NULL) {
376         HDF_LOGE("%s: Input param is null!", __func__);
377         return;
378     }
379 
380     ReleaseAllMessage(dispatcher);
381 
382     if (dispatcher->messageQueue != NULL) {
383         DestroyPriorityQueue(dispatcher->messageQueue);
384         dispatcher->messageQueue = NULL;
385     }
386 
387     ret = OsalMutexDestroy(&dispatcher->mutex);
388     if (ret != HDF_SUCCESS) {
389         HDF_LOGE("%s:Release mutex failed.ret=%d", __func__, ret);
390     }
391 
392     DEINIT_SHARED_OBJ(MessageDispatcher, dispatcher);
393     HDF_LOGD("%s:DestroyLocalDispatcher finished!", __func__);
394 }
395 
CreateLocalDispatcher(MessageDispatcher ** dispatcher,const DispatcherConfig * config)396 ErrorCode CreateLocalDispatcher(MessageDispatcher **dispatcher, const DispatcherConfig *config)
397 {
398     LocalMessageDispatcher *localDispatcher = NULL;
399     int32_t ret;
400     ErrorCode errCode;
401     if (dispatcher == NULL || config == NULL) {
402         HDF_LOGE("%s: Input param is null!", __func__);
403         return ME_ERROR_NULL_PTR;
404     }
405 
406     localDispatcher = (LocalMessageDispatcher *)OsalMemCalloc(sizeof(LocalMessageDispatcher));
407     if (localDispatcher == NULL) {
408         HDF_LOGE("%s: Request memory failed!", __func__);
409         return ME_ERROR_RES_LAKE;
410     }
411     do {
412         HDF_LOGI("%s: Create local dispatcher...!", __func__);
413         localDispatcher->status = ME_STATUS_STOPPED;
414         localDispatcher->AppendMessage = AppendToLocalDispatcher;
415         localDispatcher->Shutdown = ShutdownDispatcher;
416         localDispatcher->Start = StartDispatcher;
417 
418         localDispatcher->messageQueue = CreatePriorityQueue(config->queueSize, config->priorityLevelCount);
419         if (localDispatcher->messageQueue == NULL) {
420             HDF_LOGE("%s: CreatePriorityQueue failed!", __func__);
421             errCode = ME_ERROR_OPER_QUEUE_FAILED;
422             break;
423         }
424 
425         ret = OsalMutexInit(&localDispatcher->mutex);
426         if (ret != HDF_SUCCESS) {
427             HDF_LOGE("%s: Init mutex failed! ret=%d", __func__, ret);
428             errCode = ME_ERROR_OPER_MUTEX_FAILED;
429             break;
430         }
431 
432         errCode = INIT_SHARED_OBJ(MessageDispatcher, (MessageDispatcher *)localDispatcher, DestroyLocalDispatcher);
433         if (errCode != ME_SUCCESS) {
434             HDF_LOGE("%s: INIT_SHARED_OBJ failed! errCode=%d", __func__, errCode);
435             break;
436         }
437     } while (false);
438 
439     if (errCode == ME_SUCCESS) {
440         *dispatcher = (MessageDispatcher *)localDispatcher;
441     } else {
442         DestroyLocalDispatcher((MessageDispatcher *)localDispatcher);
443         OsalMemFree(localDispatcher);
444     }
445     HDF_LOGI("%s: CreateLocalDispatcher finished! errCode=%d", __func__, errCode);
446     return errCode;
447 }
448