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 "endpoint.h"
16
17 #include <log.h>
18 #include <ohos_errno.h>
19 #include <securec.h>
20 #include <service.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23
24 #include "default_client.h"
25 #include "ipc_skeleton.h"
26 #include "iproxy_server.h"
27 #include "memory_adapter.h"
28 #include "policy_define.h"
29 #include "pthread.h"
30 #include "serializer.h"
31 #include "thread_adapter.h"
32 #include "samgr_ipc_adapter.h"
33
34 static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2);
35 static IServerProxy *GetIServerProxy(const Router *router);
36 static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo,
37 const PolicyTrans *policy, uint32 policyNum);
38 static int RegisterRemoteEndpoint(SvcIdentity *identity, int token, const char *service, const char *feature);
39
SAMGR_CreateEndpoint(const char * name,RegisterEndpoint registry)40 Endpoint *SAMGR_CreateEndpoint(const char *name, RegisterEndpoint registry)
41 {
42 Endpoint *endpoint = SAMGR_Malloc(sizeof(Endpoint));
43 if (endpoint == NULL) {
44 return NULL;
45 }
46 endpoint->deadId = INVALID_INDEX;
47 endpoint->boss = NULL;
48 endpoint->routers = VECTOR_Make((VECTOR_Key)GetIServerProxy, (VECTOR_Compare)CompareIServerProxy);
49 endpoint->name = name;
50 endpoint->running = FALSE;
51 endpoint->identity.handle = (uint32_t)INVALID_INDEX;
52 endpoint->identity.token = (uint32_t)INVALID_INDEX;
53 endpoint->identity.cookie = (uint32_t)INVALID_INDEX;
54 endpoint->registerEP = (registry == NULL) ? RegisterRemoteEndpoint : registry;
55 TB_InitBucket(&endpoint->bucket, MAX_BUCKET_RATE, MAX_BURST_RATE);
56 return endpoint;
57 }
58
SAMGR_AddRouter(Endpoint * endpoint,const SaName * saName,const Identity * id,IUnknown * proxy)59 int SAMGR_AddRouter(Endpoint *endpoint, const SaName *saName, const Identity *id, IUnknown *proxy)
60 {
61 if (endpoint == NULL || id == NULL || proxy == NULL || saName == NULL) {
62 return EC_INVALID;
63 }
64 IServerProxy *serverProxy = NULL;
65 proxy->QueryInterface(proxy, SERVER_PROXY_VER, (void *)&serverProxy);
66 #ifndef MINI_SAMGR_LITE_RPC
67 if (serverProxy == NULL) {
68 return EC_INVALID;
69 }
70 int index = VECTOR_FindByKey(&endpoint->routers, proxy);
71 if (index != INVALID_INDEX) {
72 serverProxy->Release((IUnknown *)serverProxy);
73 return index;
74 }
75 #else
76 int index = VECTOR_FindByKey(&endpoint->routers, proxy);
77 if (index != INVALID_INDEX) {
78 serverProxy->Release((IUnknown *)serverProxy);
79 }
80 #endif
81 Router *router = SAMGR_Malloc(sizeof(Router));
82 if (router == NULL) {
83 HILOG_ERROR(HILOG_MODULE_SAMGR, "Memory is not enough! Identity<%d, %d>",
84 id->serviceId, id->featureId);
85 return EC_NOMEMORY;
86 }
87 router->saName = *saName;
88 router->identity = *id;
89 router->proxy = serverProxy;
90 router->policy = NULL;
91 router->policyNum = 0;
92 index = VECTOR_Add(&endpoint->routers, router);
93 if (index == INVALID_INDEX) {
94 SAMGR_Free(router);
95 return EC_FAILURE;
96 }
97 Listen(endpoint, index, saName->service, saName->feature);
98 return index;
99 }
100
SAMGR_AddSysCap(const Endpoint * endpoint,const char * sysCap,BOOL isReg)101 int32 SAMGR_AddSysCap(const Endpoint *endpoint, const char *sysCap, BOOL isReg)
102 {
103 if (endpoint == NULL) {
104 return EC_INVALID;
105 }
106 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap begin");
107 IpcIo req;
108 uint8 data[MAX_DATA_LEN];
109 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
110 WriteInt32(&req, 0);
111 WriteUint32(&req, RES_SYSCAP);
112 WriteUint32(&req, OP_PUT);
113 WriteBool(&req, sysCap);
114 WriteBool(&req, isReg);
115
116 IpcIo reply;
117 void *replyBuf = NULL;
118 SvcIdentity *samgr = GetContextObject();
119 MessageOption option;
120 MessageOptionInit(&option);
121 int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply,
122 option, (uintptr_t *)&replyBuf);
123 ret = -ret;
124 int32_t ipcRet = ret;
125 if (ret == EC_SUCCESS) {
126 ReadInt32(&reply, &ipcRet);
127 }
128
129 if (replyBuf != NULL) {
130 FreeBuffer(replyBuf);
131 }
132 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap ret = %d", ipcRet);
133
134 return ipcRet;
135 }
136
SAMGR_GetSysCap(const Endpoint * endpoint,const char * sysCap,BOOL * isReg)137 int32 SAMGR_GetSysCap(const Endpoint *endpoint, const char *sysCap, BOOL *isReg)
138 {
139 if (endpoint == NULL) {
140 return EC_INVALID;
141 }
142 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap begin");
143 IpcIo req;
144 uint8 data[MAX_DATA_LEN];
145 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
146 WriteInt32(&req, 0);
147 WriteUint32(&req, RES_SYSCAP);
148 WriteUint32(&req, OP_GET);
149 WriteBool(&req, sysCap);
150
151 IpcIo reply;
152 void *replyBuf = NULL;
153 SvcIdentity *samgr = GetContextObject();
154 MessageOption option;
155 MessageOptionInit(&option);
156 int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply,
157 option, (uintptr_t *)&replyBuf);
158 ret = -ret;
159 *isReg = FALSE;
160 int32_t ipcRet = ret;
161 if (ret == EC_SUCCESS) {
162 (void)ReadInt32(&reply, &ipcRet);
163 }
164 if (ipcRet == EC_SUCCESS) {
165 (void)ReadBool(&reply, (bool *)isReg);
166 }
167 if (replyBuf != NULL) {
168 FreeBuffer(replyBuf);
169 }
170 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap ret = %d", ipcRet);
171 return ipcRet;
172 }
173
SendGetAllSysCapsRequest(const Endpoint * endpoint,uint32 startIdx,IpcIo * reply,void ** replyBuf)174 static int SendGetAllSysCapsRequest(const Endpoint *endpoint, uint32 startIdx, IpcIo *reply, void **replyBuf)
175 {
176 IpcIo req;
177 uint8 data[MAX_DATA_LEN];
178 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
179 WriteInt32(&req, 0);
180 WriteUint32(&req, RES_SYSCAP);
181 WriteUint32(&req, OP_ALL);
182 WriteUint32(&req, startIdx);
183 SvcIdentity *samgr = GetContextObject();
184 MessageOption option;
185 MessageOptionInit(&option);
186 int ret = SendRequest(*samgr, INVALID_INDEX, &req, reply,
187 option, (uintptr_t *)replyBuf);
188 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SendGetAllSysCapsRequest startIdx:%u, ret:%d!", startIdx, ret);
189 return -ret;
190 }
191
ParseGetAllSysCapsReply(IpcIo * reply,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum,BOOL * isEnd,uint32 * nextRequestIdx)192 static int32 ParseGetAllSysCapsReply(IpcIo *reply, char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],
193 int32 *sysCapNum, BOOL *isEnd, uint32 *nextRequestIdx)
194 {
195 int32_t ret;
196 if (ReadInt32(reply, &ret)) {
197 if (ret != EC_SUCCESS) {
198 *isEnd = TRUE;
199 return ret;
200 }
201 } else {
202 *isEnd = TRUE;
203 return EC_INVALID;
204 }
205
206 (void)ReadBool(reply, (bool *)isEnd);
207 (void)ReadUint32(reply, nextRequestIdx);
208 uint32 size;
209 (void)ReadUint32(reply, &size);
210 size = ((size > MAX_SYSCAP_NUM) ? MAX_SYSCAP_NUM : size);
211 int cnt = *sysCapNum;
212 for (uint32 i = 0; i < size; i++) {
213 uint32 len = 0;
214 char *sysCap = (char *)ReadString(reply, (size_t *)&len);
215 if (sysCap == NULL || len == 0) {
216 continue;
217 }
218 if (strcpy_s(sysCaps[cnt], sizeof(sysCaps[cnt]), sysCap) != EC_SUCCESS) {
219 continue;
220 }
221 cnt++;
222 }
223 *sysCapNum = cnt;
224
225 return ret;
226 }
227
SAMGR_GetSystemCapabilities(const Endpoint * endpoint,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum)228 int32 SAMGR_GetSystemCapabilities(const Endpoint *endpoint,
229 char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *sysCapNum)
230 {
231 if (sysCapNum == NULL) {
232 return EC_INVALID;
233 }
234 *sysCapNum = 0;
235 if (endpoint == NULL) {
236 return EC_INVALID;
237 }
238 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities begin");
239 IpcIo reply;
240 void *replyBuf = NULL;
241 uint32 startIdx = 0;
242 BOOL isEnd = TRUE;
243 int ret;
244 do {
245 ret = SendGetAllSysCapsRequest(endpoint, startIdx, &reply, &replyBuf);
246 if (ret == EC_SUCCESS) {
247 ret = ParseGetAllSysCapsReply(&reply, sysCaps, sysCapNum, &isEnd, &startIdx);
248 }
249 if (replyBuf != NULL) {
250 FreeBuffer(replyBuf);
251 }
252 } while (isEnd == FALSE && ret == EC_SUCCESS);
253 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities ret = %d", ret);
254 return ret;
255 }
256
SAMGR_ProcPolicy(const Endpoint * endpoint,const SaName * saName,int token)257 int SAMGR_ProcPolicy(const Endpoint *endpoint, const SaName *saName, int token)
258 {
259 if (endpoint == NULL || saName == NULL || token == INVALID_INDEX) {
260 return EC_INVALID;
261 }
262 // retry until success or 20 seconds.
263 int ret = EC_INVALID;
264 uint8 retry = 0;
265 SvcIdentity saInfo = {INVALID_INDEX, token, INVALID_INDEX};
266 while (retry < MAX_REGISTER_RETRY_TIMES) {
267 ++retry;
268 PolicyTrans *policy = NULL;
269 uint32 policyNum = 0;
270 ret = RegisterIdentity(saName, &saInfo, &policy, &policyNum);
271 if (ret != EC_SUCCESS || policy == NULL) {
272 SAMGR_Free(policy);
273 continue;
274 }
275 HILOG_INFO(HILOG_MODULE_SAMGR, "Register server sa<%s, %s> id<%lu, %u> retry:%d ret:%d!",
276 saName->service, saName->feature, saInfo.handle, saInfo.token, retry, ret);
277 ret = AddPolicyToRouter(endpoint, &saInfo, policy, policyNum);
278 SAMGR_Free(policy);
279 if (ret == EC_SUCCESS) {
280 break;
281 }
282 sleep(REGISTER_RETRY_INTERVAL);
283 }
284 return ret;
285 }
286
AddPolicyToRouter(const Endpoint * endpoint,const SvcIdentity * saInfo,const PolicyTrans * policy,uint32 policyNum)287 static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo,
288 const PolicyTrans *policy, uint32 policyNum)
289 {
290 if (endpoint == NULL || saInfo == NULL || policy == NULL) {
291 return EC_INVALID;
292 }
293
294 Router *router = VECTOR_At((Vector *)&endpoint->routers, saInfo->token);
295 if (router == NULL) {
296 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, saInfo->token);
297 return EC_INVALID;
298 }
299
300 if (router->policy != NULL) {
301 return EC_SUCCESS;
302 }
303 router->policyNum = policyNum;
304 if (policyNum == 0) {
305 return EC_INVALID;
306 }
307 router->policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * policyNum);
308 if (router->policy == NULL) {
309 return EC_NOMEMORY;
310 }
311 if (memcpy_s(router->policy, sizeof(PolicyTrans) * policyNum, policy,
312 sizeof(PolicyTrans) * policyNum) != EOK) {
313 SAMGR_Free(router->policy);
314 router->policy = NULL;
315 HILOG_ERROR(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Failed!",
316 endpoint->name, router->saName.service, router->saName.feature);
317 return EC_FAILURE;
318 }
319 HILOG_DEBUG(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Success",
320 endpoint->name, router->saName.service, router->saName.feature);
321 return EC_SUCCESS;
322 }
323
CompareIServerProxy(const IServerProxy * proxy1,const IServerProxy * proxy2)324 static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2)
325 {
326 if (proxy1 == proxy2) {
327 return 0;
328 }
329 return (proxy1 > proxy2) ? 1 : -1;
330 }
331
GetIServerProxy(const Router * router)332 static IServerProxy *GetIServerProxy(const Router *router)
333 {
334 if (router == NULL) {
335 return NULL;
336 }
337 return router->proxy;
338 }
339
RegisterRemoteEndpoint(SvcIdentity * identity,int token,const char * service,const char * feature)340 static int RegisterRemoteEndpoint(SvcIdentity *identity, int token, const char *service, const char *feature)
341 {
342 return ClientRegisterRemoteEndpoint(identity, token, service, feature);
343 }