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
16 #include "ipc_invoker.h"
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <pthread.h>
20 #include <threads.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/ioctl.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <sys/syscall.h>
27 #include <unistd.h>
28 #include "rpc_errno.h"
29 #include "rpc_log.h"
30 #include "lite_ipc.h"
31 #include "ipc_types.h"
32 #include "ipc_process_skeleton.h"
33
34 #define MAX_SA_SIZE (0x100)
35 #define LITEIPC_VERSION_MIN_REQUIRE (2)
36 uint32_t g_threadId = 0;
37 static RemoteInvoker g_ipcInvoker;
38
39 typedef struct {
40 int32_t fd;
41 size_t mmapSize;
42 void *mmapAddr;
43 } IpcConnector;
44
45 static IpcConnector *g_connector = NULL;
46 static pthread_mutex_t g_connectorMutex = PTHREAD_MUTEX_INITIALIZER;
47
48 IpcCallback g_ipcCallback = {
49 .mutex = PTHREAD_MUTEX_INITIALIZER,
50 .handleId = IPC_INVALID_HANDLE,
51 .threadWorking = false
52 };
53
InitIpcCallback(void)54 static inline void InitIpcCallback(void)
55 {
56 UtilsListInit(&g_ipcCallback.apis);
57 }
58
OpenDriver(void)59 static IpcConnector *OpenDriver(void)
60 {
61 IpcConnector *connector = (IpcConnector *)malloc(sizeof(IpcConnector));
62 if (connector == NULL) {
63 RPC_LOG_ERROR("liteipc malloc failed: %d.", errno);
64 return NULL;
65 }
66 connector->fd = open(LITEIPC_DRIVER, O_RDWR);
67 if (connector->fd < 0) {
68 RPC_LOG_ERROR("liteipc open failed error : %d.", errno);
69 goto OPEN_ERR;
70 }
71 connector->mmapAddr = mmap(NULL, MMAP_MAX_SIZE, PROT_READ, MAP_PRIVATE, connector->fd, 0);
72 if (connector->mmapAddr == MAP_FAILED) {
73 RPC_LOG_ERROR("liteipc mmap failed: %d.", errno);
74 goto MMAP_ERR;
75 }
76 connector->mmapSize = MMAP_MAX_SIZE;
77 InitIpcCallback();
78 IpcVersion version;
79 int ret = ioctl(connector->fd, IPC_GET_VERSION, &version);
80 if (ret != 0) {
81 RPC_LOG_ERROR("liteipc get version failed error : %d.\n", ret);
82 goto VERSION_ERR;
83 }
84
85 uint16_t major = (version.driverVersion) & 0xffff;
86 uint16_t minor = (version.driverVersion >> 16) & 0xffff;
87 if (major < LITEIPC_VERSION_MIN_REQUIRE) {
88 RPC_LOG_ERROR("liteipc outdated version: %d.%d\n", major, minor);
89 goto VERSION_ERR;
90 }
91 return connector;
92
93 VERSION_ERR:
94 MMAP_ERR:
95 close(connector->fd);
96 OPEN_ERR:
97 free(connector);
98 return NULL;
99 }
100
CloseDriver(void)101 static void CloseDriver(void)
102 {
103 if (g_connector == NULL) {
104 return;
105 }
106 pthread_mutex_lock(&g_connectorMutex);
107 munmap(g_connector->mmapAddr, g_connector->mmapSize);
108 close(g_connector->fd);
109 free(g_connector);
110 g_connector = NULL;
111 pthread_mutex_unlock(&g_connectorMutex);
112 }
113
AcquireHandle(int32_t handle)114 static int32_t AcquireHandle(int32_t handle)
115 {
116 return ERR_NONE;
117 }
118
ReleaseHandle(int32_t handle)119 static int32_t ReleaseHandle(int32_t handle)
120 {
121 return ERR_NONE;
122 }
123
IpcFreeBuffer(void * buffer)124 static int32_t IpcFreeBuffer(void *buffer)
125 {
126 if (buffer == NULL) {
127 RPC_LOG_ERROR("Invalid parameter, null pointer: %d.", errno);
128 return ERR_INVALID_PARAM;
129 }
130 if (g_connector == NULL) {
131 RPC_LOG_ERROR("liteipc driver not init");
132 return ERR_IPC_SKELETON_NOT_INIT;
133 }
134
135 IpcContent content = {
136 .flag = BUFF_FREE,
137 .buffToFree = buffer
138 };
139 return ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
140 }
141
IpcIoInitFromMsg(IpcIo * io,const IpcMsg * msg)142 static void IpcIoInitFromMsg(IpcIo *io, const IpcMsg *msg)
143 {
144 if ((io == NULL) || (msg == NULL)) {
145 return;
146 }
147 io->bufferCur = io->bufferBase = (char *)(intptr_t)msg->data;
148 io->offsetsCur = io->offsetsBase = (size_t *)(intptr_t)(msg->offsets);
149 io->bufferLeft = msg->dataSz;
150 io->offsetsLeft = msg->spObjNum;
151 io->flag = IPC_IO_INITIALIZED;
152 }
153
IpcIoAvailable(IpcIo * io)154 static bool IpcIoAvailable(IpcIo *io)
155 {
156 bool ret = false;
157 if (io != NULL) {
158 ret = (io->flag & IPC_IO_INITIALIZED) && !(io->flag & IPC_IO_OVERFLOW);
159 }
160 return ret;
161 }
162
CheckIpcIo(IpcIo * data)163 static int32_t CheckIpcIo(IpcIo *data)
164 {
165 uint32_t totalSize;
166
167 if (data == NULL) {
168 return ERR_NONE;
169 }
170
171 if ((IpcIoAvailable(data) == false) || (data->bufferCur == NULL) || (data->bufferBase == NULL) ||
172 (data->offsetsCur == NULL) ||(data->offsetsBase == NULL) ||
173 ((intptr_t)data->bufferBase < (intptr_t)data->offsetsCur)) {
174 return ERR_INVALID_PARAM;
175 }
176
177 totalSize = data->bufferCur - data->bufferBase + ((char*)data->offsetsCur - (char*)data->offsetsBase);
178 if (totalSize > MAX_IO_SIZE) {
179 RPC_LOG_ERROR("IpcIo data too big, please use IpcIoPushDataBuff to push big data, error: %d.", errno);
180 return ERR_FAILED;
181 }
182 return ERR_NONE;
183 }
184
SendReply(IpcMsg * ipcMsg,IpcIo * reply)185 static void SendReply(IpcMsg *ipcMsg, IpcIo *reply)
186 {
187 int32_t ret;
188
189 if (ipcMsg == NULL) {
190 RPC_LOG_ERROR("Invalid parameter, null pointer.");
191 return;
192 }
193
194 ret = CheckIpcIo(reply);
195 if (ret != ERR_NONE) {
196 RPC_LOG_ERROR("CheckIpcIo failed,ret = %d.", ret);
197 return;
198 }
199
200 if (g_connector == NULL) {
201 RPC_LOG_ERROR("liteipc driver not init");
202 return;
203 }
204 IpcMsg out = {
205 .type = MT_REPLY,
206 .target.handle = ipcMsg->taskID,
207 .code = ipcMsg->code,
208 .flag = ipcMsg->flag,
209 .timestamp = ipcMsg->timestamp,
210 .dataSz = reply->bufferCur - reply->bufferBase,
211 .data = (void *)reply->bufferBase,
212 .offsets = reply->offsetsBase,
213 .spObjNum = ((char *)reply->offsetsCur - (char *)reply->offsetsBase) / sizeof(size_t)
214 };
215 IpcContent content = {
216 .flag = SEND | BUFF_FREE,
217 .outMsg = &out,
218 .buffToFree = ipcMsg
219 };
220
221 ret = ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
222 if (ret < 0) {
223 RPC_LOG_ERROR("Liteipc driver ioctl failed: %d.", errno);
224 }
225 }
226
SendFailedReply(IpcMsg * ipcMsg)227 static void SendFailedReply(IpcMsg *ipcMsg)
228 {
229 int32_t ret;
230
231 if (ipcMsg == NULL) {
232 RPC_LOG_ERROR("Invalid parameter, null pointer.");
233 return;
234 }
235
236 if (g_connector == NULL) {
237 RPC_LOG_ERROR("liteipc driver not init");
238 return;
239 }
240
241 IpcMsg out = {
242 .type = MT_FAILED_REPLY,
243 .target.handle = ipcMsg->taskID,
244 .code = ipcMsg->code,
245 .flag = ipcMsg->flag,
246 .timestamp = ipcMsg->timestamp,
247 .dataSz = 0,
248 .data = NULL,
249 .offsets = NULL,
250 .spObjNum = 0
251 };
252 IpcContent content = {
253 .flag = SEND | BUFF_FREE,
254 .outMsg = &out,
255 .buffToFree = ipcMsg
256 };
257
258 ret = ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
259 if (ret < 0) {
260 RPC_LOG_ERROR("Liteipc driver ioctl failed: %d.", errno);
261 }
262 }
263
264
CallDeathCallback(IpcMsg * ipcMsg)265 static void CallDeathCallback(IpcMsg *ipcMsg)
266 {
267 IpcSkeleton *ipcSkeleton = GetCurrentSkeleton();
268 if (ipcSkeleton == NULL) {
269 RPC_LOG_ERROR("GetCurrentSkeleton return null");
270 return;
271 }
272 DeathCallback *node = NULL;
273 RPC_LOG_INFO("<thread>for each list");
274 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &ipcSkeleton->objects, DeathCallback, list)
275 {
276 RPC_LOG_INFO("SendObituary node->handle: %d, ipcMsg->target.token: %d", node->handle, ipcMsg->target.token);
277 if (node->handle == ipcMsg->target.token) {
278 SendObituary(node);
279 break;
280 }
281 }
282 }
283
CallIpcCallback(IpcMsg * ipcMsg,HdlerArg * hdlerArg)284 static void CallIpcCallback(IpcMsg *ipcMsg, HdlerArg *hdlerArg)
285 {
286 for (uint32_t i = 0; i < hdlerArg->num; i++) {
287 if (hdlerArg->useFlag == false) {
288 continue;
289 }
290 ThreadContext *threadContext = GetCurrentThreadContext();
291 const pid_t oldPid = threadContext->callerPid;
292 const pid_t oldUid = threadContext->callerUid;
293 threadContext->callerPid = ipcMsg->processID;
294 threadContext->callerUid = (pid_t)ipcMsg->userID;
295 MessageOption option = {
296 .flags = ipcMsg->flag,
297 .args = hdlerArg->cbs[i].args
298 };
299 IpcIo reply;
300 uint8 tempData[MAX_IO_SIZE];
301 IpcIoInit(&reply, tempData, MAX_IO_SIZE, MAX_OBJ_NUM);
302 int32_t error = OnRemoteRequestInner(ipcMsg->code, &hdlerArg->io, &reply, option, &hdlerArg->cbs[i]);
303 if (error < 0) {
304 RPC_LOG_ERROR("OnRemoteRequestInner failed, error = %d", error);
305 }
306 if (!(ipcMsg->flag & TF_OP_ASYNC)) {
307 SendReply(ipcMsg, &reply);
308 } else {
309 IpcFreeBuffer((void *)ipcMsg);
310 }
311 threadContext->callerPid = oldPid;
312 threadContext->callerUid = oldUid;
313 }
314 free(hdlerArg);
315 }
316
CallbackBatchHandler(HdlerArg * hdlerArg)317 static void *CallbackBatchHandler(HdlerArg *hdlerArg)
318 {
319 pthread_detach(pthread_self());
320 IpcMsg *ipcMsg = (IpcMsg *)hdlerArg->msg;
321 switch (ipcMsg->type) {
322 case MT_DEATH_NOTIFY:
323 CallDeathCallback(ipcMsg);
324 break;
325 case MT_REQUEST:
326 CallIpcCallback(ipcMsg, hdlerArg);
327 break;
328 default:
329 RPC_LOG_ERROR("ipcMsg type unknow.");
330 break;
331 }
332 return NULL;
333 }
334
GetDeathCallback(IpcMsg * msg,HdlerArg * arg)335 static void GetDeathCallback(IpcMsg* msg, HdlerArg* arg)
336 {
337 if (pthread_mutex_lock(&g_ipcCallback.mutex) != 0) {
338 RPC_LOG_ERROR("Get callback mutex failed.");
339 return;
340 }
341 arg->msg = msg;
342 arg->num = MAX_DEATH_CALLBACK_NUM;
343 (void)pthread_mutex_unlock(&g_ipcCallback.mutex);
344 }
345
GetIpcCallback(IpcMsg * msg,HdlerArg * arg)346 static void GetIpcCallback(IpcMsg* msg, HdlerArg* arg)
347 {
348 if (pthread_mutex_lock(&g_ipcCallback.mutex) != 0) {
349 RPC_LOG_ERROR("Get callback mutex failed.");
350 return;
351 }
352 IpcIoInitFromMsg(&arg->io, msg);
353 arg->msg = msg;
354
355 AnonymousApi* node = NULL;
356 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcCallback.apis, AnonymousApi, list)
357 {
358 if (node->token == msg->target.token) {
359 arg->num = 1;
360 arg->useFlag = true;
361 arg->cbs = &node->hdlerPair;
362 (void)pthread_mutex_unlock(&g_ipcCallback.mutex);
363 return;
364 }
365 }
366 arg->num = 0;
367 arg->useFlag = false;
368 arg->cbs = NULL;
369 (void)pthread_mutex_unlock(&g_ipcCallback.mutex);
370 }
371
CallbackDispatchLoop(void)372 static void CallbackDispatchLoop(void)
373 {
374 while (1) {
375 IpcContent content = {.flag = RECV};
376 sched_yield();
377 int32_t ret = ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
378 if (ret < 0) {
379 continue;
380 }
381
382 HdlerArg *tArg = (HdlerArg *)malloc(sizeof(HdlerArg));
383 if (tArg == NULL) {
384 goto ERROR_MALLOC;
385 }
386 IpcMsg *ipcMsg = content.inMsg;
387 switch (ipcMsg->type) {
388 case MT_DEATH_NOTIFY:
389 GetDeathCallback(ipcMsg, tArg);
390 break;
391 case MT_REQUEST:
392 GetIpcCallback(ipcMsg, tArg);
393 break;
394 default:
395 RPC_LOG_ERROR("Callback thread received an unrecognized message.(type=%d)", ipcMsg->type);
396 goto ERROR_MSG;
397 }
398 if (tArg->num == 0) {
399 RPC_LOG_ERROR("failed tArg->num = 0");
400 goto ERROR_MSG;
401 }
402
403 pthread_t tid;
404 ret = pthread_create(&tid, NULL, CallbackBatchHandler, tArg);
405 if (ret == 0) {
406 continue;
407 }
408 RPC_LOG_ERROR("Create handle thread failed.");
409
410 ERROR_MSG:
411 free(tArg);
412 ERROR_MALLOC:
413 if ((ipcMsg->type == MT_REQUEST) && (ipcMsg->flag == TF_OP_SYNC)) {
414 SendFailedReply(ipcMsg);
415 } else {
416 IpcFreeBuffer((void *)ipcMsg);
417 }
418 }
419 }
420
CallbackDispatch(void)421 static void *CallbackDispatch(void)
422 {
423 if (g_connector == NULL) {
424 RPC_LOG_ERROR("liteipc driver not init");
425 return NULL;
426 }
427
428 int32_t ret = ioctl(g_connector->fd, IPC_SET_IPC_THREAD, 0);
429 g_threadId = syscall(SYS_gettid);
430 g_ipcCallback.handleId = ret;
431 g_ipcCallback.threadWorking = true;
432 CallbackDispatchLoop();
433 g_ipcCallback.threadWorking = false;
434 return NULL;
435 }
436
GetIpcCb(void)437 IpcCallback *GetIpcCb(void)
438 {
439 return &g_ipcCallback;
440 }
441
GetThreadId(void)442 uint32_t GetThreadId(void)
443 {
444 return g_threadId;
445 }
446
StartCallbackDispatch(void)447 int32_t StartCallbackDispatch(void)
448 {
449 if (!g_ipcCallback.threadWorking) {
450 pthread_attr_t threadAttr;
451 pthread_attr_init(&threadAttr);
452 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
453
454 pthread_t tid;
455 int32_t ret = pthread_create(&tid, &threadAttr, CallbackDispatch, NULL);
456 if (ret != 0) {
457 RPC_LOG_ERROR("Create callback dispatch thread failed.");
458 return ERR_FAILED;
459 }
460
461 struct timespec spark, now;
462 clock_gettime(CLOCK_REALTIME, &spark);
463 sched_yield();
464 while (!g_ipcCallback.threadWorking) {
465 clock_gettime(CLOCK_REALTIME, &now);
466 if (now.tv_sec - spark.tv_sec > 1) {
467 RPC_LOG_INFO("Wait callback thread starting timeout.");
468 return ERR_FAILED;
469 }
470 sched_yield();
471 }
472 return ERR_NONE;
473 }
474 return ERR_NONE;
475 }
476
IpcJoinThreadLoop(void)477 static void IpcJoinThreadLoop(void)
478 {
479 IpcObjectStub *objectStub = (IpcObjectStub *)GetObjectStub(0);
480 if (objectStub == NULL) {
481 RPC_LOG_INFO("objectStub is NULL.");
482 return;
483 }
484 while (1) {
485 IpcContent content = {.flag = RECV};
486 int32_t ret = ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
487 if (ret < 0) {
488 RPC_LOG_ERROR("ioctl request fail.");
489 continue;
490 }
491 IpcMsg *ipcMsg = content.inMsg;
492 ThreadContext *threadContext = GetCurrentThreadContext();
493 const pid_t oldPid = threadContext->callerPid;
494 const pid_t oldUid = threadContext->callerUid;
495 threadContext->callerPid = ipcMsg->processID;
496 threadContext->callerUid = (pid_t)ipcMsg->userID;
497
498 IpcIo data, reply;
499 IpcIoInitFromMsg(&data, ipcMsg);
500 uint8 tempData[MAX_IO_SIZE];
501 IpcIoInit(&reply, tempData, MAX_IO_SIZE, MAX_OBJ_NUM);
502 MessageOption option = {
503 .flags = ipcMsg->flag,
504 .args = objectStub->args
505 };
506 int32_t error = OnRemoteRequestInner(ipcMsg->code, &data, &reply, option, objectStub);
507 if (error < 0) {
508 RPC_LOG_ERROR("OnRemoteRequestInner failed, error = %d", error);
509 }
510 if (!(ipcMsg->flag & TF_OP_ASYNC)) {
511 SendReply(ipcMsg, &reply);
512 } else {
513 IpcFreeBuffer((void *)ipcMsg);
514 }
515 threadContext->callerPid = oldPid;
516 threadContext->callerUid = oldUid;
517 }
518 }
519
IpcJoinThread(bool initiative)520 static void IpcJoinThread(bool initiative)
521 {
522 if (g_connector == NULL) {
523 RPC_LOG_ERROR("liteipc driver not init");
524 return;
525 }
526 IpcJoinThreadLoop();
527 }
528
IpcSetMaxWorkThread(int32_t maxThreadNum)529 static int32_t IpcSetMaxWorkThread(int32_t maxThreadNum)
530 {
531 return ERR_NONE;
532 }
533
IpcSetRegistryObject(SvcIdentity target,SvcIdentity * samgr)534 static int32_t IpcSetRegistryObject(SvcIdentity target, SvcIdentity *samgr)
535 {
536 (void)target;
537 (void)samgr;
538 if (g_connector == NULL) {
539 RPC_LOG_ERROR("liteipc driver not init");
540 return ERR_IPC_SKELETON_NOT_INIT;
541 }
542 int32_t ret = ioctl(g_connector->fd, IPC_SET_CMS, MAX_SA_SIZE);
543 if (ret == ERR_NONE) {
544 GetObjectStub(target.cookie);
545 RPC_LOG_INFO("set samgr success!!");
546 return ERR_NONE;
547 }
548 RPC_LOG_ERROR("set samgr failed");
549 return IPC_INVOKER_IOCTL_FAILED;
550 }
551
IpcSendRequest(SvcIdentity target,uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option,uintptr_t * buffer)552 static int32_t IpcSendRequest(SvcIdentity target, uint32_t code, IpcIo *data, IpcIo *reply,
553 MessageOption option, uintptr_t *buffer)
554 {
555 int32_t ret;
556
557 if ((option.flags > TF_OP_ASYNC) || ((option.flags == TF_OP_SYNC) && (buffer == NULL))) {
558 RPC_LOG_ERROR("Invalid parameter, null pointer.");
559 return ERR_INVALID_PARAM;
560 }
561
562 ret = CheckIpcIo(data);
563 if (ret != ERR_NONE) {
564 RPC_LOG_ERROR("CheckIpcIo failed.");
565 return ret;
566 }
567
568 if (g_connector == NULL) {
569 RPC_LOG_ERROR("liteipc driver not init");
570 return ERR_IPC_SKELETON_NOT_INIT;
571 }
572 IpcMsg msg = {
573 .type = MT_REQUEST,
574 .target = target,
575 .code = code,
576 .flag = option.flags,
577 .dataSz = (data == NULL) ? 0 : data->bufferCur - data->bufferBase,
578 .data = (data == NULL) ? NULL : data->bufferBase,
579 .offsets = (data == NULL) ? NULL : data->offsetsBase,
580 .spObjNum = (data == NULL) ? 0 : ((char *)data->offsetsCur - (char *)data->offsetsBase) / sizeof(size_t)
581 };
582
583 IpcContent content = {
584 .outMsg = &msg,
585 .flag = (option.flags == TF_OP_ASYNC) ? SEND : (SEND | RECV)
586 };
587
588 ret = ioctl(g_connector->fd, IPC_SEND_RECV_MSG, &content);
589 if (ret < 0) {
590 RPC_LOG_ERROR("send ioctl failed: %d.", errno);
591 return IPC_INVOKER_IOCTL_FAILED;
592 }
593
594 if (option.flags != TF_OP_ASYNC) {
595 if (reply != NULL) {
596 IpcIoInitFromMsg(reply, content.inMsg);
597 }
598 *buffer = (uintptr_t)content.inMsg;
599 }
600
601 return ret;
602 }
603
IpcAddDeathRecipient(int32_t handle,void * cookie)604 static int32_t IpcAddDeathRecipient(int32_t handle, void *cookie)
605 {
606 if (!g_ipcCallback.threadWorking) {
607 pthread_mutex_lock(&g_ipcCallback.mutex);
608 int32_t ret = StartCallbackDispatch();
609 if (ret < 0) {
610 RPC_LOG_ERROR("IpcAddDeathRecipient StartCallbackDispatch failed.");
611 pthread_mutex_unlock(&g_ipcCallback.mutex);
612 return false;
613 }
614 pthread_mutex_unlock(&g_ipcCallback.mutex);
615 }
616 return ERR_NONE;
617 }
618
IpcRemoveDeathRecipient(int32_t handle,void * cookie)619 static int32_t IpcRemoveDeathRecipient(int32_t handle, void *cookie)
620 {
621 return ERR_NONE;
622 }
623
IpcExitCurrentThread(void)624 static void IpcExitCurrentThread(void)
625 {
626 }
627
628 static IpcConnector *InitIpcConnector(void);
629
InvokerResetIpc(void)630 static void InvokerResetIpc(void)
631 {
632 if (g_connector != NULL) {
633 free(g_connector);
634 g_connector = NULL;
635 }
636
637 pthread_mutex_init(&g_connectorMutex, NULL);
638 g_ipcCallback.handleId = IPC_INVALID_HANDLE;
639 g_ipcCallback.threadWorking = false;
640 pthread_mutex_init(&(g_ipcCallback.mutex), NULL);
641
642 if (InitIpcConnector() == NULL) {
643 RPC_LOG_ERROR("init liteipc invoker failed: %d.", errno);
644 }
645 }
646
InitIpcConnector(void)647 static IpcConnector *InitIpcConnector(void)
648 {
649 if (g_connector == NULL) {
650 if (pthread_mutex_lock(&g_connectorMutex) != 0) {
651 RPC_LOG_ERROR("init liteipc connector lock failed: %d.", errno);
652 return NULL;
653 }
654 if (g_connector == NULL) {
655 IpcConnector *connector = OpenDriver();
656 if (connector == NULL) {
657 pthread_mutex_unlock(&g_connectorMutex);
658 RPC_LOG_ERROR("create liteipc connector failed: %d.", errno);
659 return NULL;
660 }
661 g_connector = connector;
662 g_ipcInvoker.connector = g_connector;
663 g_ipcInvoker.AcquireHandle = AcquireHandle;
664 g_ipcInvoker.ReleaseHandle = ReleaseHandle;
665 g_ipcInvoker.SendRequest = IpcSendRequest;
666 g_ipcInvoker.FreeBuffer = IpcFreeBuffer;
667 g_ipcInvoker.SetMaxWorkThread = IpcSetMaxWorkThread;
668 g_ipcInvoker.JoinThread = IpcJoinThread;
669 g_ipcInvoker.SetRegistryObject = IpcSetRegistryObject;
670 g_ipcInvoker.AddDeathRecipient = IpcAddDeathRecipient;
671 g_ipcInvoker.RemoveDeathRecipient = IpcRemoveDeathRecipient;
672 g_ipcInvoker.ExitCurrentThread = IpcExitCurrentThread;
673 g_ipcInvoker.InvokerResetIpc = InvokerResetIpc;
674 }
675 pthread_mutex_unlock(&g_connectorMutex);
676 }
677
678 return g_connector;
679 }
680
GetIpcInvoker(void)681 RemoteInvoker *GetIpcInvoker(void)
682 {
683 if (InitIpcConnector() == NULL) {
684 RPC_LOG_ERROR("init liteipc invoker failed: %d.", errno);
685 return NULL;
686 }
687
688 return &g_ipcInvoker;
689 }
690
DeinitIpcInvoker(RemoteInvoker * invoker)691 void DeinitIpcInvoker(RemoteInvoker *invoker)
692 {
693 if (invoker != &g_ipcInvoker) {
694 return;
695 }
696 CloseDriver();
697 }