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 }