1 /*
2 * Copyright (c) 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 <threads.h>
16 #include <pthread.h>
17 #include "ipc_skeleton.h"
18 #include "rpc_log.h"
19 #include "lite_ipc.h"
20 #include "serializer_inner.h"
21
22 #define IPC_IO_RETURN_IF_FAIL(value) \
23 do { \
24 if (!(value)) { \
25 RPC_LOG_ERROR("IPC_ASSERT_ERR: [%s:%d]\n", __FUNCTION__, __LINE__); \
26 if (io != NULL) { \
27 io->flag |= IPC_IO_OVERFLOW; \
28 } \
29 return NULL; \
30 } \
31 } while (0)
32
33 thread_local uintptr_t g_objectStub = NULL;
34
GetObjectStub(uintptr_t cookie)35 uintptr_t GetObjectStub(uintptr_t cookie)
36 {
37 if (cookie != NULL) {
38 g_objectStub = cookie;
39 }
40 return g_objectStub;
41 }
42
IoPushSpecObj(IpcIo * io)43 static SpecialObj* IoPushSpecObj(IpcIo* io)
44 {
45 IPC_IO_RETURN_IF_FAIL(io != NULL);
46 IPC_IO_RETURN_IF_FAIL(io->offsetsCur != NULL);
47 SpecialObj* ptr = IoPush(io, sizeof(SpecialObj));
48 if ((ptr != NULL) && io->offsetsLeft) {
49 io->offsetsLeft--;
50 *(io->offsetsCur) = (char*)ptr - io->bufferBase;
51 io->offsetsCur++;
52 return ptr;
53 } else {
54 io->flag |= IPC_IO_OVERFLOW;
55 return NULL;
56 }
57 }
58
IoPopSpecObj(IpcIo * io)59 static SpecialObj* IoPopSpecObj(IpcIo* io)
60 {
61 IPC_IO_RETURN_IF_FAIL(io != NULL);
62 IPC_IO_RETURN_IF_FAIL(io->offsetsCur != NULL);
63 if ((io->offsetsLeft == 0) || (*(io->offsetsCur) != io->bufferCur - io->bufferBase)) {
64 goto ERROR;
65 }
66
67 SpecialObj* obj = IoPop(io, sizeof(SpecialObj));
68 if (obj != NULL) {
69 io->offsetsCur++;
70 io->offsetsLeft--;
71 return obj;
72 }
73
74 ERROR:
75 io->flag |= IPC_IO_OVERFLOW;
76 return NULL;
77 }
78
AddList(IpcObjectStub * stub,uint32_t * token,IpcCallback * ipcCallback)79 static int32_t AddList(IpcObjectStub *stub, uint32_t *token, IpcCallback *ipcCallback)
80 {
81 int32_t ret = -1;
82 pthread_mutex_lock(&ipcCallback->mutex);
83 static uint32_t index = 0;
84 AnonymousApi *anonymousApi = (AnonymousApi *)malloc(sizeof(AnonymousApi));
85 if (anonymousApi == NULL) {
86 RPC_LOG_ERROR("anonymousApi malloc failed");
87 pthread_mutex_unlock(&ipcCallback->mutex);
88 return ret;
89 }
90 *token = index++;
91 anonymousApi->token = *token;
92 ret = memcpy_s((char *)&anonymousApi->hdlerPair, sizeof(IpcObjectStub), stub, sizeof(IpcObjectStub));
93 if (ret == 0) {
94 UtilsListAdd(&ipcCallback->apis, &anonymousApi->list);
95 pthread_mutex_unlock(&ipcCallback->mutex);
96 return ret;
97 }
98 RPC_LOG_ERROR("anonymousApi memcpy_s failed");
99 free(anonymousApi);
100 anonymousApi = NULL;
101 pthread_mutex_unlock(&ipcCallback->mutex);
102 return ret;
103 }
104
WriteRemoteObject(IpcIo * io,const SvcIdentity * svc)105 bool WriteRemoteObject(IpcIo *io, const SvcIdentity *svc)
106 {
107 if (io == NULL) {
108 return false;
109 }
110 if (svc == NULL) {
111 io->flag |= IPC_IO_OVERFLOW;
112 return false;
113 }
114 SpecialObj* ptr = IoPushSpecObj(io);
115 if (ptr == NULL) {
116 return false;
117 }
118 ptr->type = OBJ_SVC;
119 ptr->content.svc.handle = svc->handle;
120 ptr->content.svc.token = svc->token;
121 ptr->content.svc.cookie = svc->cookie;
122 if (ptr->content.svc.handle != IPC_INVALID_HANDLE) {
123 return true;
124 }
125 IpcObjectStub *stub = (IpcObjectStub *)ptr->content.svc.cookie;
126 if (ptr->content.svc.token == SERVICE_TYPE_NORMAL) {
127 g_objectStub = stub;
128 } else if (ptr->content.svc.token == SERVICE_TYPE_ANONYMOUS) {
129 IpcCallback *ipcCallback = GetIpcCb();
130 uint32_t token;
131 int32_t ret = AddList(stub, &token, ipcCallback);
132 if (ret != 0) {
133 RPC_LOG_ERROR("Add list failed.");
134 return false;
135 }
136 ptr->content.svc.token = token;
137 if (!ipcCallback->threadWorking) {
138 pthread_mutex_lock(&ipcCallback->mutex);
139 ret = StartCallbackDispatch();
140 if (ret < 0) {
141 RPC_LOG_ERROR("WriteRemoteObject StartCallbackDispatch failed.");
142 pthread_mutex_unlock(&ipcCallback->mutex);
143 return false;
144 }
145 pthread_mutex_unlock(&ipcCallback->mutex);
146 }
147 ptr->content.svc.handle = GetThreadId();
148 }
149 return true;
150 }
151
ReadRemoteObject(IpcIo * io,SvcIdentity * svc)152 bool ReadRemoteObject(IpcIo *io, SvcIdentity *svc)
153 {
154 SpecialObj* ptr = IoPopSpecObj(io);
155 if (ptr == NULL || ptr->type != OBJ_SVC) {
156 return false;
157 } else {
158 *svc = ptr->content.svc;
159 WaitForProxyInit(svc);
160 return true;
161 }
162 }
163
WriteFileDescriptor(IpcIo * io,uint32_t fd)164 bool WriteFileDescriptor(IpcIo *io, uint32_t fd)
165 {
166 SpecialObj* ptr = IoPushSpecObj(io);
167 if (ptr != NULL) {
168 ptr->type = OBJ_FD;
169 ptr->content.fd = fd;
170 return true;
171 }
172 return false;
173 }
174
ReadFileDescriptor(IpcIo * io)175 int32_t ReadFileDescriptor(IpcIo *io)
176 {
177 SpecialObj* ptr = IoPopSpecObj(io);
178 if (ptr == NULL || ptr->type != OBJ_FD) {
179 return -1;
180 } else {
181 return ptr->content.fd;
182 }
183 }
184