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 = (int32_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 const SvcIdentity *samgr = GetContextObject();
119 if (samgr == NULL) {
120 return EC_INVALID;
121 }
122 MessageOption option;
123 MessageOptionInit(&option);
124 int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply,
125 option, (uintptr_t *)&replyBuf);
126 ret = -ret;
127 int32_t ipcRet = ret;
128 if (ret == EC_SUCCESS) {
129 ReadInt32(&reply, &ipcRet);
130 }
131
132 if (replyBuf != NULL) {
133 FreeBuffer(replyBuf);
134 }
135 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap ret = %d", ipcRet);
136
137 return ipcRet;
138 }
139
SAMGR_GetSysCap(const Endpoint * endpoint,const char * sysCap,BOOL * isReg)140 int32 SAMGR_GetSysCap(const Endpoint *endpoint, const char *sysCap, BOOL *isReg)
141 {
142 if (endpoint == NULL) {
143 return EC_INVALID;
144 }
145 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap begin");
146 IpcIo req;
147 uint8 data[MAX_DATA_LEN];
148 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
149 WriteInt32(&req, 0);
150 WriteUint32(&req, RES_SYSCAP);
151 WriteUint32(&req, OP_GET);
152 WriteBool(&req, sysCap);
153
154 IpcIo reply;
155 void *replyBuf = NULL;
156 const SvcIdentity *samgr = GetContextObject();
157 if (samgr == NULL) {
158 return EC_INVALID;
159 }
160 MessageOption option;
161 MessageOptionInit(&option);
162 int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply,
163 option, (uintptr_t *)&replyBuf);
164 ret = -ret;
165 *isReg = FALSE;
166 int32_t ipcRet = ret;
167 if (ret == EC_SUCCESS) {
168 (void)ReadInt32(&reply, &ipcRet);
169 }
170 if (ipcRet == EC_SUCCESS) {
171 (void)ReadBool(&reply, (bool *)isReg);
172 }
173 if (replyBuf != NULL) {
174 FreeBuffer(replyBuf);
175 }
176 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap ret = %d", ipcRet);
177 return ipcRet;
178 }
179
SendGetAllSysCapsRequest(const Endpoint * endpoint,uint32 startIdx,IpcIo * reply,void ** replyBuf)180 static int SendGetAllSysCapsRequest(const Endpoint *endpoint, uint32 startIdx, IpcIo *reply, void **replyBuf)
181 {
182 IpcIo req;
183 uint8 data[MAX_DATA_LEN];
184 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
185 WriteInt32(&req, 0);
186 WriteUint32(&req, RES_SYSCAP);
187 WriteUint32(&req, OP_ALL);
188 WriteUint32(&req, startIdx);
189 const SvcIdentity *samgr = GetContextObject();
190 if (samgr == NULL) {
191 return EC_INVALID;
192 }
193 MessageOption option;
194 MessageOptionInit(&option);
195 int ret = SendRequest(*samgr, INVALID_INDEX, &req, reply,
196 option, (uintptr_t *)replyBuf);
197 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SendGetAllSysCapsRequest startIdx:%u, ret:%d!", startIdx, ret);
198 return -ret;
199 }
200
ParseGetAllSysCapsReply(IpcIo * reply,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum,BOOL * isEnd,uint32 * nextRequestIdx)201 static int32 ParseGetAllSysCapsReply(IpcIo *reply, char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],
202 int32 *sysCapNum, BOOL *isEnd, uint32 *nextRequestIdx)
203 {
204 if (isEnd == NULL) {
205 return EC_INVALID;
206 }
207 int32_t ret;
208 if (ReadInt32(reply, &ret)) {
209 if (ret != EC_SUCCESS) {
210 *isEnd = TRUE;
211 return ret;
212 }
213 } else {
214 *isEnd = TRUE;
215 return EC_INVALID;
216 }
217
218 (void)ReadBool(reply, (bool *)isEnd);
219 (void)ReadUint32(reply, nextRequestIdx);
220 uint32 size;
221 (void)ReadUint32(reply, &size);
222 size = ((size > MAX_SYSCAP_NUM) ? MAX_SYSCAP_NUM : size);
223 int cnt = *sysCapNum;
224 for (uint32 i = 0; i < size; i++) {
225 uint32 len = 0;
226 char *sysCap = (char *)ReadString(reply, (size_t *)&len);
227 if (sysCap == NULL || len == 0) {
228 continue;
229 }
230 if (strcpy_s(sysCaps[cnt], sizeof(sysCaps[cnt]), sysCap) != EC_SUCCESS) {
231 continue;
232 }
233 cnt++;
234 }
235 *sysCapNum = cnt;
236
237 return ret;
238 }
239
SAMGR_GetSystemCapabilities(const Endpoint * endpoint,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum)240 int32 SAMGR_GetSystemCapabilities(const Endpoint *endpoint,
241 char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *sysCapNum)
242 {
243 if (sysCapNum == NULL) {
244 return EC_INVALID;
245 }
246 *sysCapNum = 0;
247 if (endpoint == NULL) {
248 return EC_INVALID;
249 }
250 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities begin");
251 IpcIo reply;
252 void *replyBuf = NULL;
253 uint32 startIdx = 0;
254 BOOL isEnd = TRUE;
255 int ret;
256 do {
257 ret = SendGetAllSysCapsRequest(endpoint, startIdx, &reply, &replyBuf);
258 if (ret == EC_SUCCESS) {
259 ret = ParseGetAllSysCapsReply(&reply, sysCaps, sysCapNum, &isEnd, &startIdx);
260 }
261 if (replyBuf != NULL) {
262 FreeBuffer(replyBuf);
263 }
264 } while (isEnd == FALSE && ret == EC_SUCCESS);
265 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities ret = %d", ret);
266 return ret;
267 }
268
SAMGR_ProcPolicy(const Endpoint * endpoint,const SaName * saName,int token)269 int SAMGR_ProcPolicy(const Endpoint *endpoint, const SaName *saName, int token)
270 {
271 if (endpoint == NULL || saName == NULL || token == INVALID_INDEX) {
272 return EC_INVALID;
273 }
274 // retry until success or 20 seconds.
275 int ret = EC_INVALID;
276 uint8 retry = 0;
277 SvcIdentity saInfo = {INVALID_INDEX, token, INVALID_INDEX};
278 while (retry < MAX_REGISTER_RETRY_TIMES) {
279 ++retry;
280 PolicyTrans *policy = NULL;
281 uint32 policyNum = 0;
282 ret = RegisterIdentity(saName, &saInfo, &policy, &policyNum);
283 if (ret != EC_SUCCESS || policy == NULL) {
284 SAMGR_Free(policy);
285 continue;
286 }
287 HILOG_INFO(HILOG_MODULE_SAMGR, "Register server sa<%s, %s> id<%d> retry:%d ret:%d!",
288 saName->service, saName->feature, saInfo.handle, retry, ret);
289 ret = AddPolicyToRouter(endpoint, &saInfo, policy, policyNum);
290 SAMGR_Free(policy);
291 if (ret == EC_SUCCESS) {
292 break;
293 }
294 sleep(REGISTER_RETRY_INTERVAL);
295 }
296 return ret;
297 }
298
AddPolicyToRouter(const Endpoint * endpoint,const SvcIdentity * saInfo,const PolicyTrans * policy,uint32 policyNum)299 static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo,
300 const PolicyTrans *policy, uint32 policyNum)
301 {
302 if (endpoint == NULL || saInfo == NULL || policy == NULL) {
303 return EC_INVALID;
304 }
305
306 Router *router = VECTOR_At((Vector *)&endpoint->routers, saInfo->token);
307 if (router == NULL) {
308 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s> is NULL", endpoint->name);
309 return EC_INVALID;
310 }
311
312 if (router->policy != NULL) {
313 return EC_SUCCESS;
314 }
315 router->policyNum = policyNum;
316 if (policyNum == 0) {
317 return EC_INVALID;
318 }
319 router->policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * policyNum);
320 if (router->policy == NULL) {
321 return EC_NOMEMORY;
322 }
323 if (memcpy_s(router->policy, sizeof(PolicyTrans) * policyNum, policy,
324 sizeof(PolicyTrans) * policyNum) != EOK) {
325 SAMGR_Free(router->policy);
326 router->policy = NULL;
327 HILOG_ERROR(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Failed!",
328 endpoint->name, router->saName.service, router->saName.feature);
329 return EC_FAILURE;
330 }
331 HILOG_DEBUG(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Success",
332 endpoint->name, router->saName.service, router->saName.feature);
333 return EC_SUCCESS;
334 }
335
CompareIServerProxy(const IServerProxy * proxy1,const IServerProxy * proxy2)336 static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2)
337 {
338 if (proxy1 == proxy2) {
339 return 0;
340 }
341 return (proxy1 > proxy2) ? 1 : -1;
342 }
343
GetIServerProxy(const Router * router)344 static IServerProxy *GetIServerProxy(const Router *router)
345 {
346 if (router == NULL) {
347 return NULL;
348 }
349 return router->proxy;
350 }
351
RegisterRemoteEndpoint(SvcIdentity * identity,int token,const char * service,const char * feature)352 static int RegisterRemoteEndpoint(SvcIdentity *identity, int token, const char *service, const char *feature)
353 {
354 return ClientRegisterRemoteEndpoint(identity, token, service, feature);
355 }