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