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 }