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