• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 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 #include "message_inner.h"
16 #include <ohos_errno.h>
17 #include <log.h>
18 #include "memory_adapter.h"
19 #include "queue_adapter.h"
20 #include "securec.h"
21 #include "task_manager.h"
22 
23 #undef LOG_TAG
24 #undef LOG_DOMAIN
25 #define LOG_TAG "Samgr"
26 #define LOG_DOMAIN 0xD001800
27 
28 #define DONT_WAIT 0
29 #define WAIT_FOREVER (-1)
30 static int32 SharedSend(MQueueId queueId, Exchange *exchange, int initRef);
31 static BOOL FreeReference(Exchange *exchange);
32 
SAMGR_SendRequest(const Identity * identity,const Request * request,Handler handler)33 int32 SAMGR_SendRequest(const Identity *identity, const Request *request, Handler handler)
34 {
35     if (request == NULL || identity == NULL) {
36         return EC_INVALID;
37     }
38 
39     Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, NULL};
40     exchange.id.queueId = NULL;
41     if (handler != NULL) {
42         exchange.id.queueId = SAMGR_GetCurrentQueueID();
43         exchange.type = MSG_CON;
44     }
45 
46     return QUEUE_Put(identity->queueId, &exchange, 0, DONT_WAIT);
47 }
48 
SAMGR_SendResponse(const Request * request,const Response * response)49 int32 SAMGR_SendResponse(const Request *request, const Response *response)
50 {
51     // we need send the default the con message or not?
52     if (request == NULL) {
53         return EC_INVALID;
54     }
55 
56     Exchange *exchange = GET_OBJECT(request, Exchange, request);
57     if (exchange->type != MSG_CON) {
58         return EC_INVALID;
59     }
60 
61     if (exchange->handler == NULL) {
62         return EC_SUCCESS;
63     }
64 
65     exchange->type = MSG_ACK;
66     exchange->response.data = NULL;
67     exchange->response.len = 0;
68     if (response != NULL) {
69         exchange->response = *response;
70     }
71 
72     // If there is no task queue, we will call the response processor in current task.
73     if (exchange->id.queueId == NULL) {
74         exchange->handler(&exchange->request, &exchange->response);
75         return EC_SUCCESS;
76     }
77 
78     // Send back to the origin to process the task.
79     int32 ret = SharedSend(exchange->id.queueId, exchange, 1);
80     if (ret != EC_SUCCESS) {
81         exchange->handler(&exchange->request, &exchange->response);
82         (void)FreeReference(exchange);
83     }
84     return EC_SUCCESS;
85 }
86 
SAMGR_MsgRecv(MQueueId queueId,uint8 * interMsg,uint32 size)87 int32 SAMGR_MsgRecv(MQueueId queueId, uint8 *interMsg, uint32 size)
88 {
89     if (queueId == NULL || interMsg == NULL || size == 0) {
90         return EC_INVALID;
91     }
92 
93     if (memset_s(interMsg, size, 0x00, size) != EOK) {
94         return EC_FAILURE;
95     }
96 
97     return QUEUE_Pop(queueId, interMsg, 0, WAIT_FOREVER);
98 }
99 
SAMGR_FreeMsg(Exchange * exchange)100 int32 SAMGR_FreeMsg(Exchange *exchange)
101 {
102     if (!FreeReference(exchange)) {
103         return EC_SUCCESS;
104     }
105 
106     if (exchange->request.len > 0) {
107         SAMGR_Free(exchange->request.data);
108         exchange->request.data = NULL;
109     }
110 
111     if (exchange->response.len > 0) {
112         SAMGR_Free(exchange->response.data);
113         exchange->response.data = NULL;
114     }
115     return EC_SUCCESS;
116 }
117 
SAMGR_SendSharedRequest(const Identity * identity,const Request * request,uint32 * token,Handler handler)118 uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler)
119 {
120     if (identity == NULL || request == NULL) {
121         return NULL;
122     }
123     Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, token};
124     exchange.type = (handler == NULL) ? MSG_NON : MSG_CON;
125     exchange.id.queueId = NULL;
126     int32 err = SharedSend(identity->queueId, &exchange, 0);
127     if (err != EC_SUCCESS) {
128         HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend failed(%d)!", err);
129         (void)FreeReference(&exchange);
130     }
131     return exchange.sharedRef;
132 }
133 
SAMGR_SendSharedDirectRequest(const Identity * id,const Request * req,const Response * resp,uint32 ** ref,Handler handler)134 int32 SAMGR_SendSharedDirectRequest(const Identity *id, const Request *req, const Response *resp, uint32 **ref,
135                                     Handler handler)
136 {
137     if (handler == NULL || ref == NULL) {
138         return EC_INVALID;
139     }
140 
141     Exchange exchange = {0};
142     if (req != NULL) {
143         exchange.request = *req;
144     }
145 
146     if (resp != NULL) {
147         exchange.response = *resp;
148     }
149 
150     exchange.handler = handler;
151     exchange.sharedRef = *ref;
152     exchange.type = MSG_DIRECT;
153     exchange.id = *id;
154     exchange.id.queueId = NULL;
155     int32 err = SharedSend(id->queueId, &exchange, 0);
156     if (err != EC_SUCCESS) {
157         HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend failed(%d)!", err);
158         (void)FreeReference(&exchange);
159     }
160     *ref = exchange.sharedRef;
161     return err;
162 }
163 
SAMGR_SendResponseByIdentity(const Identity * id,const Request * request,const Response * response)164 int32 SAMGR_SendResponseByIdentity(const Identity *id, const Request *request, const Response *response)
165 {
166     // we need send the default the con message or not?
167     if (request == NULL || id == NULL) {
168         return EC_INVALID;
169     }
170 
171     Exchange *exchange = GET_OBJECT(request, Exchange, request);
172     if (exchange->type == MSG_NON) {
173         return EC_INVALID;
174     }
175     exchange->id.queueId = id->queueId;
176 
177     return SAMGR_SendResponse(request, response);
178 }
179 
SharedSend(MQueueId queueId,Exchange * exchange,int initRef)180 static int32 SharedSend(MQueueId queueId, Exchange *exchange, int initRef)
181 {
182     /* if the msg data and response is NULL, we just direct copy, no need shared the message. */
183     if ((exchange->request.data == NULL || exchange->request.len <= 0) &&
184         (exchange->response.data == NULL || exchange->response.len <= 0)) {
185         return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);
186     }
187 
188     /* 1.add reference */
189     MUTEX_GlobalLock();
190     if (exchange->sharedRef == NULL) {
191         exchange->sharedRef = (uint32*)SAMGR_Malloc(sizeof(uint32));
192         if (exchange->sharedRef == NULL) {
193             MUTEX_GlobalUnlock();
194             return EC_NOMEMORY;
195         }
196         *(exchange->sharedRef) = initRef;
197     }
198     (*(exchange->sharedRef))++;
199     MUTEX_GlobalUnlock();
200 
201     return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);
202 }
203 
FreeReference(Exchange * exchange)204 static BOOL FreeReference(Exchange *exchange)
205 {
206     if (exchange == NULL) {
207         return FALSE;
208     }
209 
210     BOOL needFree = TRUE;
211     /* 1. check the shared reference */
212     MUTEX_GlobalLock();
213     if (exchange->sharedRef != NULL) {
214         if (*(exchange->sharedRef) > 0) {
215             (*(exchange->sharedRef))--;
216         }
217 
218         if (*(exchange->sharedRef) > 0) {
219             needFree = FALSE;
220         }
221     }
222     MUTEX_GlobalUnlock();
223 
224     if (needFree) {
225         SAMGR_Free(exchange->sharedRef);
226         exchange->sharedRef = NULL;
227     }
228     return needFree;
229 }