• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2022 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 <stdlib.h>
16 #include "default_client_adapter.h"
17 
18 static int AddRef(IUnknown *iUnknown);
19 static int Release(IUnknown *proxy);
20 static int ProxyInvoke(IClientProxy *proxy, int funcId, IpcIo *request, IOwner owner, INotify notify);
21 static void OnServiceExit(void *argv);
22 static SvcIdentity QueryIdentity(const char *service, const char *feature);
23 static SvcIdentity QueryRemoteIdentity(const char *deviceId, const char *service, const char *feature);
24 static const IClientEntry DEFAULT_ENTRY = {CLIENT_IPROXY_BEGIN, .Invoke = ProxyInvoke, IPROXY_END};
25 static MutexId g_mutex = NULL;
26 
SAMGR_IsProxyValid(IUnknown * proxy)27 BOOL SAMGR_IsProxyValid(IUnknown *proxy)
28 {
29     if (proxy != NULL) {
30         IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
31         if (client == NULL) {
32             return false;
33         }
34         IClientHeader *header = &client->header;
35         if (header == NULL) {
36             return false;
37         }
38         if (header->deadId == INVALID_INDEX &&
39         header->target.handle == INVALID_INDEX &&
40         header->target.token == INVALID_INDEX &&
41         header->target.cookie == INVALID_INDEX) {
42             return false;
43         } else {
44             return true;
45         }
46     }
47     return false;
48 }
49 
SAMGR_CreateIProxy(const char * service,const char * feature)50 IUnknown *SAMGR_CreateIProxy(const char *service, const char *feature)
51 {
52     SvcIdentity identity = QueryIdentity(service, feature);
53     if (identity.handle == INVALID_INDEX) {
54         return NULL;
55     }
56 
57     IDefaultClient *client = SAMGR_CreateIClient(service, feature, sizeof(IClientHeader));
58     if (client == NULL) {
59         client = SAMGR_Malloc(sizeof(IDefaultClient));
60         if (client == NULL) {
61             return NULL;
62         }
63         client->entry = DEFAULT_ENTRY;
64     }
65 
66     IClientHeader *header = &client->header;
67     header->target = identity;
68     header->key.service = service;
69     header->key.feature = feature;
70     header->saId = 0;
71     (void)AddDeathRecipient(identity, OnServiceExit, client, &header->deadId);
72 
73     IClientEntry *entry = &client->entry;
74     entry->iUnknown.Invoke = ProxyInvoke;
75     entry->iUnknown.AddRef = AddRef;
76     entry->iUnknown.Release = Release;
77     return GET_IUNKNOWN(*entry);
78 }
79 
SAMGR_CreateIRemoteProxy(const char * deviceId,const char * service,const char * feature)80 IUnknown *SAMGR_CreateIRemoteProxy(const char* deviceId, const char *service, const char *feature)
81 {
82     SvcIdentity identity = QueryRemoteIdentity(deviceId, service, feature);
83 
84     IDefaultClient *client = SAMGR_CreateIClient(service, feature, sizeof(IClientHeader));
85     if (client == NULL) {
86         client = SAMGR_Malloc(sizeof(IDefaultClient));
87         if (client == NULL) {
88             return NULL;
89         }
90         client->entry = DEFAULT_ENTRY;
91     }
92 
93     IClientHeader *header = &client->header;
94     header->target = identity;
95     header->key.service = service;
96     header->key.feature = feature;
97     header->saId = GetRemoteSaIdInner(service, feature);
98 
99     IClientEntry *entry = &client->entry;
100     entry->iUnknown.Invoke = ProxyInvoke;
101     entry->iUnknown.AddRef = AddRef;
102     entry->iUnknown.Release = Release;
103     return GET_IUNKNOWN(*entry);
104 }
105 
SAMGR_GetRemoteIdentity(const char * service,const char * feature)106 SvcIdentity SAMGR_GetRemoteIdentity(const char *service, const char *feature)
107 {
108     SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
109     IUnknown *iUnknown = SAMGR_FindServiceApi(service, feature);
110     if (iUnknown == NULL) {
111         return identity;
112     }
113     IClientProxy *proxy = NULL;
114     if (iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy) != EC_SUCCESS || proxy == NULL) {
115         return identity;
116     }
117     struct IDefaultClient *client = GET_OBJECT(proxy, struct IDefaultClient, entry.iUnknown);
118     identity = client->header.target;
119     proxy->Release((IUnknown *)proxy);
120     return identity;
121 }
122 
SAMGR_GetSAName(const IUnknown * proxy)123 SaName *SAMGR_GetSAName(const IUnknown *proxy)
124 {
125     IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
126     return &(client->header.key);
127 }
128 
SAMGR_CompareSAName(const SaName * key1,const SaName * key2)129 int SAMGR_CompareSAName(const SaName *key1, const SaName *key2)
130 {
131     if (key1 == key2) {
132         return 0;
133     }
134 
135     if (key1->service != key2->service) {
136         int ret = strcmp(key1->service, key2->service);
137         if (ret != 0) {
138             return ret;
139         }
140     }
141 
142     if (key1->feature == key2->feature) {
143         return 0;
144     }
145 
146     if (key1->feature == NULL) {
147         return -1;
148     }
149 
150     if (key2->feature == NULL) {
151         return 1;
152     }
153 
154     return strcmp(key1->feature, key2->feature);
155 }
156 
AddRef(IUnknown * iUnknown)157 static int AddRef(IUnknown *iUnknown)
158 {
159     MUTEX_Lock(g_mutex);
160     int ref = IUNKNOWN_AddRef(iUnknown);
161     MUTEX_Unlock(g_mutex);
162     return ref;
163 }
164 
Release(IUnknown * proxy)165 static int Release(IUnknown *proxy)
166 {
167     MUTEX_Lock(g_mutex);
168     int ref = IUNKNOWN_Release(proxy);
169     MUTEX_Unlock(g_mutex);
170     if (ref != 0) {
171         return ref;
172     }
173     IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
174     int ret = SAMGR_ReleaseIClient(client->header.key.service, client->header.key.feature, client);
175     if (ret == EC_NOHANDLER) {
176         SAMGR_Free(client);
177         return EC_SUCCESS;
178     }
179     return ret;
180 }
181 
ProxyInvoke(IClientProxy * proxy,int funcId,IpcIo * request,IOwner owner,INotify notify)182 static int ProxyInvoke(IClientProxy *proxy, int funcId, IpcIo *request, IOwner owner, INotify notify)
183 {
184     if (proxy == NULL) {
185         return EC_INVALID;
186     }
187 
188     IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
189     IClientHeader *header = &client->header;
190 
191     IpcIo reply;
192     void *replyBuf = NULL;
193     MessageOption flag;
194     MessageOptionInit(&flag);
195     flag.flags = (notify == NULL) ? TF_OP_ASYNC : TF_OP_SYNC;
196     IpcIo requestWrapper;
197     uint8_t *data = (uint8_t *) malloc(MAX_IO_SIZE);
198     if (data == NULL) {
199         HILOG_ERROR(HILOG_MODULE_SAMGR, "malloc data for ipc io failed\n");
200         return EC_INVALID;
201     } else {
202         IpcIoInit(&requestWrapper, data, MAX_IO_SIZE, MAX_OBJ_NUM);
203     }
204     ProxyInvokeArgInner(&requestWrapper, header);
205     if (request != NULL) {
206         if (!IpcIoAppend(&requestWrapper, request)) {
207             HILOG_ERROR(HILOG_MODULE_SAMGR, "ipc io append fail\n");
208             free(data);
209             return EC_INVALID;
210         }
211     }
212     int ret = SendRequest(header->target, funcId, &requestWrapper, &reply, flag, (uintptr_t *)&replyBuf);
213     free(data);
214 
215     if (notify != NULL) {
216         notify(owner, ret, &reply);
217     }
218 
219     if (replyBuf != NULL) {
220         FreeBuffer(replyBuf);
221     }
222     return ret;
223 }
224 
OnServiceExit(void * argv)225 static void OnServiceExit(void *argv)
226 {
227     IClientHeader *header = (IClientHeader *)argv;
228     ReleaseSvc(header->target);
229     header->deadId = INVALID_INDEX;
230     header->target.handle = INVALID_INDEX;
231     header->target.token = INVALID_INDEX;
232     header->target.cookie = INVALID_INDEX;
233     HILOG_ERROR(HILOG_MODULE_SAMGR, "Miss the remote service<%d>!", header->target.handle);
234 }
235 
QueryIdentity(const char * service,const char * feature)236 static SvcIdentity QueryIdentity(const char *service, const char *feature)
237 {
238     IpcIo req;
239     uint8 data[MAX_DATA_LEN];
240     SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
241     IpcIoInit(&req, data, MAX_DATA_LEN, 0);
242     WriteInt32(&req, 0);
243     WriteUint32(&req, RES_FEATURE);
244     WriteUint32(&req, OP_GET);
245     WriteString(&req, service);
246     WriteBool(&req, feature == NULL);
247     if (feature != NULL) {
248         WriteString(&req, feature);
249     }
250     IpcIo reply;
251     void *replyBuf = NULL;
252     const SvcIdentity *samgr = GetContextObject();
253     if (samgr == NULL) {
254         return target;
255     }
256     MessageOption flag;
257     MessageOptionInit(&flag);
258     int ret = SendRequest(*samgr, INVALID_INDEX, &req, &reply, flag, (uintptr_t *)&replyBuf);
259     int32_t saRet = EC_FAILURE;
260     ret = (ret != EC_SUCCESS) ? EC_FAILURE : ReadInt32(&reply, &saRet);
261     if (saRet == EC_SUCCESS) {
262         ReadRemoteObject(&reply, &target);
263         uint32_t token;
264         ReadUint32(&reply, &token);
265         target.token = (uintptr_t)token;
266     }
267     if (ret == EC_PERMISSION) {
268         HILOG_INFO(HILOG_MODULE_SAMGR, "Cannot Access<%s, %s> No Permission!", service, feature);
269     }
270     if (replyBuf != NULL) {
271         FreeBuffer(replyBuf);
272     }
273     return target;
274 }
275 
QueryRemoteIdentity(const char * deviceId,const char * service,const char * feature)276 static SvcIdentity QueryRemoteIdentity(const char *deviceId, const char *service, const char *feature)
277 {
278     return QueryRemoteIdentityInner(deviceId, service, feature);
279 }
280