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