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