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 }