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