Add license file
[platform/upstream/csf-framework.git] / framework / IpcClient.c
1 /*
2     Copyright (c) 2014, McAfee, Inc.
3     
4     All rights reserved.
5     
6     Redistribution and use in source and binary forms, with or without modification,
7     are permitted provided that the following conditions are met:
8     
9     Redistributions of source code must retain the above copyright notice, this list
10     of conditions and the following disclaimer.
11     
12     Redistributions in binary form must reproduce the above copyright notice, this
13     list of conditions and the following disclaimer in the documentation and/or other
14     materials provided with the distribution.
15     
16     Neither the name of McAfee, Inc. nor the names of its contributors may be used
17     to endorse or promote products derived from this software without specific prior
18     written permission.
19     
20     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23     IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29     OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /**
33  * \file IpcClient.c
34  * \brief Ipc Client Source File
35  *  
36  * This file implements the IPC Client API functions used by Security framework.
37  */
38
39 #include <dbus/dbus.h>
40 #include <stdbool.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46
47 #include "Debug.h"
48 #include "IpcClient.h"
49 #include "IpcStructs.h"
50 #include "TSCErrorCodes.h"
51
52 static DBusHandlerResult _IpcClientMsgFilter(DBusConnection *dbconn, DBusMessage *dbmsg, void *data);
53 static bool _IpcClientInit(IpcClientInfo *pInfo);
54 static void _IpcClientDeInit(IpcClientInfo *pInfo);
55 static void _IpcHandleAsyncReply(DBusPendingCall *pPendingCall, void *pThreadData);
56 static void _free_str_array(char*** arr, int size);
57
58 /**
59  * Initializes and returns handle to client side IPC.
60  */
61 TSC_IPC_HANDLE IpcClientOpen(void)
62 {
63     IpcClientInfo *pInfo = NULL;
64     pInfo = calloc(1, sizeof(IpcClientInfo));
65     if (pInfo == NULL)
66         return NULL;
67
68     snprintf(pInfo->pid, TSC_REQ_STR_LEN, "%d", getpid());
69     snprintf(pInfo->req_name, TSC_REQ_STR_LEN, "%s%d", TSC_DBUS_CLIENT, getpid());
70
71     // Init Dbus Client
72     if (!_IpcClientInit(pInfo))
73         goto err_conn;
74
75     return (TSC_IPC_HANDLE)pInfo;
76
77 err_conn:
78     if (pInfo)
79         free(pInfo);
80
81     return INVALID_IPC_HANDLE;
82 }
83
84 /**
85  * Close the client-side IPC and release the resources.
86  */
87 void IpcClientClose(TSC_IPC_HANDLE hIpc)
88 {
89     if (hIpc == INVALID_IPC_HANDLE)
90         return;
91
92     IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
93     _IpcClientDeInit(pInfo);
94     free(pInfo);
95 }
96
97 /**
98  * Gives the prefix for the unique id of message sent.
99  */
100 char *_GetMsgIdPrefix(void)
101 {
102     char szIdPrefix[MSGHANDLE_LEN] = {0};
103     if (snprintf(szIdPrefix, MSGHANDLE_LEN, TSC_MID_PREFIX_FORMAT, getpid(), pthread_self()) >= 0)
104         return strdup(szIdPrefix);
105
106     return NULL;
107 }
108
109 /**
110  * Requests the Security framework's IPC server and returns back the reply.
111  */
112 int TSCSendMessageN(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod, int argc,
113                     char **argv, int *argc_reply, char ***argv_reply, int timeout_milliseconds)
114 {
115     IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
116     DBusMessage *dbmsg = NULL;
117     DBusMessage *reply_msg = NULL;
118     DBusMessageIter dbiter;
119     DBusError dberr;
120     char *pArgItem = NULL;
121     char *pBuf = NULL;
122     int i = 0;
123     int j = 0;
124     int iErr = TSC_ERROR_MODULE_GENERIC;
125     int iSize = TSC_REPLY_MSG_COUNT_AVERAGE;
126
127     *argc_reply = 0;
128
129     // TODO: Avoid multiple exits.
130     if (pInfo == NULL)
131         return TSC_ERROR_INVALID_HANDLE;
132
133     if (pInfo->dbconn == NULL)
134         return TSC_ERROR_INVALID_HANDLE;
135
136     if (argc < 0 || !szMethod)
137         return TSC_ERROR_INVALID_PARAM;
138
139     *argv_reply = malloc(iSize * sizeof(char *));
140     if (!*argv_reply)
141     {
142         iErr = TSC_ERROR_INSUFFICIENT_RES;
143         goto err_send;
144     }
145
146     dbus_error_init(&dberr);
147
148     dbmsg = dbus_message_new_method_call(service_name, TSC_DBUS_PATH, TSC_DBUS_INTERFACE, szMethod);
149     if (dbmsg == NULL)
150     {
151         iErr = TSC_ERROR_INSUFFICIENT_RES;
152         goto err_send;
153     }
154     dbus_message_iter_init_append(dbmsg, &dbiter);
155
156     // Add the message unique id as first element (the prefix).
157     char *szIdPrefix = _GetMsgIdPrefix();
158     if (!szIdPrefix || !dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &szIdPrefix))
159     {
160         DDBG("client_lib: Failed to append id prefix for %s.\n", szMethod);
161         free(szIdPrefix);
162         goto err_send;
163     }
164     free(szIdPrefix);
165     for (i = 0; i < argc; i++)
166     {
167         if (!dbus_validate_utf8(argv[i], &dberr))
168         {
169             DDBG("%s", "client_lib: Not valid utf8 string\n");
170             goto err_send;
171         }
172         if (!dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &argv[i]))
173         {
174             DDBG("client_lib: %s failed to append arguments\n", pInfo->pid);
175             goto err_send;
176         }
177     }
178
179     if (timeout_milliseconds == 0)
180         timeout_milliseconds = DBUS_TIMEOUT_INFINITE;
181
182     reply_msg = dbus_connection_send_with_reply_and_block(pInfo->dbconn, dbmsg, 
183                                                           timeout_milliseconds,
184                                                           &dberr);
185
186     if (reply_msg == NULL && dbus_error_is_set(&dberr))
187     {
188         DDBG("client_lib: Failed to end %s\n", dberr.message);
189         goto err_send;
190     }
191
192     if (reply_msg == NULL)
193     {
194         DDBG("%s\n", "client_lib: reply message is NULL");
195         goto err_send;
196     }
197
198     j = 0;
199     if (!dbus_message_iter_init(reply_msg, &dbiter))
200     {
201         DDBG("%s\n", "client_lib: Message has no arguments.");
202         goto zero_args;
203     }
204
205     do
206     {
207         if (dbus_message_iter_get_arg_type(&dbiter) != DBUS_TYPE_STRING)
208         {
209             DDBG("client_lib: %s argument is not string\n", pInfo->pid);
210             goto err_send;
211         }
212
213         dbus_message_iter_get_basic(&dbiter, &pArgItem);
214         if (!pArgItem)
215         {
216             DDBG("client_lib: %s arg is NULL\n", pInfo->pid);
217             goto err_send;
218         }
219
220         if (!(pBuf = strdup((const char*)pArgItem)))
221         {
222             goto err_send;
223         }
224         (*argv_reply)[j++] = pBuf;
225
226         if (j >= iSize)
227         {
228             iSize += TSC_REPLY_MSG_COUNT_AVERAGE;
229             *argv_reply = realloc(*argv_reply, sizeof(char*) * iSize);
230             if (!*argv_reply)
231             {
232                 goto err_send;
233             }
234         }
235     } while (dbus_message_iter_has_next(&dbiter) && dbus_message_iter_next(&dbiter));
236
237 zero_args:
238     *argc_reply = j;
239     return 0;
240
241 err_send:
242     if (*argv_reply)
243     {
244         while (j)
245             free((*argv_reply)[--j]);
246
247         free(*argv_reply);
248         *argv_reply = NULL;
249     }
250     if (dbmsg)
251         dbus_message_unref(dbmsg);
252     if(reply_msg)
253         dbus_message_unref(reply_msg);
254
255     return -1;
256 }
257
258 /**
259  * Block current thread till message is sent and structure is updated in child thread.
260  */
261 void BlockTillSent(SharedData *pSharedData)
262 {
263     pthread_mutex_lock(&pSharedData->lock);
264     while (pSharedData->iSent == 0)
265         pthread_cond_wait(&pSharedData->cond, &pSharedData->lock);
266     pthread_mutex_unlock(&pSharedData->lock);
267 }
268
269 /**
270  * Unblock parent thread as the message structures have been updated.
271  * Unblocks only 1 thread associated with the condition variable.
272  * Broadcast avoided as only waiting thread is expected.
273  */
274 void UnblockOnSent(SharedData *pSharedData)
275 {
276     pthread_mutex_lock(&pSharedData->lock);
277     pSharedData->iSent = 1;
278     pthread_cond_signal(&pSharedData->cond);
279     pthread_mutex_unlock(&pSharedData->lock);
280 }
281
282 /**
283  * Creates a thread for asynchronous task.
284  * TODO: Merge with TCS module.
285  */
286 int _RunDetachedThread(void *pfWorkerFunc, void *pThreadData)
287 {
288     pthread_t thread;
289     pthread_attr_t attr;
290
291     int rc = -1;
292     do
293     {
294         if (pthread_attr_init(&attr) != 0)
295             break;
296
297         if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
298             break;
299
300         if (pthread_create(&thread, &attr, pfWorkerFunc, pThreadData) != 0)
301             break;
302
303         if (pthread_attr_destroy(&attr) != 0)
304         {
305             // As the thread is already running, return different error code.
306             rc = -2;
307             break;
308         }
309
310         rc = 0;
311     }
312     while (0);
313
314     return rc;
315 }
316
317 void *_SendMessageWorker(void *pData)
318 {
319     dbus_bool_t result;
320     DBusPendingCall *pPendingCall = NULL;
321     ThreadData *pThreadData = (ThreadData *) pData;
322     ThreadData *pPendingData = NULL;
323     int iSentFailed = 1;
324
325     do
326     {
327         if (pThreadData == NULL)
328         {
329             DDBG("%s\n", "Nothing to send from thread. Deadlock!!");
330             break;
331         }
332
333         // Duplicate the User data to create the pending User data.
334         pPendingData = _AllocThreadData(NULL, DEF_TIMEOUT, NULL, pThreadData->pCallBack,
335                                         pThreadData->pPrivate);
336         if (pPendingData == NULL)
337         {
338             DDBG("%s\n", "Duplicating user data in thread failed. Deadlock!!");
339             break;
340         }
341
342         // Ownership of pThreadData remains with 'parent' thread.
343         result = dbus_connection_send_with_reply(pThreadData->pConn, pThreadData->pSharedData->pMsg,
344                                                  &pPendingCall, pThreadData->timeout_milliseconds);
345         if (!result || !pPendingCall)
346         {
347             DDBG("%s\n", "client_lib: SendAsync failed.");
348             break;
349         }
350
351         if (!pPendingData->pCallBack)
352             dbus_pending_call_cancel(pPendingCall);
353         else
354             dbus_pending_call_set_notify(pPendingCall, _IpcHandleAsyncReply, pPendingData,
355                                          _FreeThreadData);
356
357         // Set the values for parent thread to allow cancellation or further async action if needed.
358         if (_CreateClientCallHandle(&pThreadData->pSharedData->pCallHandle,
359                                     pThreadData->pSharedData->szCallHandlePrefix,
360                                     dbus_message_get_serial(pThreadData->pSharedData->pMsg),
361                                     pPendingCall) != 0)
362         {
363             dbus_pending_call_cancel(pPendingCall);
364             break;
365         }
366
367         UnblockOnSent(pThreadData->pSharedData);
368         // WARNING: Do not use pThreadData beyond this point, as parent thread may destroy it.
369
370         dbus_pending_call_block(pPendingCall);
371
372         iSentFailed = 0;
373     }
374     while(0);
375
376     if (iSentFailed && pThreadData)
377     {
378         DDBG("%s\n", "Error in send messsage worker. Unblocking..");
379         UnblockOnSent(pThreadData->pSharedData);
380     }
381
382     DDBG("%s\n", "Finished send message worker.");
383     return NULL;
384 }
385
386
387 /**
388  * Requests the Security framework's IPC server asynchronously.
389  */
390 int TSCSendMessageAsync(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod,
391                         int argc, char **argv, TSC_CALL_HANDLE *phCallHandle, TSCCallback pCallback,
392                         void *pPrivate, int timeout_milliseconds)
393 {
394     DDBG("%s %s\n", "sendmessage async ", service_name);
395     IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
396     DBusMessage *pMsg = NULL;
397     DBusMessageIter dbiter;
398     DBusError dberr;
399     ThreadData *pThreadData = NULL;
400     int i = 0;
401     int iErr = TSC_ERROR_MODULE_GENERIC;
402
403     // TODO: Avoid multiple exits.
404     if (pInfo == NULL)
405         return TSC_ERROR_INVALID_HANDLE;
406
407     if (pInfo->dbconn == NULL)
408         return TSC_ERROR_INVALID_HANDLE;
409
410     if (argc < 0 || !szMethod)
411         return TSC_ERROR_INVALID_PARAM;
412
413     dbus_error_init(&dberr);
414     pMsg = dbus_message_new_method_call(service_name, TSC_DBUS_PATH, TSC_DBUS_INTERFACE, szMethod);
415
416     if (pMsg == NULL)
417     {
418         iErr = TSC_ERROR_INSUFFICIENT_RES;
419         goto err_send;
420     }
421
422     dbus_message_iter_init_append(pMsg, &dbiter);
423
424     // Add the message unique id as first element (the prefix).
425     char *szIdPrefix = _GetMsgIdPrefix();
426     if (!szIdPrefix || !dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &szIdPrefix))
427     {
428         DDBG("client_lib: Failed to append id prefix for %s.\n", szMethod);
429         free(szIdPrefix);
430         goto err_send;
431     }
432
433     for (i = 0; i < argc; i++)
434     {
435         if (!dbus_validate_utf8(argv[i], &dberr))
436         {
437             DDBG("%s", "client_lib: Not valid utf8 string\n");
438             goto err_send;
439         }
440         if (!dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &argv[i]))
441         {
442             DDBG("client_lib: %s failed to append arguments\n", pInfo->pid);
443             goto err_send;
444         }
445     }
446
447     // Reply is discarded and not sent back to client, if no callback available.
448     if (!pCallback)
449         dbus_message_set_no_reply(pMsg, TRUE);
450
451     SharedData *pSharedData = _CreateSharedData(szIdPrefix, pMsg);
452     free(szIdPrefix);
453
454     if (!pSharedData)
455     {
456         iErr = TSC_ERROR_INSUFFICIENT_RES;
457         goto err_send;
458     }
459
460     if (timeout_milliseconds == 0)
461         timeout_milliseconds = DBUS_TIMEOUT_INFINITE;
462
463     pThreadData = _AllocThreadData(pInfo->dbconn, timeout_milliseconds, pSharedData, pCallback,
464                                    pPrivate);
465     if (!pThreadData)
466     {
467         _FreeSharedData(pSharedData);
468         iErr = TSC_ERROR_INSUFFICIENT_RES;
469         goto err_send;
470     }
471
472     // Assert that the message is ready to be used.
473     if (pThreadData->pSharedData->iSent)
474     {
475         DDBG("%s\n", "client_lib: Sent flag already set!!");
476         goto err_send;
477     }
478
479     DDBG("Before sending: %d\n", dbus_message_get_serial(pMsg));
480     if (_RunDetachedThread(_SendMessageWorker, pThreadData) == -1)
481     {
482         DDBG("%s\n", "client_lib: Running thread failed!!");
483         goto err_send;
484     }
485
486     BlockTillSent(pThreadData->pSharedData);
487     DDBG("After sending: %d\n", dbus_message_get_serial(pMsg));
488
489     if (phCallHandle)
490     {
491         *phCallHandle = (TSC_CALL_HANDLE)pThreadData->pSharedData->pCallHandle;
492         //TODO: should add here
493         DDBG("method unique  id :%s\n", ((ClientCallHandle*) phCallHandle)->idUnique);
494         strncpy(pThreadData->pSharedData->pCallHandle->service_name, service_name, TSC_SERVER_NAME_LEN);
495     }
496     else
497     {
498         // The caller does not want to call special methods (cancel, get progress) later.
499         _FreeClientCallHandle(pThreadData->pSharedData->pCallHandle);
500         pThreadData->pSharedData->pCallHandle = NULL;
501     }
502
503     iErr = 0;
504
505 err_send:
506     if (pMsg)
507         dbus_message_unref(pMsg);
508
509     if (pThreadData)
510         _FreeThreadData(pThreadData);
511
512     return iErr;
513 }
514
515 /**
516  * Releases the asynchronous call handle.
517  */
518 void TSCFreeSentMessageHandle(TSC_CALL_HANDLE hCallHandle)
519 {
520     _FreeClientCallHandle((ClientCallHandle *)hCallHandle);
521 }
522
523 /**
524  * Callback when reply is received from IPC server for asynchronous method call.
525  */
526 static void _IpcHandleAsyncReply(DBusPendingCall *pPendingCall, void *pThreadData)
527 {
528     int i = 0;
529     int argc = 0;
530     char **argv = NULL;
531     char *pBuf = NULL;
532     char *pArgItem = NULL;
533     DBusError dberr;
534     DBusMessageIter dbiter;
535     DBusMessage *pMsg = NULL;
536     int iErr = TSC_ERROR_MODULE_GENERIC;
537     int iSize = TSC_REPLY_MSG_COUNT_AVERAGE;
538     ThreadData *pData = (ThreadData *)pThreadData;
539
540     argv = malloc(iSize * sizeof(char *));
541     if (!argv)
542     {
543         iErr = TSC_ERROR_INSUFFICIENT_RES;
544         goto reply_err;
545     }
546
547     dbus_error_init(&dberr);
548
549     pMsg = dbus_pending_call_steal_reply(pPendingCall);
550     if (pMsg == NULL)
551     {
552         DDBG("%s\n", "client_lib: reply message is NULL");
553         goto reply_err;
554     }
555
556     i = 0;
557     if (!dbus_message_iter_init(pMsg, &dbiter))
558     {
559         DDBG("%s\n", "client_lib: Async reply has no arguments");
560         goto reply_err;
561     }
562
563     do
564     {
565         if (dbus_message_iter_get_arg_type(&dbiter) != DBUS_TYPE_STRING)
566         {
567             DDBG("%s\n", "client_lib: Reply argument is not string");
568             goto reply_err;
569         }
570
571         dbus_message_iter_get_basic(&dbiter, &pArgItem);
572         if (!pArgItem)
573         {
574             DDBG("%s\n", "client_lib: Failed getting string arg from reply");
575             goto reply_err;
576         }
577
578         if (!(pBuf = strdup((const char*)pArgItem)))
579         {
580             goto reply_err;
581         }
582         argv[i++] = pBuf;
583
584         if (i >= iSize)
585         {
586             iSize += TSC_REPLY_MSG_COUNT_AVERAGE;
587             argv = realloc(argv, sizeof(char*) * iSize);
588             if (!argv)
589             {
590                 goto reply_err;
591             }
592         }
593     } while (dbus_message_iter_has_next(&dbiter) && dbus_message_iter_next(&dbiter));
594
595     argc = i;
596     // Continue passing the returned values to callback.
597     goto forward_reply;
598
599 reply_err:
600     // Reset values being returned.
601     _free_str_array(&argv, i);
602
603 forward_reply:
604     if(pMsg)
605         dbus_message_unref(pMsg);
606     if (pPendingCall)
607         dbus_pending_call_unref(pPendingCall);
608
609     if (pData && pData->pCallBack)
610         (*(pData->pCallBack))(pData->pPrivate, argc, (const char**)argv);
611
612     _free_str_array(&argv, i);
613
614     DDBG("%s\n", "client_lib: Async Reply Completed.");
615 }
616
617
618 /**
619  * Cancels an asynchronous request previously made to the Security framework's IPC server.
620  * On success, releases the handle of the previously called asynchronous method.
621  */
622 int TSCCancelMessage(TSC_IPC_HANDLE hIpc, TSC_CALL_HANDLE hCallHandle)
623 {
624     IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
625     ClientCallHandle *pCallHandle = (ClientCallHandle *)hCallHandle;
626     char *argv_req[1];
627     int iResult = -1;
628
629     do
630     {
631         DDBG("%s\n", "client_lib: CANCELing.");
632         if (!pInfo || !pCallHandle)
633             break;
634
635         DDBG("%s\n", "prepare cancel");
636         // Cancel the message call locally.
637         dbus_pending_call_cancel(pCallHandle->pPendingCall);
638
639         // Now request the server to abort the running of the method.
640         argv_req[0] = pCallHandle->idUnique;
641         DDBG("cancel method unique id:%s\n", argv_req[0]);
642         //TODO: need change here for cancel message
643
644         TSC_CALL_HANDLE handle = NULL;
645         iResult = TSCSendMessageAsync((TSC_IPC_HANDLE)pInfo, pCallHandle->service_name,
646                                       TSC_FN_CANCELMETHOD, 1, argv_req, &handle, NULL, NULL,
647                                       DEF_TIMEOUT);
648         DDBG("%s\n", "client_lib: Sent Cancel to server.");
649
650         if (iResult == 0)
651         {
652             _FreeClientCallHandle(pCallHandle);
653         }
654
655     } while (0);
656
657     return iResult;
658 }
659
660 static DBusHandlerResult _IpcClientMsgFilter(DBusConnection *dbconn, DBusMessage *dbmsg, void *data)
661 {
662     IpcClientInfo *info = (IpcClientInfo*) data;
663     if (dbus_message_is_signal(dbmsg, DBUS_INTERFACE_LOCAL, "Disconnected"))
664     {
665         DDBG("client_lib: %s disconnected by signal\n", info->pid);
666         info->dbconn = NULL;
667         return DBUS_HANDLER_RESULT_HANDLED;
668     }
669
670     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
671 }
672
673 static bool _IpcClientInit(IpcClientInfo *pInfo)
674 {
675     if (!pInfo)
676         return false;
677
678     DBusError dberr;
679     int ret;
680
681     if (!dbus_threads_init_default())
682     {
683         DDBG("failed dbus_threads_init_default %s\n", "");
684         goto err;
685     }
686
687     dbus_error_init(&dberr);
688
689
690     if (pInfo->dbconn != NULL)
691         return false;
692
693     pInfo->dbconn = dbus_bus_get(DBUS_BUS_SYSTEM, &dberr);
694
695     if (pInfo->dbconn == NULL && dbus_error_is_set(&dberr))
696     {
697         DDBG("client_lib: %s error in get connection %s\n", pInfo->pid, dberr.message);
698         goto err_get;
699     }
700
701     if (!pInfo->dbconn)
702     {
703         DDBG("client_lib: %s get connection is NULL\n", pInfo->pid);
704         goto err_get;
705     }
706
707     dbus_connection_set_exit_on_disconnect(pInfo->dbconn, false);
708
709     if (!dbus_connection_add_filter(pInfo->dbconn, _IpcClientMsgFilter, pInfo, NULL))
710     {
711         DDBG("client_lib: %s failed to add filter %s\n", pInfo->pid, dberr.message);
712         goto err_get;
713     }
714
715     ret = dbus_bus_request_name(pInfo->dbconn, pInfo->req_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
716
717     if (ret == -1 && dbus_error_is_set(&dberr))
718     {
719         DDBG("client_lib: %s failed to request name %s\n", pInfo->pid, dberr.message);
720         goto err_get;
721     }
722
723     if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
724     {
725         DDBG("client_lib: %s failed, it is not primary owner %d\n", pInfo->req_name, ret);
726         goto err_get;
727     }
728
729     dbus_error_free(&dberr);
730     return  true;
731
732 err_get:
733     if (pInfo->dbconn)
734     {
735         dbus_connection_unref(pInfo->dbconn);
736         pInfo->dbconn = NULL;
737     }
738     dbus_error_free(&dberr);
739
740 err:
741     return false;
742 }
743
744 static void _IpcClientDeInit(IpcClientInfo *pInfo)
745 {
746     if (!pInfo)
747         return;
748
749     DBusError dberr;
750     int ret;
751
752     if (!pInfo->dbconn)
753         return;
754
755     dbus_error_init(&dberr);
756     ret = dbus_bus_release_name(pInfo->dbconn, pInfo->req_name, &dberr);
757
758     if (ret == -1 && dbus_error_is_set(&dberr))
759         DDBG("client_lib: %s failed to release name %s\n", pInfo->pid, dberr.message);
760
761     dbus_error_free(&dberr);
762
763     dbus_connection_remove_filter(pInfo->dbconn, _IpcClientMsgFilter, pInfo);
764     dbus_connection_unref(pInfo->dbconn);
765     pInfo->dbconn = NULL;
766 }
767
768 /**
769  * Release all the elements of the array and assign it to NULL.
770  */
771 static void _free_str_array(char*** arr, int size)
772 {
773     if (arr)
774     {
775         char **sArr = *arr;
776         if (sArr && *sArr)
777         {
778             while (size)
779                 free(sArr[--size]);
780
781             free(sArr);
782             *arr = NULL;
783         }
784     }
785 }