5df1959b43808e5cd08359ad2b804584c5ee8aa7
[platform/core/system/libsyscommon.git] / src / libgdbus / dbus-system.c
1 /*
2  * libsyscommon
3  *
4  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <errno.h>
24 #include <string.h>
25
26 #include "shared/log.h"
27 #include "dbus-system.h"
28
29 /* 10 seconds */
30 #define DBUS_REPLY_TIMEOUT      (10000)
31
32 static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM;
33 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 void dbus_handle_set_default_bus_type(GBusType bus_type)
36 {
37         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION)
38                 return ;
39
40         pthread_mutex_lock(&g_mutex);
41         g_default_bus_type = bus_type;
42         pthread_mutex_unlock(&g_mutex);
43 }
44
45 GBusType dbus_handle_get_default_bus_type(void)
46 {
47         GBusType type;
48
49         pthread_mutex_lock(&g_mutex);
50         type = g_default_bus_type;
51         pthread_mutex_unlock(&g_mutex);
52
53         return type;
54 }
55
56 typedef struct {
57         const char *bus_name;
58         guint id;
59 } dbus_name;
60
61 /* basic information */
62 typedef struct {
63         GDBusConnection *conn;
64         GBusType bus_type;
65         gboolean priv;
66         GList *list_names;      /* dbus_name */
67         GList *list_object;     /* dbus_object_handle_s */
68         pthread_mutex_t mutex;
69 } dbus_handle_s;
70
71 /* path + interfaces */
72 typedef struct {
73         dbus_handle_s *dh;      /* dbus handle */
74         const char *path;       /* object path */
75         GList *list_ifaces;     /* dbus_interface_s */
76 } dbus_object_handle_s;
77
78 typedef struct {
79         dbus_object_handle_s *oh;       /* object handle */
80         const char *name;       /* interface name */
81         GList *list_methods;    /* const dbus_method_s */
82         guint reg_id;
83         int modified;
84 } dbus_interface_s;
85
86 #define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh
87
88 /* global shared bus : system, session */
89 static dbus_handle_s g_dh[2];
90
91 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type);
92
93 dbus_handle_s * _dbus_handle_get_default_connection(void)
94 {
95         return _dbus_handle_get_connection(dbus_handle_get_default_bus_type());
96 }
97
98 #define dbus_handle_lock(handle) do {\
99         assert(handle);\
100         pthread_mutex_lock(&((handle)->mutex));\
101 } while (0);
102
103 #define dbus_handle_unlock(handle) do {\
104         assert(handle);\
105         pthread_mutex_unlock(&(handle)->mutex);\
106 } while (0);
107
108 #define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle;
109 #define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\
110         if (!dh) {\
111         _E("dbus handle is null\n");\
112         return 0;\
113         }
114
115 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path);
116 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name);
117 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name);
118 static GVariant* _append_variant(const char *signature, const char *param[]);
119
120 dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u)
121 {
122         dbus_interface_s *iface = NULL;
123
124         if (!iface_u || !iface_u->methods) {
125                 _E("param is null");
126                 return NULL;
127         }
128
129         iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s));
130         if (!iface) {
131                 _E("failed to calloc");
132                 return NULL;
133         }
134
135         iface->name = iface_u->name;
136         iface->modified = TRUE;
137
138         for (int i = 0 ; i < iface_u->nr_methods; ++i) {
139                 //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func);
140                 iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i));
141         }
142
143         return iface;
144 }
145
146 static GDBusConnection * _get_bus(GBusType bus_type)
147 {
148         GDBusConnection *conn = NULL;
149         GError *err = NULL;
150
151         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
152                 _E("Wrong bus_type %d", bus_type);
153                 return NULL;
154         }
155
156         conn = g_bus_get_sync(bus_type, NULL, &err);
157         if (!conn || err) {
158                 _E("failed to get bus:type:%d, %s\n", bus_type, err->message);
159                 g_error_free(err);
160                 return NULL;
161         }
162
163         return conn;
164 }
165
166 static GDBusConnection * _get_bus_private(GBusType bus_type)
167 {
168         GError *err = NULL;
169         GDBusConnection *conn = NULL;
170         const char * address;
171
172         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
173                 _E("Wrong bus_type %d", bus_type);
174                 return NULL;
175         }
176
177         address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err);
178         if (!address || err) {
179                 _E("failed to get bus address\n");
180                 g_error_free(err);
181                 return NULL;
182         }
183
184         conn = g_dbus_connection_new_for_address_sync(address,
185                         (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
186                         G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
187                         NULL, /* GDBusAuthObserver */
188                         NULL,
189                         &err);
190         if (!conn || err) {
191                 _E("failed to get private bus\n");
192                 g_error_free(err);
193                 return NULL;
194         }
195
196         return conn;
197 }
198
199 /* ref cout is 1 */
200 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type)
201 {
202         int ibus = bus_type - 1;
203         dbus_handle_s *dh = NULL;
204
205         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
206                 _E("Unknown bus type %d", bus_type);
207                 return NULL;
208         }
209         dh = &g_dh[ibus];
210
211         dbus_handle_lock(dh);
212
213         if (!dh->conn) {
214                 dh->conn = _get_bus(bus_type);
215                 if (!dh->conn) {
216                         dbus_handle_unlock(dh);
217                         return NULL;
218                 }
219                 dh->priv = FALSE;
220                 dh->bus_type = bus_type;
221         }
222
223         dbus_handle_unlock(dh);
224
225         return dh;
226 }
227
228 /* ref cout is 1 */
229 static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type)
230 {
231         dbus_handle_s * dh;
232
233         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
234                 _E("Unknown bus type %d", bus_type);
235                 return NULL;
236         }
237
238         dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s));
239         if (!dh) {
240                 _E("failed to allocate memory for dbus handle");
241                 return NULL;
242         }
243
244         dbus_handle_lock(dh);
245
246         if (!dh->conn) {
247                 dh->conn = _get_bus_private(bus_type);
248                 dh->bus_type = bus_type;
249                 if (!dh->conn)
250                         goto err;
251         }
252
253         dbus_handle_unlock(dh);
254
255         return dh;
256 err:
257         if (dh) {
258                 dbus_handle_unlock(dh);
259                 free(dh);
260         }
261         return NULL;
262 }
263
264 dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv)
265 {
266         dbus_handle_s *dh = NULL;
267         int i;
268
269         if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
270                 _E("Wrong bus_type %d\n", bus_type);
271                 return dh;
272         }
273
274         for (i = 0 ; i < 3; ++i) {
275                 /* private */
276                 if (priv)
277                         dh = _dbus_handle_get_connection_private(bus_type);
278                 /* shared */
279                 else
280                         dh = _dbus_handle_get_connection(bus_type);
281
282                 if (dh)
283                         break;
284                 usleep(5000);
285         }
286
287         return dh;
288 }
289
290 static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id)
291 {
292         dbus_name *dn = NULL;
293         int locked = 0;
294
295         if (!handle || !name || !id)
296                 return ;
297
298         dn = (dbus_name*)calloc(1, sizeof(dbus_name));
299         if (!dn) {
300                 _E("failed to calloc");
301                 assert(0);
302         }
303         dn->bus_name = name;
304         dn->id = id;
305
306         // todo : delete lock ?
307         locked = pthread_mutex_trylock(&handle->mutex);
308         if (locked != 0 && locked != EBUSY) {
309                 _E("failed to lock %d\n", locked);
310                 assert(0);
311         }
312
313         handle->list_names = g_list_prepend(handle->list_names, dn);
314
315         // todo : delete lock ?
316         if (locked != EBUSY)
317                 dbus_handle_unlock(handle);
318 }
319
320 static gint _compare_dbus_name(gconstpointer a, gconstpointer b)
321 {
322         const char *bus_name = ((dbus_name *)a)->bus_name;
323         if (!bus_name || !b)
324                 return -1;
325         return strcmp(bus_name, (const char *)b);
326 }
327
328 dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name)
329 {
330         if (!list_name || !bus_name)
331                 return NULL;
332
333         GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name);
334         if (!item)
335                 return NULL;
336
337         return (dbus_name *)item->data;
338 }
339
340 #define dh_to_ds(x) ((dbus_handle_s*)x)
341
342 /* remove dbus_name from dbus handle */
343 static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name)
344 {
345         dcl_dbus_handle();
346         dbus_name *dn = NULL;
347
348         if (!bus_name) {
349                 _E("wrong bus_name is null");
350                 return ;
351         }
352         if (!dh) {
353                 dh = _dbus_handle_get_default_connection();
354                 if (!dh) {
355                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
356                         return ;
357                 }
358         }
359
360         dbus_handle_lock(dh);
361         dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
362         if (!dn) {
363                 _E("failed to find dbus name %s", bus_name);
364                 goto out;
365         }
366         dh->list_names = g_list_remove(dh->list_names, dn);
367         free(dn);
368 out:
369         dbus_handle_unlock(dh);
370 }
371
372 //extern void booting_done(void);
373
374 /* default handler */
375 static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
376 {
377         dbus_handle_s *dh = (dbus_handle_s *)user_data;
378
379         _D("name %s", name);
380
381         if (!dh) {
382                 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
383                 return ;
384         }
385
386         // todo: add bus name?
387         //dh->bus_name = name;
388 }
389
390 /* default handler */
391 static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
392 {
393         _E("%s:%d:%s\n", __func__, __LINE__, name);
394         dbus_handle_s *dh = (dbus_handle_s *)user_data;
395         if (!dh) {
396                 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
397                 return ;
398         }
399         _dbus_handle_remove_bus_name(dh, name);
400 }
401
402 int dbus_handle_request_bus_name(dbus_handle_h handle,
403                                 const char *bus_name,
404                                 GBusNameAcquiredCallback acquired_handler,
405                                 GBusNameLostCallback lost_handler)
406 {
407         dcl_dbus_handle();
408         int id = -1;
409         GList *item = NULL;
410
411         if (!bus_name) {
412                 _E("bus_name is NULL");
413                 return -1;
414         }
415
416         /* get shared connection */
417         if (!dh) {
418                 dh = _dbus_handle_get_default_connection();
419                 if (!dh) {
420                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
421                         return -1;
422                 }
423         }
424
425         dbus_handle_lock(dh);
426         if (!dh->conn) {
427                 _E("failed to register name: connection is null\n");
428                 goto out;
429         }
430
431         /* todo : search name on connection */
432         item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name);
433         if (item) {
434                 id = ((dbus_name*)(item->data))->id;
435                 _E("name already exist:%u", id);
436                 goto out;
437         }
438
439         id = g_bus_own_name_on_connection(dh->conn,
440                                         bus_name,
441                                         G_BUS_NAME_OWNER_FLAGS_NONE,
442                                         acquired_handler ? acquired_handler : _name_acquired,
443                                         lost_handler ? lost_handler : _name_lost,
444                                         dh,
445                                         NULL);
446         if (!id) {
447                 _E("failed to own name:%s\n", bus_name);
448                 goto out;
449         }
450
451         _dbus_handle_add_bus_name(dh, bus_name, id);
452
453 out:
454         dbus_handle_unlock(dh);
455         return id;
456 }
457
458 /* !! _name_lost handler callback is disabled by g_bus_unown_name : ubuntu */
459 int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name)
460 {
461         dcl_dbus_handle();
462         dbus_name *dn = NULL;
463
464         if (!bus_name) {
465                 _E("Wrong bus name");
466                 return -1;
467         }
468
469         if (!dh) {
470                 dh = _dbus_handle_get_default_connection();
471                 if (!dh) {
472                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
473                         return -1;
474                 }
475         }
476
477         dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
478         if (!dn) {
479                 _E("failed to find bus_name %s on dbus handle", bus_name);
480                 return -1;
481         }
482
483         _E("unown name %d", dn->id);
484         /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
485         g_bus_unown_name(dn->id);
486
487         dbus_handle_lock(dh);
488         dh->list_names = g_list_remove(dh->list_names, dn);
489         free(dn);
490         dbus_handle_unlock(dh);
491
492         return 0;
493 }
494
495 int dbus_handle_free_connection(dbus_handle_h handle)
496 {
497         dcl_dbus_handle();
498         dbus_handle_s *pdh = NULL;
499         GError *err = NULL;
500         GList *item = NULL;
501
502         if (!dh) {
503                 dh = _dbus_handle_get_default_connection();
504                 if (!dh) {
505                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
506                         return -1;
507                 }
508         }
509
510         if (!dh->conn) {
511                 _E("connection is NULL");
512                 return 0;
513         }
514
515         pdh = dh;
516
517         /* disable dbus handler */
518         dbus_handle_lock(dh);
519         if (!pdh->conn) {
520                 _E("conn is null");
521                 free(pdh);
522                 return 0;
523         }
524
525         /* flush everything */
526         if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) {
527                 _E("failed to flush %s\n", err->message);
528                 g_error_free(err);
529                 err = NULL;
530         }
531
532         _D("list_names %u", g_list_length(pdh->list_names));
533
534         /* unown every well-knwon name */
535         if (pdh->list_names) {
536                 dbus_name *dn = NULL;
537                 for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) {
538                         dn = (dbus_name *)item->data;
539                         if (!dn)
540                                 continue;
541
542                         /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
543                         _D("unown name id : %u", dn->id);
544                         g_bus_unown_name(dn->id);
545                         free(dn);
546                 }
547                 g_list_free(pdh->list_names);
548                 pdh->list_names = NULL;
549         }
550
551         _D("list_object %u", g_list_length(pdh->list_object));
552
553         /* unregister every object */
554         if (pdh->list_object) {
555                 dbus_object_handle_s * oh = NULL;
556                 //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data) {}, NULL);
557                 for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) {
558                         oh = (dbus_object_handle_s *)item->data;
559                         if (!oh || !oh->list_ifaces)
560                                 continue;
561
562                         _D("delete object path %s", oh->path);
563
564                         /* unregister every interface, method handles */
565                         for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) {
566                                 dbus_interface_s *ih = (dbus_interface_s *)iface->data;
567                                 if (!ih)
568                                         continue;
569
570                                 _D("delete object iface %s", ih->name);
571
572                                 if (ih->reg_id)
573                                         g_dbus_connection_unregister_object(pdh->conn, ih->reg_id);
574                         }
575                 }
576         }
577
578         /* close connection */
579         if (pdh->priv) {
580                 _E("close private connection\n");
581
582                 if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) {
583                         _E("Error closing connection %s\n", err->message);
584                         g_error_free(err);
585                         err = NULL;
586                 }
587         }
588
589         /* _free_func_object callback free the data */
590         //assert(g_list_length(pdh->list_names) == 0);
591         //assert(g_list_length(pdh->list_object) == 0);
592
593         g_object_unref(pdh->conn);
594
595         dbus_handle_unlock(dh);
596
597         if (dh->priv)
598                 free(dh);
599
600         return 0;
601
602         // todo: signal ?
603 }
604
605 #define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0)
606 #define buf_block_size 8192
607
608 #define buf_check_space_realloc(buf, nwrite, buf_len) do {\
609         if ((nwrite >= buf_len - 1024)) {\
610                 if (buf_len >= buf_block_size * 10) {\
611                         _E("buf is too big to allocate. %d", buf_len);\
612                 } else {\
613                         _E("buf_check_space_realloc");\
614                         char *tmp = NULL;\
615                         buf_len += buf_block_size;\
616                         tmp = (char *)realloc(buf, buf_len);\
617                         if (!tmp) {\
618                                 _E("failed to realloc");\
619                         } else\
620                                 buf = tmp;\
621                 } \
622         } \
623 } while (0);
624
625 /* cal index of end of brace */
626 static int _check_brace(const char * expr)
627 {
628         int len = 0;
629         char qu[128];
630         int qucnt = 0;
631
632         if (!expr)
633                 return -1;
634
635         len = strlen(expr);
636
637         if (expr[0] != '(' && expr[0] != '{')
638                 return -1;
639
640         for (int i = 0 ; i < len; ++i) {
641
642                 if (expr[i] == '(' || expr[i] == '{') {
643                         qu[qucnt++] = expr[i];
644                         if (qucnt >= sizeof(qu)) {
645                                 _E("queue is too large. %s", expr);
646                                 return -1;
647                         }
648                         continue;
649                 }
650
651                 if (expr[i] == ')' || expr[i] == '}') {
652                         char ch;
653
654                         if (qucnt > 0)
655                                 ch = qu[qucnt-1];
656                         else
657                                 return -1;
658
659                         if (expr[i] == ')') {
660                                 if (ch == '(')
661                                         --qucnt;
662                                 else
663                                         return -1;
664                         } else if (expr[i] == '}') {
665                                 if (ch == '{')
666                                         --qucnt;
667                                 else
668                                         return -1;
669                         } else
670                                 return -1;
671
672                         if (qucnt == 0)
673                                 return i + 1;
674                 }
675         }
676
677         return -1;
678 }
679
680 /*
681 in : interface_s
682 out : xml format
683 */
684 static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces)
685 {
686         int nwrite = 0;
687         int len_args;
688         char *buf = NULL;
689         const dbus_method_s *pmethod;
690         int buf_len = buf_block_size;
691
692         if (!interfaces) {
693                 _E("interfaces is null");
694                 return -1;
695         }
696
697         // todo : check dbus naming rule for interface name. ?
698         if (!interfaces->name) {
699                 _E("wrong interface name");
700                 return -1;
701         }
702         if (!interfaces->list_methods) {
703                 _E("no methods");
704                 return -1;
705         }
706
707         buf = (char *)malloc(buf_len);
708         if (!buf) {
709                 _E("buf is null. not enough memory\n");
710                 return -1;
711         }
712
713         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "<node>""\n""\t""<interface name='%s'>""\n", interfaces->name);
714
715         /* members */
716         for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) {
717                 pmethod = (const dbus_method_s *)item->data;
718                 if (!pmethod)
719                         continue;
720
721                 /* check free space of buf */
722                 buf_check_space_realloc(buf, nwrite, buf_len);
723
724                 if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) {
725                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'/>""\n", pmethod->member);
726                         continue;
727                 }
728
729                 /* <method name='###'> */
730                 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'>""\n", pmethod->member);
731
732                 /* in args */
733                 len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0;
734                 for (int m = 0; m < len_args; ++m) {
735                         // todo
736                         // array a(), as, ay ?
737                         if (pmethod->signature_in[m] == 'a') {
738                                 int ei; //end index
739                                 ei = _check_brace(pmethod->signature_in + m + 1);
740                                 if (ei > 0) {
741                                         char tmp[128] = {0,};
742                                         strncpy(tmp, pmethod->signature_in + m, ei + 1);
743                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='in'/>""\n", tmp, m);
744                                         m += ei;
745                                         continue;
746                                 } else {
747                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m);
748                                         m += 1;
749                                         continue;
750                                 }
751                         }
752                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], m);
753                 }
754
755                 /* out args */
756                 len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0;
757                 for (int m = 0; m < len_args; ++m) {
758                         // array
759                         // todo: container type
760                         if (pmethod->signature_out[m] == 'a') {
761                                 int ei; //end index
762                                 ei = _check_brace(pmethod->signature_out + m + 1);
763                                 if (ei > 0) {
764                                         char tmp[128] = {0,};
765                                         strncpy(tmp, pmethod->signature_out + m, ei + 1);
766                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='out'/>""\n", tmp, m);
767                                         m += ei;
768                                         continue;
769                                 } else {
770                                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m);
771                                         m += 1;
772                                         continue;
773                                 }
774                         }
775                         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], m);
776                 }
777
778                 /* </method> */
779                 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""</method>""\n");
780         }
781
782         nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""</interface>""\n""</node>""");
783
784         *xml = buf;
785
786         /* todo: delete log */
787 #if 0
788         if (nwrite <= 512)
789                 _E("%s", buf);
790         else
791                 _E("%s", buf + nwrite - 512);
792 #endif
793         return 0;
794 }
795
796 static gint _compare_dbus_object(gconstpointer a, gconstpointer b)
797 {
798         dbus_object_handle_s * pa = (dbus_object_handle_s *)a;
799         if (!pa->path || !((const char*)b))
800                 return -1;
801         return strcmp(pa->path, (const char*)b);
802 }
803
804 static gint _compare_dbus_interface(gconstpointer a, gconstpointer b)
805 {
806         dbus_interface_s * pa = (dbus_interface_s *)a;
807         if (!pa->name || !((const char*)b))
808                 return -1;
809         return strcmp(pa->name, (const char*)b);
810 }
811
812 static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b)
813 {
814         dbus_interface_s * pa = (dbus_interface_s *)a;
815         if (!pa->reg_id || !((guint*)b))
816                 return -1;
817         return !(pa->reg_id == *((guint*)b));
818 }
819
820 static gint _compare_dbus_method(gconstpointer a, gconstpointer b)
821 {
822         dbus_method_s *pa = (dbus_method_s*)a;
823         if (!pa->member || !((const char*)b))
824                 return -1;
825         return strcmp(pa->member, (const char*)b);
826 }
827
828 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path)
829 {
830         if (!list_obj || !obj_path)
831                 return NULL;
832
833         GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object);
834         if (!item)
835                 return NULL;
836
837         return (dbus_object_handle_s *)item->data;
838 }
839
840 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name)
841 {
842         if (!list_iface || !iface_name)
843                 return NULL;
844
845         GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface);
846         if (!item)
847                 return NULL;
848
849         return (dbus_interface_s *)item->data;
850 }
851
852 dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id)
853 {
854         if (!list_iface || !id)
855                 return NULL;
856
857         GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id);
858         if (!item)
859                 return NULL;
860
861         return (dbus_interface_s *)item->data;
862 }
863
864 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name)
865 {
866         if (!list_methods || !method_name)
867                 return NULL;
868
869         GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method);
870         if (!item)
871                 return NULL;
872
873         return (dbus_method_s *)item->data;
874 }
875
876 static void _free_func_object(gpointer data)
877 {
878         dbus_interface_s *ih = (dbus_interface_s *)data;
879         dbus_object_handle_s *oh = NULL;
880
881         if (!ih) {
882                 _E("interface handle is null");
883                 assert(0); // something wrong
884                 return ;
885         }
886
887         _E("unregister interface %s", ih->name);
888
889         /* just free list, not data(static dbus_method_s) */
890         g_list_free(ih->list_methods);
891
892         oh = ih->oh;
893         if (!oh) {
894                 _E("object handle is null");
895                 assert(0); // something wrong
896                 return ;
897         }
898
899         /* remove ih from list_ifaces */
900         oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
901
902         /* interface_s is copy of interface_u */
903         free(ih);
904
905         /* remove oh from list_object */
906         if (!oh->list_ifaces) {
907                 oh->dh->list_object = g_list_remove(oh->dh->list_object, oh);
908                 free(oh);
909         }
910 }
911
912 static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface)
913 {
914         dbus_object_handle_s *oh = NULL;
915
916         if (!dh || !obj_path || !iface) {
917                 _E("failed to attache object. wrong parameter");
918                 return -1;
919         }
920
921         /* find object handle */
922         if (dh->list_object)
923                 oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
924
925         if (!oh) {
926                 oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s));
927                 if (!oh) {
928                         _E("failed to calloc");
929                         return -1;
930                 }
931                 oh->dh = dh;
932                 oh->path = obj_path;
933
934                 /* attach object */
935                 dh->list_object = g_list_prepend(dh->list_object, oh);
936         }
937
938         iface->oh = oh;
939         /* attach interface */
940         oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface);
941
942         return 0;
943 }
944
945 /*
946 _method_call_handler
947
948 libgio verify path and interface of incoming message.
949 --> just check method name.
950
951 # parameters - member of invocation struct
952 every parameters of this function are member of GDBusMethodInvocation *invocation.
953 There are no reason to using g_dbus_method_invocation_get_* apis to get inforamtion from message.
954 just use params - sender, path, iface, name and param.
955
956
957 # user defined handler #
958
959 1. synchronous handling
960         1) with return value
961                 handler() {
962                         return g_variant_new("(i)", ret);
963                 }
964
965         2) without return value
966                 handler() {
967                         return dbus_handle_new_g_variant_tuple(); // g_variant_new_tuple(NULL, 0)
968                 }
969
970 2. asynchronous handling
971    handler MUST call 'g_dbus_method_invocation_return_value' itself. otherwise, LEAK !!
972
973         handler() {
974                 return NULL;
975         }
976
977         # if handler return NULL, assume asynchronous handling. do nothing.
978
979         thread() {
980                 do something;
981
982         1) with return value
983                 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
984
985         2) without return value
986                 g_dbus_method_invocation_return_value(invocation, NULL);
987         }
988
989
990 */
991 static void _method_call_handler(GDBusConnection *conn,
992                                 const gchar *sender,
993                                 const gchar *path,
994                                 const gchar *iface,
995                                 const gchar *name,
996                                 GVariant *param,
997                                 GDBusMethodInvocation *invocation,
998                                 gpointer user_data)
999 {
1000         dbus_interface_s *iface_s = (dbus_interface_s *)user_data;
1001         const dbus_method_s *methods;
1002         GVariant *result = NULL;
1003
1004         /* todo: ghash ? */
1005         methods = _dbus_handle_lookup_method(iface_s->list_methods, name);
1006         if (methods) {
1007                 result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh));
1008
1009                 /* async, maybe they will reply...maybe.. */
1010                 if (!result)
1011                         return;
1012         } else {
1013                 _E("no methods");
1014         }
1015
1016         g_dbus_method_invocation_return_value(invocation, result);
1017 }
1018
1019 static GDBusInterfaceVTable path_vtable = {_method_call_handler};
1020
1021
1022 /*
1023 before register object, attach object into dbus handle
1024 _dbus_handle_attach_object()
1025 */
1026 static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface)
1027 {
1028         dcl_dbus_handle();
1029         int ret = 0;
1030         char *buf = NULL;
1031         GError *err = NULL;
1032         GDBusNodeInfo * nodeinfo = NULL;
1033         GDBusInterfaceInfo *ifaceinfo = NULL;
1034
1035         if (!obj_path || !iface) {
1036                 _E("wrong parameter\n");
1037                 return -1;
1038         }
1039         if (!dh) {
1040                 dh = _dbus_handle_get_default_connection();
1041                 if (!dh) {
1042                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1043                         return -1;
1044                 }
1045         }
1046         if (!dh->conn) {
1047                 _E("connection is null\n");
1048                 return -1;
1049         }
1050
1051         ret = _get_xml_from_interfaces(&buf, iface);
1052         if (ret < 0) {
1053                 _E("failed to make xml format");
1054                 goto err;
1055         }
1056
1057         /* todo: delete this */
1058 #if 0
1059         if (strlen(buf) <= 512) {
1060                 _E("%s", buf);
1061         } else {
1062                 _E("%s", buf + strlen(buf) - 512);
1063         }
1064 #endif
1065
1066         nodeinfo = g_dbus_node_info_new_for_xml(buf, &err);
1067         if (!nodeinfo || err) {
1068                 _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf);
1069                 ret = -1;
1070                 goto err;
1071         }
1072
1073         ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name);
1074         if (!ifaceinfo) {
1075                 _E("failed to g_dbus_node_info_lookup_interface");
1076                 ret = -1;
1077                 goto err;
1078         }
1079
1080         /*
1081                 path own single interface
1082                 if interface is already registered, then failed.
1083                 g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered
1084         */
1085         ret = g_dbus_connection_register_object(dh->conn,
1086                                                 obj_path,
1087                                                 ifaceinfo/*ref 2*/,
1088                                                 &path_vtable,
1089                                                 (void*)iface,
1090                                                 _free_func_object,
1091                                                 &err);
1092         if (err) {
1093                 _E("failed to register object:err:%s:\n", err->message);
1094                 ret = -1;
1095                 goto err;
1096         }
1097
1098         iface->reg_id = ret;
1099         iface->modified = FALSE;
1100
1101 err:
1102         /* todo: detach object */
1103         //_dbus_handle_detach_object(dh, obj_path, iface);
1104         /* attach interface before register object */
1105         /*ret = _dbus_handle_detach_object(dh, obj_path, iface);
1106         if (ret < 0) {
1107                 _E("failed to attach object");
1108                 goto err;
1109         }*/
1110
1111         if (nodeinfo)
1112                 g_dbus_node_info_unref(nodeinfo);
1113         if (buf)
1114                 free(buf);
1115         if (err)
1116                 g_error_free(err);
1117
1118         return ret;
1119 }
1120
1121 /*
1122 register same interface at once
1123
1124 if interface is constructed by multiple methods,
1125 also it is not possible to make methods struct at once,
1126
1127 use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all().
1128
1129 return reg_id
1130 */
1131 int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1132 {
1133         dcl_dbus_handle();
1134         int ret = 0;
1135         dbus_interface_s *iface = NULL;
1136
1137         if (!obj_path || !iface_u) {
1138                 _E("wrong parameter\n");
1139                 return -1;
1140         }
1141         if (!dh) {
1142                 dh = _dbus_handle_get_default_connection();
1143                 if (!dh) {
1144                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1145                         return -1;
1146                 }
1147         }
1148         if (!dh->conn) {
1149                 _E("connection is null\n");
1150                 return -1;
1151         }
1152
1153         /* check registered interface */
1154         if (dh->list_object) {
1155                 dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1156                 if (oh) {
1157                         dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1158                         if (ih) {
1159                                 _E("path %s, interface %s already registered", obj_path, iface_u->name);
1160                                 return -1;
1161                         }
1162                 }
1163         }
1164
1165         iface = _iface_u_to_s(iface_u);
1166         if (!iface) {
1167                 _E("failed to _iface_u_to_s");
1168                 return -1;
1169         }
1170
1171         /* attach interface before register object */
1172         ret = _dbus_handle_attach_object(dh, obj_path, iface);
1173         if (ret < 0) {
1174                 _E("failed to attach object");
1175                 goto err;
1176         }
1177
1178         ret = _dbus_handle_register_dbus_object(dh, obj_path, iface);
1179         if (ret <= 0) {
1180                 _E("failed to register dbus object%d", ret);
1181                 goto err;
1182         }
1183 err:
1184         return ret;
1185 }
1186
1187 int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path)
1188 {
1189         dcl_dbus_handle();
1190         dbus_object_handle_s *oh = NULL;
1191         int ret = 0;
1192
1193         if (!obj_path)
1194                 return -1;
1195
1196         if (!dh) {
1197                 dh = _dbus_handle_get_default_connection();
1198                 if (!dh) {
1199                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1200                         return -1;
1201                 }
1202         }
1203         if (!dh->list_object) {
1204                 _E("list_object is empty");
1205                 return 0;
1206         }
1207
1208         oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1209         if (!oh) {
1210                 _E("no object with name %s", obj_path);
1211                 return -1;
1212         }
1213
1214         /* unregister every interface of object*/
1215         for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) {
1216                 dbus_interface_s *ih = item->data;
1217                 if (!ih) {
1218                         _E("this is error");
1219                         assert(0);
1220                 }
1221
1222                 /* remove ih from list_ifaces */
1223                 if (!ih->reg_id) {
1224                         item = g_list_previous(item);
1225
1226                         /* remove and free link */
1227                         oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
1228
1229                         /* free list_methods */
1230                         g_list_free(ih->list_methods);
1231
1232                         /* free data */
1233                         free(ih);
1234                         continue;
1235                 }
1236
1237                 /* unregister object by id */
1238                 ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id);
1239                 if (!ret)
1240                         _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id);
1241         }
1242
1243         return 0;
1244 }
1245
1246 /*
1247 add object temporarily.
1248 dbus_handle_register_dbus_object_all register every objects on connection.
1249
1250 return registered method count
1251 */
1252 int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1253 {
1254         dcl_dbus_handle();
1255         dbus_object_handle_s *oh = NULL;
1256         dbus_interface_s *ih = NULL;
1257         int cnt;
1258
1259         if (!obj_path || !iface_u) {
1260                 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1261                 return -1;
1262         }
1263         if (iface_u && (!iface_u->name || !iface_u->methods)) {
1264                 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1265                 return -1;
1266         }
1267
1268         cnt = iface_u->nr_methods;
1269
1270         if (!dh) {
1271                 dh = _dbus_handle_get_default_connection();
1272                 if (!dh) {
1273                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1274                         return -1;
1275                 }
1276         }
1277
1278         if (!dh->conn) {
1279                 _E("failed to register method. connection is null\n");
1280                 return -1;
1281         }
1282
1283         /* if there are no object list, just add */
1284         if (!dh->list_object) {
1285                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1286                         _E("failed to attach object");
1287                         return -1;
1288                 }
1289                 goto out;
1290         }
1291
1292         oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1293         /* if there are no matched object, just add */
1294         if (!oh) {
1295                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1296                         _E("failed to attach object");
1297                         return -1;
1298                 }
1299                 goto out;
1300         }
1301
1302         /* this is an error, interface must have one or more item ? */
1303         if (!oh->list_ifaces) {
1304                 _E("error. list_ifaces is null\n");
1305                 assert(0);
1306                 goto out;
1307         }
1308
1309         ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1310         /* if there are no matched interface, just add */
1311         if (!ih) {
1312                 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1313                         _E("failed to attach object");
1314                         return -1;
1315                 }
1316                 goto out;
1317         }
1318
1319         /*  todo:
1320                 1. unregister interface
1321                 2. update interface and methods
1322                 3. register interface
1323         */
1324         if (ih->reg_id) {
1325                 _E("interface already registered, ignore new interface");
1326                 return -1;
1327         }
1328
1329         /* attach new methods */
1330         cnt = 0;
1331         for (int i = 0; i < iface_u->nr_methods; ++i) {
1332                 GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method);
1333                 if (!item) {
1334                         //_D("attached %s", iface_u->methods[i].member);
1335                         ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i));
1336                         ++cnt;
1337                 }
1338         }
1339
1340         if (cnt)
1341                 ih->modified = TRUE;
1342
1343 out:
1344         /*todo: delete debugging log */
1345         //if (dh && dh->list_object)
1346         //      _D("obj list len %d", g_list_length(dh->list_object));
1347         //if (oh && oh->list_ifaces)
1348         //      _D("iface list len %d", g_list_length(oh->list_ifaces));
1349         //if (ih && ih->list_methods)
1350         //      _D("method list len %d", g_list_length(ih->list_methods));
1351
1352         return cnt;
1353 }
1354
1355 int dbus_handle_register_dbus_object_all(dbus_handle_h handle)
1356 {
1357         dcl_dbus_handle();
1358         dbus_object_handle_s *oh = NULL;
1359         dbus_interface_s *ih = NULL;
1360         int ret = 0;
1361
1362         if (!dh) {
1363                 dh = _dbus_handle_get_default_connection();
1364                 if (!dh) {
1365                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1366                         return -1;
1367                 }
1368         }
1369         if (!dh->conn) {
1370                 _E("connection is null\n");
1371                 return -1;
1372         }
1373
1374         if (!dh->list_object) {
1375                 _E("obj list is empty");
1376                 return -1;
1377         }
1378
1379         /*if (dh && dh->list_object)
1380                 _D("obj list len %d", g_list_length(dh->list_object));*/
1381
1382         for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) {
1383                 oh = (dbus_object_handle_s *)item->data;
1384
1385                 if (!oh) {
1386                         _E("something wrong");
1387                         assert(0);
1388                 }
1389                 if (!oh->list_ifaces) {
1390                         _E("path %s: list_ifaces are null", oh->path);
1391                         goto err;
1392                 }
1393
1394                 //_D("iface list len %d", g_list_length(oh->list_ifaces));
1395
1396                 for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) {
1397                         ih = (dbus_interface_s *)li->data;
1398
1399                         /* if there are no modification, goto next */
1400                         if (!ih->modified)
1401                                 continue;
1402
1403                         /* todo: if already registered interface, unregister first */
1404
1405                         /*_E("interface %s:", ih->name);
1406                         if (ih && ih->list_methods)
1407                                 _D("method list len %d", g_list_length(ih->list_methods));*/
1408
1409                         ret = _dbus_handle_register_dbus_object(dh, oh->path, ih);
1410                         if (ret <= 0)
1411                                 _E("failed to register dbus object%d", ret);
1412
1413                 }
1414         }
1415         return 0;
1416 err:
1417
1418         // todo: delete all updates
1419
1420         return -1;
1421 }
1422
1423 guint subscribe_dbus_signal(dbus_handle_h handle, const char *path,
1424                         const char *iface, const char *name,
1425                         GDBusSignalCallback cb, void *data,
1426                         destroy_notified free_func)
1427 {
1428         dcl_dbus_handle();
1429
1430         if (!dh) {
1431                 dh = _dbus_handle_get_default_connection();
1432                 if (!dh) {
1433                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1434                         return 0;
1435                 }
1436         }
1437
1438         if (!dh->conn) {
1439                 _E("connection is null. check bus status");
1440                 return 0;
1441         }
1442         return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, free_func);
1443 }
1444
1445 void unsubscribe_dbus_signal(dbus_handle_h handle, guint id)
1446 {
1447         dcl_dbus_handle();
1448         if (!dh) {
1449                 dh = _dbus_handle_get_default_connection();
1450                 if (!dh) {
1451                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1452                         return;
1453                 }
1454         }
1455
1456         if (!dh->conn) {
1457                 _E("connection is null. check bus status");
1458                 return;
1459         }
1460
1461         g_dbus_connection_signal_unsubscribe(dh->conn, id);
1462 }
1463
1464 static void _signal_reply_sync_cb(GDBusConnection  *conn,
1465         const gchar *sender,
1466         const gchar *path,
1467         const gchar *iface,
1468         const gchar *name,
1469         GVariant *param,
1470         gpointer data)
1471 {
1472         sig_ctx *ctx = data;
1473         if (!ctx) {
1474                 _E("user data is null");
1475                 assert(0);
1476         }
1477
1478         ctx->param = g_variant_ref(param);
1479         ctx->quit_reason = CTX_QUIT_NORMAL;
1480
1481         if (ctx->timeout_src) {
1482                 g_source_destroy(ctx->timeout_src);
1483                 ctx->timeout_src = NULL;
1484         }
1485         g_main_loop_quit(ctx->loop);
1486 }
1487
1488 sig_ctx *dbus_handle_new_signal_ctx(void)
1489 {
1490         sig_ctx *ctx;
1491
1492         ctx = (sig_ctx *)malloc(sizeof(sig_ctx));
1493         if (!ctx) {
1494                 _E("failed to alloc mem");
1495                 return NULL;
1496         }
1497
1498         ctx->sig_id = 0;
1499
1500         ctx->context = g_main_context_new();
1501         if (!ctx->context) {
1502                 _E("failed to alloc context");
1503                 free(ctx);
1504                 return NULL;
1505         }
1506         ctx->loop = g_main_loop_new(ctx->context, FALSE);
1507         if (!ctx->loop) {
1508                 _E("failed to alloc main loop");
1509                 g_main_context_unref(ctx->context);
1510                 free(ctx);
1511                 return NULL;
1512         }
1513         ctx->timeout_src = NULL;
1514         ctx->param = NULL;
1515         ctx->quit_reason = CTX_QUIT_UNKNOWN;
1516         ctx->user_data = NULL;
1517
1518         return ctx;
1519 }
1520
1521 void dbus_handle_free_signal_ctx(sig_ctx *ctx)
1522 {
1523         if (!ctx)
1524                 return ;
1525
1526         if (ctx->param) {
1527                 g_variant_unref(ctx->param);
1528                 ctx->param = NULL;
1529         }
1530         if (ctx->sig_id) {
1531                 unsubscribe_dbus_signal(NULL, ctx->sig_id);
1532                 ctx->sig_id = 0;
1533         }
1534         if (ctx->timeout_src) {
1535                 g_source_destroy(ctx->timeout_src);
1536                 ctx->timeout_src = NULL;
1537         }
1538         if (ctx->context) {
1539                 g_main_context_pop_thread_default(ctx->context);
1540                 g_main_context_unref(ctx->context);
1541                 ctx->context = NULL;
1542         }
1543         if (ctx->loop) {
1544                 g_main_loop_unref(ctx->loop);
1545                 ctx->loop = NULL;
1546         }
1547         free(ctx);
1548 }
1549
1550 static gboolean _cb_ctx_timeout(gpointer user_data)
1551 {
1552         sig_ctx *ctx = user_data;
1553
1554         if (!ctx) {
1555                 _E("user_data is null");
1556                 return FALSE;
1557         }
1558
1559         ctx->quit_reason = CTX_QUIT_TIMEOUT;
1560         /* if cb return FALSE, source will be destroyed */
1561         ctx->timeout_src = NULL;
1562
1563         unsubscribe_dbus_signal(NULL, ctx->sig_id);
1564         ctx->sig_id = 0;
1565
1566         g_main_loop_quit(ctx->loop);
1567
1568         return FALSE;
1569 }
1570
1571 #define CTX_MAX_TIMEOUT 25000
1572
1573 int dbus_handle_signal_ctx_add_timeout(sig_ctx *ctx, int timeout_msec)
1574 {
1575         GSource *src = NULL;
1576
1577         if (!ctx)
1578                 return -EINVAL;
1579         if (timeout_msec < -1)
1580                 return -EINVAL;
1581
1582         if (timeout_msec == -1 || timeout_msec >= CTX_MAX_TIMEOUT)
1583                 timeout_msec = CTX_MAX_TIMEOUT;
1584
1585         src = g_timeout_source_new(timeout_msec);
1586         if (!src)
1587                 return -ENOMEM;
1588
1589         g_source_set_callback(src, _cb_ctx_timeout, ctx, NULL);
1590         g_source_attach(src, ctx->context);
1591         g_source_unref(src);
1592
1593         ctx->timeout_src = src;
1594
1595         return 0;
1596 }
1597
1598 guint subscribe_dbus_signal_ctx(dbus_handle_h handle, sig_ctx *ctx,
1599                 const char *sender,     const char *path,
1600                 const char *iface, const char *name,
1601                 GDBusSignalCallback _cb)
1602 {
1603         dcl_dbus_handle();
1604
1605         if (!ctx) {
1606                 _E("wrong param ctx is null");
1607                 return 0;
1608         }
1609
1610         if (!dh) {
1611                 dh = _dbus_handle_get_default_connection();
1612                 if (!dh) {
1613                         _E("failed to get default connection, bustype:%d",
1614                                         (int)dbus_handle_get_default_bus_type());
1615                         return 0;
1616                 }
1617         }
1618
1619         if (!dh->conn) {
1620                 _E("connection is null. check bus status");
1621                 return 0;
1622         }
1623
1624         if (!_cb)
1625                 _cb = _signal_reply_sync_cb;
1626
1627         /* change context before subscribe */
1628         g_main_context_push_thread_default(ctx->context);
1629
1630         ctx->sig_id = g_dbus_connection_signal_subscribe(dh->conn,
1631                         sender, iface, name, path, NULL,
1632                         G_DBUS_SIGNAL_FLAGS_NONE, _cb,
1633                         (void*)ctx, NULL);
1634
1635         if (!ctx->sig_id)
1636                 _E("failed to subscribe signal");
1637
1638         return ctx->sig_id;
1639 }
1640
1641 int dbus_handle_signal_ctx_wait(sig_ctx *ctx)
1642 {
1643         if (!ctx || !ctx->loop)
1644                 return -EINVAL;
1645
1646         g_main_loop_run(ctx->loop);
1647
1648         _D("quit g_main_loop");
1649
1650         return ctx->quit_reason;
1651 }
1652
1653 int _check_type_string_is_container(const char *signature)
1654 {
1655         if (!signature)
1656                 return FALSE;
1657
1658         switch (signature[0]) {
1659         case 'a':
1660         case 'm':
1661         case 'r':
1662         case '(':
1663         case '{':
1664         case 'v':
1665                 return TRUE;
1666         default:
1667                 return FALSE;
1668         }
1669
1670         return TRUE;
1671 }
1672
1673 /* todo: looks like garbage... */
1674 static GVariant* _append_variant(const char *signature, const char *param[])
1675 {
1676         char *ch;
1677         int i;
1678         int pi;
1679         int int_type;
1680         gboolean bool_type;
1681         unsigned long long int64_type;
1682         GVariant *ret;
1683         int len;
1684         char container[255];// The maximum length of a signature is 255.
1685         const char *sig = signature;
1686         GVariantBuilder *builder = NULL;
1687
1688         if (!signature || !param)
1689                 return 0;
1690
1691         /* workaround for user fault "(i) != i" but we treat this as same signature */
1692         /* G_VARIANT_TYPE("si") return NULL */
1693         /* todo: actually user have to use correct signature */
1694         if (!_check_type_string_is_container(signature)) {
1695                 snprintf(container, sizeof(container) - 1, "(%s)", signature);
1696                 sig = container;
1697         }
1698         if (!g_variant_type_is_container(G_VARIANT_TYPE(sig)))
1699                 _E("signature (%s) is not container type", signature);
1700
1701         builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
1702         len = strlen(sig);
1703         pi = 0;
1704         for (ch = (char *)sig, i = 0; i < len; ++i, ++ch) {
1705                 switch (*ch) {
1706                 case '(':
1707                 case ')':
1708                         continue;
1709                 case 'b':
1710                         bool_type = (atoi(param[pi++]) == 0 ? FALSE : TRUE);
1711                         g_variant_builder_add(builder, "b", bool_type);
1712                         break;
1713                 case 'i':
1714                         int_type = atoi(param[pi++]);
1715                         g_variant_builder_add(builder, "i", int_type);
1716                         break;
1717                 case 'u':
1718                         int_type = strtoul(param[pi++], NULL, 10);
1719                         g_variant_builder_add(builder, "u", int_type);
1720                         break;
1721                 case 't':
1722                         int64_type = atoll(param[pi++]);
1723                         g_variant_builder_add(builder, "t", int64_type);
1724                         break;
1725                 case 's':
1726                         g_variant_builder_add(builder, "s", param[pi++]);
1727                         break;
1728                 case 'a':
1729                         ++ch;
1730                         switch (*ch) {
1731                         case 'y':
1732                                 g_variant_builder_add(builder, "^ay", param[pi++]);
1733                                 ++i;
1734                                 break;
1735                         default:
1736                                 break;
1737                         }
1738                         break;
1739                 default:
1740                         break;
1741                 }
1742         }
1743         ret = g_variant_builder_end(builder);
1744         g_variant_builder_clear(builder);
1745         g_variant_builder_unref(builder);
1746
1747         return ret;
1748 }
1749
1750 int dbus_handle_emit_dbus_signal(const char *dest,
1751                                         const char *path,
1752                                         const char *iface,
1753                                         const char *name,
1754                                         GVariant *param)
1755 {
1756         dbus_handle_s *dh = NULL;
1757         GError *err = NULL;
1758         gboolean ret = 0;
1759
1760         dh = _dbus_handle_get_default_connection();
1761         if (!dh) {
1762                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1763                 return -1;
1764         }
1765
1766         ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1767         if (err) {
1768                 _E("%d %s\n", ret, err ? err->message : "NULL");
1769                 g_error_free(err);
1770         }
1771
1772         return ret;
1773 }
1774
1775 int dbus_handle_emit_dbus_signal_sync(const char *dest,
1776                                         const char *path,
1777                                         const char *iface,
1778                                         const char *name,
1779                                         GVariant *param)
1780 {
1781         dbus_handle_s *dh = NULL;
1782         GError *err = NULL;
1783         gboolean ret = 0;
1784
1785         dh = _dbus_handle_get_default_connection();
1786         if (!dh) {
1787                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1788                 return -1;
1789         }
1790
1791         ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1792         if (!ret) {
1793                 _E("%d %s\n", ret, err ? err->message : "NULL");
1794                 g_error_free(err);
1795         }
1796
1797         ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1798         if (!ret) {
1799                 _E("%d %s\n", ret, err ? err->message : "NULL");
1800                 g_error_free(err);
1801         }
1802
1803         return ret;
1804 }
1805
1806 int dbus_handle_flush_sync(dbus_handle_h handle)
1807 {
1808         dcl_dbus_handle();
1809         GError *err = NULL;
1810         gboolean ret = 0;
1811
1812         if (!dh) {
1813                 dh = _dbus_handle_get_default_connection();
1814                 if (!dh) {
1815                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1816                         return 0;
1817                 }
1818         }
1819
1820         ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1821         if (!ret) {
1822                 _E("%d %s\n", ret, err ? err->message : "NULL");
1823                 g_error_free(err);
1824         }
1825
1826         return ret;
1827 }
1828
1829 GVariant *dbus_handle_method_sync_with_reply_var(const char *dest,
1830                                                 const char *path,
1831                                                 const char *iface,
1832                                                 const char *method,
1833                                                 GVariant *var)
1834 {
1835         GError *err = NULL;
1836         GVariant * ret = NULL;
1837         dbus_handle_s *dh = NULL;
1838
1839         if (!dest || !path || !iface || !method) {
1840                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1841                 if (var)
1842                         g_variant_unref(var);
1843                 return NULL;
1844         }
1845
1846         dh = _dbus_handle_get_default_connection();
1847         if (!dh) {
1848                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1849                 if (var)
1850                         g_variant_unref(var);
1851                 return NULL;
1852         }
1853
1854         ret = g_dbus_connection_call_sync(dh->conn,
1855                         dest, path, iface, method,
1856                         var, NULL,
1857                         G_DBUS_CALL_FLAGS_NONE,
1858                         DBUS_REPLY_TIMEOUT,
1859                         NULL,
1860                         &err);
1861         if (!ret || err) {
1862                 if (err) {
1863                         _E("failed to g_dbus_connection_call_sync:%s", err->message);
1864                         if (g_error_matches(err, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED))
1865                                 ret = g_variant_new("(i)", -EPERM);
1866                         else
1867                                 ret = NULL;
1868                         g_error_free(err);
1869                         return ret;
1870                 } else {
1871                         _E("failed to g_dbus_connection_call_sync");
1872                 }
1873                 return NULL;
1874         }
1875
1876         return ret;
1877 }
1878
1879 GVariant *dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path,
1880         const char *iface, const char *method, GVariant *var, int timeout)
1881 {
1882         GError *err = NULL;
1883         GVariant * ret = NULL;
1884         dbus_handle_s *dh = NULL;
1885
1886         if (!dest || !path || !iface || !method) {
1887                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1888                 if (var)
1889                         g_variant_unref(var);
1890                 return NULL;
1891         }
1892
1893         dh = _dbus_handle_get_default_connection();
1894         if (!dh) {
1895                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1896                 if (var)
1897                         g_variant_unref(var);
1898                 return NULL;
1899         }
1900
1901         ret = g_dbus_connection_call_sync(dh->conn,
1902                                         dest, path, iface, method,
1903                                         var, NULL,
1904                                         G_DBUS_CALL_FLAGS_NONE,
1905                                         timeout,
1906                                         NULL,
1907                                         &err);
1908         if (!ret || err) {
1909                 if (err) {
1910                         _E("failed to g_dbus_connection_call_sync:%s", err->message);
1911                         g_error_free(err);
1912                 } else {
1913                         _E("failed to g_dbus_connection_call_sync");
1914                 }
1915                 return NULL;
1916         }
1917
1918         return ret;
1919 }
1920
1921 gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size)
1922 {
1923         GUnixFDList *fd_list = NULL;
1924         int length = 0;
1925
1926         fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation));
1927
1928         if (!fd_list) {
1929                 _E("failed to g_unix_fd_list_get_length: fd_list is null");
1930                 return NULL;
1931         }
1932
1933         length = g_unix_fd_list_get_length(fd_list);
1934         if (length == 0) {
1935                 _E("failed to g_unix_fd_list_get_length: list size is 0");
1936                 return NULL;
1937         }
1938         if (size)
1939                 *size = length;
1940
1941         return g_unix_fd_list_steal_fds(fd_list, NULL);
1942 }
1943
1944 GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply(const char *dest,
1945                                                         const char *path,
1946                                                         const char *iface,
1947                                                         const char *method,
1948                                                         const char *signature,
1949                                                         const char *param[],
1950                                                         int *in_fdlist,
1951                                                         int in_size,
1952                                                         int **out_fdlist,
1953                                                         int *out_size)
1954 {
1955         GError *err = NULL;
1956         GVariant * var = NULL;
1957         GVariant * ret = NULL;
1958         dbus_handle_s *dh = NULL;
1959         GUnixFDList *g_infdlist = NULL;
1960         GUnixFDList *g_outfdlist = NULL;
1961
1962         if (!dest || !path || !iface || !method) {
1963                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1964                 return NULL;
1965         }
1966         if (in_fdlist && in_size == 0) {
1967                 _E("wrong in_fdlist is not null but in_size is 0");
1968                 return NULL;
1969         }
1970
1971         dh = _dbus_handle_get_default_connection();
1972         if (!dh) {
1973                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1974                 return NULL;
1975         }
1976
1977         if (signature && param)
1978                 var = _append_variant(signature, param);
1979
1980         /* append fd */
1981         if (in_fdlist) {
1982                 g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
1983                 if (!g_infdlist) {
1984                         _E("failed to g_unix_fd_list_new_from_array\n");
1985                         goto out;
1986                 }
1987                 //g_infdlist = g_unix_fd_list_new();
1988                 //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
1989         }
1990
1991         ret = g_dbus_connection_call_with_unix_fd_list_sync(dh->conn,
1992                 dest, path, iface, method,
1993                 var, NULL,
1994                 G_DBUS_CALL_FLAGS_NONE,
1995                 -1,
1996                 g_infdlist, &g_outfdlist,
1997                 NULL,
1998                 &err);
1999         if (!ret || err) {
2000                 if (err) {
2001                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message);
2002                         g_error_free(err);
2003                 } else {
2004                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:");
2005                         if (var)
2006                                 g_variant_unref(var);
2007                         if (g_infdlist)
2008                                 g_object_unref(g_infdlist);
2009                 }
2010                 goto out;
2011         }
2012
2013         /* fds to out array */
2014         if (g_outfdlist) {
2015                 *out_size = g_unix_fd_list_get_length(g_outfdlist);
2016                 if (*out_size == 0)
2017                         goto out;
2018
2019                 *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
2020         }
2021
2022 out:
2023         if (g_outfdlist)
2024                 g_object_unref(g_outfdlist);
2025
2026         return ret;
2027 }
2028
2029 GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply_var(const char *dest,
2030                                                                 const char *path,
2031                                                                 const char *iface,
2032                                                                 const char *method,
2033                                                                 GVariant *param,
2034                                                                 int *in_fdlist,
2035                                                                 int in_size,
2036                                                                 int **out_fdlist,
2037                                                                 int *out_size)
2038 {
2039         GError *err = NULL;
2040         GVariant * ret = NULL;
2041         dbus_handle_s *dh = NULL;
2042         GUnixFDList *g_infdlist = NULL;
2043         GUnixFDList *g_outfdlist = NULL;
2044
2045         if (!dest || !path || !iface || !method) {
2046                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2047                 return NULL;
2048         }
2049         if (in_fdlist && in_size == 0) {
2050                 _E("wrong in_fdlist is not null but in_size is 0");
2051                 return NULL;
2052         }
2053
2054         dh = _dbus_handle_get_default_connection();
2055         if (!dh) {
2056                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2057                 return NULL;
2058         }
2059
2060         /* append fd */
2061         if (in_fdlist) {
2062                 g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
2063                 if (!g_infdlist) {
2064                         _E("failed to g_unix_fd_list_new_from_array\n");
2065                         goto out;
2066                 }
2067                 //g_infdlist = g_unix_fd_list_new();
2068                 //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
2069         }
2070
2071         /* send message */
2072         ret = g_dbus_connection_call_with_unix_fd_list_sync(dh->conn,
2073                 dest, path, iface, method,
2074                 param, NULL,
2075                 G_DBUS_CALL_FLAGS_NONE,
2076                 -1,
2077                 g_infdlist, &g_outfdlist,
2078                 NULL, &err);
2079         if (!ret || err) {
2080                 if (err) {
2081                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message);
2082                         g_error_free(err);
2083                 } else {
2084                         _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:");
2085                         if (param)
2086                                 g_variant_unref(param);
2087                         if (g_infdlist)
2088                                 g_object_unref(g_infdlist);
2089                 }
2090                 goto out;
2091         }
2092
2093         /* copy fds to out array */
2094         if (g_outfdlist) {
2095                 *out_size = g_unix_fd_list_get_length(g_outfdlist);
2096                 if (*out_size == 0)
2097                         goto out;
2098                 *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
2099         }
2100 out:
2101         if (g_outfdlist)
2102                 g_object_unref(g_outfdlist);
2103         return ret;
2104 }
2105
2106 int dbus_handle_method_sync(const char *dest,
2107                         const char *path,
2108                         const char *iface,
2109                         const char *method,
2110                         const char *signature,
2111                         const char *param[])
2112 {
2113         int result;
2114         gboolean result_bool;
2115         GVariant *reply = NULL;
2116         GVariant * var = NULL;
2117         GError *err = NULL;
2118         dbus_handle_s *dh = NULL;
2119
2120         if (!dest || !path || !iface || !method) {
2121                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2122                 return -1;
2123         }
2124
2125         dh = _dbus_handle_get_default_connection();
2126         if (!dh) {
2127                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2128                 return -ECOMM;
2129         }
2130
2131         if (signature && param)
2132                 var = _append_variant(signature, param);
2133
2134         reply = g_dbus_connection_call_sync(dh->conn,
2135                         dest, path, iface, method,
2136                         var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
2137         if (!reply || err) {
2138                 if (err) {
2139                         _E("failed to g_dbus_connection_call_sync:%s", err->message);
2140                         g_error_free(err);
2141                 } else {
2142                         _E("failed to g_dbus_connection_call_sync");
2143                         g_variant_unref(var);
2144                 }
2145                 return -ECOMM;
2146         }
2147
2148         if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
2149                 g_variant_get(reply, "(i)", &result);
2150         } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
2151                 g_variant_get(reply, "(b)", &result_bool);
2152                 result = (int)result_bool;
2153         } else {
2154                 result = -ENOMSG;
2155         }
2156
2157         g_variant_unref(reply);
2158
2159         return result;
2160 }
2161
2162 int dbus_handle_method_sync_var(const char *dest,
2163                                 const char *path,
2164                                 const char *iface,
2165                                 const char *method,
2166                                 GVariant *param)
2167 {
2168         int result;
2169         gboolean result_bool;
2170         GVariant *reply = NULL;
2171
2172         if (!dest || !path || !iface || !method) {
2173                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2174                 return -1;
2175         }
2176
2177         reply = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param);
2178         if (!reply)
2179                 return -ECOMM;
2180
2181         if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
2182                 g_variant_get(reply, "(i)", &result);
2183         } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
2184                 g_variant_get(reply, "(b)", &result_bool);
2185                 result = (int)result_bool;
2186         } else {
2187                 result = -ENOMSG;
2188         }
2189
2190         g_variant_unref(reply);
2191
2192         return result;
2193 }
2194
2195 int dbus_handle_method_sync_timeout(const char *dest,
2196                                         const char *path,
2197                                         const char *iface,
2198                                         const char *method,
2199                                         const char *signature,
2200                                         const char *param[],
2201                                         int timeout)
2202 {
2203         dbus_handle_s *dh = NULL;
2204         GError *err = NULL;
2205         GVariant * var = NULL;
2206         GVariant * reply = NULL;
2207         int result = 0;
2208
2209         if (!dest || !path || !iface || !method) {
2210                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2211                 return -1;
2212         }
2213
2214         dh = _dbus_handle_get_default_connection();
2215         if (!dh) {
2216                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2217                 return -EPERM;
2218         }
2219
2220         if (signature && param)
2221                 var = _append_variant(signature, param);
2222
2223         reply = g_dbus_connection_call_sync(dh->conn,
2224                         dest, path, iface, method,
2225                         var, NULL,
2226                         G_DBUS_CALL_FLAGS_NONE,
2227                         timeout,
2228                         NULL,
2229                         &err);
2230         if (!reply || err) {
2231                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2232                 g_error_free(err);
2233                 return -1;
2234         }
2235
2236         if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0)
2237                 g_variant_get(reply, "(i)", &result);
2238         else
2239                 result = -ENOMSG;
2240
2241         g_variant_unref(reply);
2242
2243         return result;
2244 }
2245
2246 int dbus_handle_method_async(const char *dest,
2247                                 const char *path,
2248                                 const char *iface,
2249                                 const char *method,
2250                                 const char *signature,
2251                                 const char *param[])
2252 {
2253         GVariant * var = NULL;
2254         dbus_handle_s *dh = NULL;
2255
2256         if (!dest || !path || !iface || !method) {
2257                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2258                 return -1;
2259         }
2260
2261         dh = _dbus_handle_get_default_connection();
2262         if (!dh) {
2263                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2264                 return -1;
2265         }
2266
2267         if (signature && param)
2268                 var = _append_variant(signature, param);
2269
2270         g_dbus_connection_call(dh->conn,
2271                                 dest, path, iface, method,
2272                                 var, NULL,
2273                                 G_DBUS_CALL_FLAGS_NONE,
2274                                 -1,
2275                                 NULL,
2276                                 NULL,
2277                                 NULL);
2278
2279         return 0;
2280 }
2281
2282 int dbus_handle_method_async_var(const char *dest,
2283                                         const char *path,
2284                                         const char *iface,
2285                                         const char *method,
2286                                         GVariant *param)
2287 {
2288         dbus_handle_s *dh = NULL;
2289
2290         if (!dest || !path || !iface || !method) {
2291                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2292                 return -1;
2293         }
2294
2295         dh = _dbus_handle_get_default_connection();
2296         if (!dh) {
2297                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2298                 return -1;
2299         }
2300
2301         g_dbus_connection_call(dh->conn,
2302                                 dest, path, iface, method,
2303                                 param, NULL,
2304                                 G_DBUS_CALL_FLAGS_NONE,
2305                                 -1,
2306                                 NULL,
2307                                 NULL,
2308                                 NULL);
2309
2310         return 0;
2311 }
2312
2313 /* callback should free gvariant */
2314 static void _cb_pending(GDBusConnection *conn,
2315                         GAsyncResult *res,
2316                         gpointer user_data)
2317 {
2318         GVariant *reply = NULL;
2319         GError *err = NULL;
2320         pending_call_data *data = (pending_call_data *)user_data;
2321
2322         reply = g_dbus_connection_call_finish(conn, res, &err);
2323         if (!reply || err) {
2324                 if (!err)
2325                         g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
2326                                 "Error during g_dbus_connection_call");
2327
2328                 if (data && data->func)
2329                         data->func(NULL, data->data, err);
2330                 goto out;
2331         }
2332
2333         if (data && data->func)
2334                 data->func(reply, data->data, err);
2335 out:
2336         if (err)
2337                 g_error_free(err);
2338         if (data)
2339                 free(data);
2340 }
2341
2342 int dbus_handle_method_async_with_reply(const char *dest,
2343                                         const char *path,
2344                                         const char *iface,
2345                                         const char *method,
2346                                         const char *signature,
2347                                         const char *param[],
2348                                         dbus_pending_cb cb,
2349                                         int timeout_msec,
2350                                         void *data)
2351 {
2352         dbus_handle_s *dh = NULL;
2353         pending_call_data *pdata = NULL;
2354         GVariant * var = NULL;
2355         int ret = 0;
2356
2357         if (!dest || !path || !iface || !method) {
2358                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2359                 return -1;
2360         }
2361
2362         if (timeout_msec < -1) {
2363                 _E("wrong timeout %d", timeout_msec);
2364                 return -1;
2365         }
2366
2367         dh = _dbus_handle_get_default_connection();
2368         if (!dh) {
2369                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2370                 return -EPERM;
2371         }
2372
2373         if (signature && param)
2374                 var = _append_variant(signature, param);
2375
2376         if (cb) {
2377                 pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
2378                 if (!pdata) {
2379                         ret = -ENOMEM;
2380                         goto err;
2381                 }
2382
2383                 pdata->func = cb;
2384                 pdata->data = data;
2385         }
2386         g_dbus_connection_call(dh->conn,
2387                                 dest, path, iface, method,
2388                                 var, NULL,
2389                                 G_DBUS_CALL_FLAGS_NONE,
2390                                 timeout_msec,
2391                                 NULL,
2392                                 (GAsyncReadyCallback)_cb_pending,
2393                                 pdata);
2394
2395         return ret;
2396 err:
2397         if (var)
2398                 g_variant_unref(var);
2399         return ret;
2400 }
2401
2402 int dbus_handle_method_async_with_reply_var(const char *dest,
2403                                         const char *path,
2404                                         const char *iface,
2405                                         const char *method,
2406                                         GVariant *param,
2407                                         dbus_pending_cb cb,
2408                                         int timeout_msec,
2409                                         void *data)
2410 {
2411         dbus_handle_s *dh = NULL;
2412         pending_call_data *pdata = NULL;
2413         int ret = 0;
2414
2415         if (!dest || !path || !iface || !method) {
2416                 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2417                 return -1;
2418         }
2419
2420         if (timeout_msec < -1) {
2421                 _E("wrong timeout %d", timeout_msec);
2422                 return -1;
2423         }
2424
2425         dh = _dbus_handle_get_default_connection();
2426         if (!dh) {
2427                 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2428                 return -EPERM;
2429         }
2430
2431         if (cb) {
2432                 pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
2433                 if (!pdata) {
2434                         ret = -ENOMEM;
2435                         goto err;
2436                 }
2437
2438                 pdata->func = cb;
2439                 pdata->data = data;
2440         }
2441         g_dbus_connection_call(dh->conn,
2442                                 dest, path, iface, method,
2443                                 param, NULL,
2444                                 G_DBUS_CALL_FLAGS_NONE,
2445                                 timeout_msec,
2446                                 NULL,
2447                                 (GAsyncReadyCallback)_cb_pending,
2448                                 pdata);
2449
2450         return ret;
2451 err:
2452         if (param)
2453                 g_variant_unref(param);
2454         return ret;
2455 }
2456
2457 int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender)
2458 {
2459         GError *err = NULL;
2460         GVariant *vret = NULL;
2461         pid_t pid = 0;
2462
2463         if (!conn) {
2464                 _E("connection is null");
2465                 return -1;
2466         }
2467         if (!sender) {
2468                 _E("sender is null");
2469                 return -1;
2470         }
2471
2472         vret = g_dbus_connection_call_sync(conn,
2473                         "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID",
2474                         g_variant_new("(s)", sender), NULL,
2475                         G_DBUS_CALL_FLAGS_NONE,
2476                         DBUS_REPLY_TIMEOUT,
2477                         NULL,
2478                         &err);
2479         if (!vret || err) {
2480                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2481                 g_error_free(err);
2482                 return -1;
2483         }
2484
2485         g_variant_get(vret, "(u)", &pid);
2486         g_variant_unref(vret);
2487
2488         return pid;
2489 }
2490
2491 int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender)
2492 {
2493         dcl_dbus_handle();
2494
2495         if (!dh) {
2496                 dh = _dbus_handle_get_default_connection();
2497                 if (!dh) {
2498                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2499                         return -1;
2500                 }
2501         }
2502         if (!dh->conn) {
2503                 _E("wrong dbus handle. connection is null");
2504                 assert(0);
2505                 return -1;
2506         }
2507
2508         return dbus_connection_get_sender_pid(dh->conn, sender);
2509 }
2510
2511 int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds)
2512 {
2513         dcl_dbus_handle();
2514         GVariant *vret = NULL;
2515         GError *err = NULL;
2516         GVariantIter *iter = NULL;
2517         char * item;
2518         GVariant *sub;
2519
2520         if (!dh) {
2521                 dh = _dbus_handle_get_default_connection();
2522                 if (!dh) {
2523                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2524                         return -1;
2525                 }
2526         }
2527         vret = g_dbus_connection_call_sync(dh->conn,
2528                                         DBUS_BUS_NAME,
2529                                         DBUS_OBJECT_PATH,
2530                                         DBUS_INTERFACE_NAME,
2531                                         "GetConnectionCredentials",
2532                                         g_variant_new("(s)", name),
2533                                         NULL,
2534                                         G_DBUS_CALL_FLAGS_NONE,
2535                                         DBUS_REPLY_TIMEOUT,
2536                                         NULL,
2537                                         &err);
2538         if (!vret || err) {
2539                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2540                 return -1;
2541         }
2542
2543         g_variant_get(vret, "(a{sv})", &iter);
2544
2545         while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) {
2546                 if (!g_strcmp0(item, "UnixUserID")) {
2547                         g_variant_get(sub, "u", &creds->uid);
2548                         //_D("UnixUserID %u", creds->uid);
2549                 } else if (!g_strcmp0(item, "ProcessID")) {
2550                         g_variant_get(sub, "u", &creds->pid);
2551                         //_D("ProcessID %u", creds->pid);
2552                 } else if (!g_strcmp0(item, "LinuxSecurityLabel")) {
2553                         g_variant_get(sub, "^ay", &creds->sec_label);
2554                         //_D("%s", creds->sec_label);
2555                 }
2556         }
2557
2558         if (iter)
2559                 g_variant_iter_free(iter);
2560         if (vret)
2561                 g_variant_unref(vret);
2562
2563         return 0;
2564 }
2565
2566 void _destroy_notify_watch_name(gpointer data)
2567 {
2568 //      if (data)
2569 //              free(data);
2570 }
2571
2572 int dbus_handle_watch_name(const char *name,
2573                         GBusNameAppearedCallback  name_appeared_handler,
2574                         GBusNameVanishedCallback  name_vanished_handler,
2575                         void *user_data,
2576                         GDestroyNotify user_data_free_func)
2577 {
2578         guint id = 0;
2579
2580         if (!name) {
2581                 _E("wrong name name is null");
2582                 return -1;
2583         }
2584         if (!name_appeared_handler && !name_vanished_handler) {
2585                 _E("both function pointers are null");
2586                 return -1;
2587         }
2588
2589         id = g_bus_watch_name(dbus_handle_get_default_bus_type(),
2590                                 name,
2591                                 G_BUS_NAME_WATCHER_FLAGS_NONE,
2592                                 name_appeared_handler,
2593                                 name_vanished_handler,
2594                                 user_data,
2595                                 user_data_free_func ? user_data_free_func : _destroy_notify_watch_name);
2596         if (!id) {
2597                 _E("failed to g_bus_watch_name");
2598                 return -1;
2599         }
2600
2601         return id;
2602 }
2603
2604 void dbus_handle_unwatch_name(guint id)
2605 {
2606         if (id == 0) {
2607                 _E("wrong id %d", id);
2608                 return;
2609         }
2610         g_bus_unwatch_name(id);
2611 }
2612
2613 int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size)
2614 {
2615         int fd, ret;
2616         char buf[PATH_MAX + 1];
2617         char *filename;
2618
2619         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
2620         fd = open(buf, O_RDONLY);
2621         if (fd < 0) {
2622                 errno = ESRCH;
2623                 return -1;
2624         }
2625
2626         ret = read(fd, buf, PATH_MAX);
2627         close(fd);
2628         if (ret < 0)
2629                 return -1;
2630
2631         buf[PATH_MAX] = '\0';
2632
2633         filename = strrchr(buf, '/');
2634         if (filename == NULL)
2635                 filename = buf;
2636         else
2637                 filename = filename + 1;
2638
2639         if (cmdline_size < strlen(filename) + 1) {
2640                 errno = EOVERFLOW;
2641                 return -1;
2642         }
2643
2644         strncpy(cmdline, filename, cmdline_size - 1);
2645         cmdline[cmdline_size - 1] = '\0';
2646         return 0;
2647 }
2648
2649 // g_strfreev(strv)
2650 char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name)
2651 {
2652         dcl_dbus_handle();
2653         GError *err = NULL;
2654         GVariant *vret = NULL;
2655         GVariantIter *iter = NULL;
2656         gchar **strv = NULL;
2657         gchar *str = NULL;
2658         int i = 0;
2659
2660         if (!bus_name) {
2661                 _E("wrong parameter bus_name is null");
2662                 return NULL;
2663         }
2664
2665         if (!dh) {
2666                 dh = _dbus_handle_get_default_connection();
2667                 if (!dh) {
2668                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2669                         return NULL;
2670                 }
2671         }
2672
2673         vret = g_dbus_connection_call_sync(dh->conn,
2674                                         "org.freedesktop.DBus",
2675                                         "/",
2676                                         "org.freedesktop.DBus",
2677                                         "ListQueuedOwners",
2678                                         g_variant_new("(s)", bus_name),
2679                                         NULL,
2680                                         G_DBUS_CALL_FLAGS_NONE,
2681                                         DBUS_REPLY_TIMEOUT,
2682                                         NULL,
2683                                         &err);
2684         if (!vret || err) {
2685                 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2686                 g_error_free(err);
2687                 return NULL;
2688         }
2689
2690         g_variant_get(vret, "(as)", &iter);
2691         strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1);
2692
2693         i = 0;
2694         while (g_variant_iter_loop(iter, "s", &str))
2695                 strv[i++] = g_strdup(str);
2696         strv[i] = NULL;
2697
2698         g_variant_iter_free(iter);
2699         g_variant_unref(vret);
2700
2701         return strv;
2702 }
2703
2704 void dbus_handle_check_owner_name(dbus_handle_h handle, const char *owner_name)
2705 {
2706         dcl_dbus_handle();
2707         char exe_name[PATH_MAX];
2708         int pid;
2709         char **strv = NULL;
2710         int i;
2711
2712         if (!dh) {
2713                 dh = _dbus_handle_get_default_connection();
2714                 if (!dh) {
2715                         _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2716                         return ;
2717                 }
2718         }
2719
2720         strv = dbus_handle_get_owner_list(dh, owner_name);
2721         if (!strv) {
2722                 _E("failed to get owner list of %s", owner_name);
2723                 return ;
2724         }
2725
2726         for (i = 0; strv[i] != NULL; ++i) {
2727                 pid = dbus_handle_get_sender_pid(dh, strv[i]);
2728                 if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0)
2729                         break;
2730                 _I("%s(%d)", exe_name, pid);
2731         }
2732
2733         g_strfreev(strv);
2734 }
2735
2736 int check_systemd_active(void)
2737 {
2738         int ret = FALSE;
2739         GVariant *msg = NULL;
2740         GVariant *var = NULL;
2741         char *state;
2742
2743         _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState");
2744
2745         msg = dbus_handle_method_sync_with_reply_var("org.freedesktop.systemd1",
2746                         "/org/freedesktop/systemd1/unit/default_2etarget",
2747                         "org.freedesktop.DBus.Properties",
2748                         "Get",
2749                         g_variant_new("(ss)", "org.freedesktop.systemd1.Unit", "ActiveState"));
2750         if (!msg)
2751                 return -EBADMSG;
2752
2753         if (!g_variant_get_safe(msg, "(v)", &var)) {
2754                 _E("reply is not variant type");
2755                 ret = -EBADMSG;
2756                 goto out;
2757         }
2758         if (!g_variant_get_safe(var, "(s)", &state)) {
2759                 _E("variant doesn't have string (%s)", g_variant_get_type_string(var));
2760                 ret = -EBADMSG;
2761                 goto out;
2762         }
2763
2764         if (strncmp(state, "active", 6) == 0)
2765                 ret = TRUE;
2766
2767         g_free(state);
2768 out:
2769         if (var)
2770                 g_variant_unref(var);
2771         if (msg)
2772                 g_variant_unref(msg);
2773
2774         return ret;
2775 }
2776
2777 GVariant *dbus_handle_make_simple_array(const char *sig, int *param)
2778 {
2779         GVariantBuilder *builder = NULL;
2780         GVariant *var = NULL;
2781         char format[256];
2782         int i = 0;
2783
2784         builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
2785         if (!builder) {
2786                 _E("failed to g_variant_builder_new");
2787                 return NULL;
2788         }
2789
2790         while (param[i])
2791                 g_variant_builder_add(builder, "i", param[i++]);
2792
2793         snprintf(format, sizeof(format) - 1, "(%s)", sig);
2794         var = g_variant_new(format, builder);
2795         g_variant_builder_unref(builder);
2796         return var;
2797 }