4 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include "shared/log.h"
27 #include "dbus-system.h"
30 #define DBUS_REPLY_TIMEOUT (10000)
32 static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM;
33 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
35 void dbus_handle_set_default_bus_type(GBusType bus_type)
37 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION)
40 pthread_mutex_lock(&g_mutex);
41 g_default_bus_type = bus_type;
42 pthread_mutex_unlock(&g_mutex);
45 GBusType dbus_handle_get_default_bus_type(void)
49 pthread_mutex_lock(&g_mutex);
50 type = g_default_bus_type;
51 pthread_mutex_unlock(&g_mutex);
61 /* basic information */
63 GDBusConnection *conn;
66 GList *list_names; /* dbus_name */
67 GList *list_object; /* dbus_object_handle_s */
68 pthread_mutex_t mutex;
71 /* path + interfaces */
73 dbus_handle_s *dh; /* dbus handle */
74 const char *path; /* object path */
75 GList *list_ifaces; /* dbus_interface_s */
76 } dbus_object_handle_s;
79 dbus_object_handle_s *oh; /* object handle */
80 const char *name; /* interface name */
81 GList *list_methods; /* const dbus_method_s */
86 #define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh
88 /* global shared bus : system, session */
89 static dbus_handle_s g_dh[2];
91 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type);
93 dbus_handle_s * _dbus_handle_get_default_connection(void)
95 return _dbus_handle_get_connection(dbus_handle_get_default_bus_type());
98 #define dbus_handle_lock(handle) do {\
100 pthread_mutex_lock(&((handle)->mutex));\
103 #define dbus_handle_unlock(handle) do {\
105 pthread_mutex_unlock(&(handle)->mutex);\
108 #define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle;
109 #define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\
111 _E("dbus handle is null\n");\
115 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path);
116 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name);
117 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name);
118 static GVariant* _append_variant(const char *signature, const char *param[]);
120 dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u)
122 dbus_interface_s *iface = NULL;
124 if (!iface_u || !iface_u->methods) {
129 iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s));
131 _E("failed to calloc");
135 iface->name = iface_u->name;
136 iface->modified = TRUE;
138 for (int i = 0 ; i < iface_u->nr_methods; ++i) {
139 //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func);
140 iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i));
146 static GDBusConnection * _get_bus(GBusType bus_type)
148 GDBusConnection *conn = NULL;
151 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
152 _E("Wrong bus_type %d", bus_type);
156 conn = g_bus_get_sync(bus_type, NULL, &err);
158 _E("failed to get bus:type:%d, %s\n", bus_type, err->message);
166 static GDBusConnection * _get_bus_private(GBusType bus_type)
169 GDBusConnection *conn = NULL;
170 const char * address;
172 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
173 _E("Wrong bus_type %d", bus_type);
177 address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err);
178 if (!address || err) {
179 _E("failed to get bus address\n");
184 conn = g_dbus_connection_new_for_address_sync(address,
185 (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
186 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
187 NULL, /* GDBusAuthObserver */
191 _E("failed to get private bus\n");
200 static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type)
202 int ibus = bus_type - 1;
203 dbus_handle_s *dh = NULL;
205 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
206 _E("Unknown bus type %d", bus_type);
211 dbus_handle_lock(dh);
214 dh->conn = _get_bus(bus_type);
216 dbus_handle_unlock(dh);
220 dh->bus_type = bus_type;
223 dbus_handle_unlock(dh);
229 static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type)
233 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
234 _E("Unknown bus type %d", bus_type);
238 dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s));
240 _E("failed to allocate memory for dbus handle");
244 dbus_handle_lock(dh);
247 dh->conn = _get_bus_private(bus_type);
248 dh->bus_type = bus_type;
253 dbus_handle_unlock(dh);
258 dbus_handle_unlock(dh);
264 dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv)
266 dbus_handle_s *dh = NULL;
269 if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) {
270 _E("Wrong bus_type %d\n", bus_type);
274 for (i = 0 ; i < 3; ++i) {
277 dh = _dbus_handle_get_connection_private(bus_type);
280 dh = _dbus_handle_get_connection(bus_type);
290 static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id)
292 dbus_name *dn = NULL;
295 if (!handle || !name || !id)
298 dn = (dbus_name*)calloc(1, sizeof(dbus_name));
300 _E("failed to calloc");
306 // todo : delete lock ?
307 locked = pthread_mutex_trylock(&handle->mutex);
308 if (locked != 0 && locked != EBUSY) {
309 _E("failed to lock %d\n", locked);
313 handle->list_names = g_list_prepend(handle->list_names, dn);
315 // todo : delete lock ?
317 dbus_handle_unlock(handle);
320 static gint _compare_dbus_name(gconstpointer a, gconstpointer b)
322 const char *bus_name = ((dbus_name *)a)->bus_name;
325 return strcmp(bus_name, (const char *)b);
328 dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name)
330 if (!list_name || !bus_name)
333 GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name);
337 return (dbus_name *)item->data;
340 #define dh_to_ds(x) ((dbus_handle_s*)x)
342 /* remove dbus_name from dbus handle */
343 static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name)
346 dbus_name *dn = NULL;
349 _E("wrong bus_name is null");
353 dh = _dbus_handle_get_default_connection();
355 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
360 dbus_handle_lock(dh);
361 dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
363 _E("failed to find dbus name %s", bus_name);
366 dh->list_names = g_list_remove(dh->list_names, dn);
369 dbus_handle_unlock(dh);
372 //extern void booting_done(void);
374 /* default handler */
375 static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
377 dbus_handle_s *dh = (dbus_handle_s *)user_data;
382 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
386 // todo: add bus name?
387 //dh->bus_name = name;
390 /* default handler */
391 static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
393 _E("%s:%d:%s\n", __func__, __LINE__, name);
394 dbus_handle_s *dh = (dbus_handle_s *)user_data;
396 _E("%s:%d:dbus handle is null\n", __func__, __LINE__);
399 _dbus_handle_remove_bus_name(dh, name);
402 int dbus_handle_request_bus_name(dbus_handle_h handle,
403 const char *bus_name,
404 GBusNameAcquiredCallback acquired_handler,
405 GBusNameLostCallback lost_handler)
412 _E("bus_name is NULL");
416 /* get shared connection */
418 dh = _dbus_handle_get_default_connection();
420 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
425 dbus_handle_lock(dh);
427 _E("failed to register name: connection is null\n");
431 /* todo : search name on connection */
432 item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name);
434 id = ((dbus_name*)(item->data))->id;
435 _E("name already exist:%u", id);
439 id = g_bus_own_name_on_connection(dh->conn,
441 G_BUS_NAME_OWNER_FLAGS_NONE,
442 acquired_handler ? acquired_handler : _name_acquired,
443 lost_handler ? lost_handler : _name_lost,
447 _E("failed to own name:%s\n", bus_name);
451 _dbus_handle_add_bus_name(dh, bus_name, id);
454 dbus_handle_unlock(dh);
458 /* !! _name_lost handler callback is disabled by g_bus_unown_name : ubuntu */
459 int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name)
462 dbus_name *dn = NULL;
465 _E("Wrong bus name");
470 dh = _dbus_handle_get_default_connection();
472 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
477 dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name);
479 _E("failed to find bus_name %s on dbus handle", bus_name);
483 _E("unown name %d", dn->id);
484 /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
485 g_bus_unown_name(dn->id);
487 dbus_handle_lock(dh);
488 dh->list_names = g_list_remove(dh->list_names, dn);
490 dbus_handle_unlock(dh);
495 int dbus_handle_free_connection(dbus_handle_h handle)
498 dbus_handle_s *pdh = NULL;
503 dh = _dbus_handle_get_default_connection();
505 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
511 _E("connection is NULL");
517 /* disable dbus handler */
518 dbus_handle_lock(dh);
525 /* flush everything */
526 if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) {
527 _E("failed to flush %s\n", err->message);
532 _D("list_names %u", g_list_length(pdh->list_names));
534 /* unown every well-knwon name */
535 if (pdh->list_names) {
536 dbus_name *dn = NULL;
537 for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) {
538 dn = (dbus_name *)item->data;
542 /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */
543 _D("unown name id : %u", dn->id);
544 g_bus_unown_name(dn->id);
547 g_list_free(pdh->list_names);
548 pdh->list_names = NULL;
551 _D("list_object %u", g_list_length(pdh->list_object));
553 /* unregister every object */
554 if (pdh->list_object) {
555 dbus_object_handle_s * oh = NULL;
556 //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data) {}, NULL);
557 for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) {
558 oh = (dbus_object_handle_s *)item->data;
559 if (!oh || !oh->list_ifaces)
562 _D("delete object path %s", oh->path);
564 /* unregister every interface, method handles */
565 for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) {
566 dbus_interface_s *ih = (dbus_interface_s *)iface->data;
570 _D("delete object iface %s", ih->name);
573 g_dbus_connection_unregister_object(pdh->conn, ih->reg_id);
578 /* close connection */
580 _E("close private connection\n");
582 if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) {
583 _E("Error closing connection %s\n", err->message);
589 /* _free_func_object callback free the data */
590 //assert(g_list_length(pdh->list_names) == 0);
591 //assert(g_list_length(pdh->list_object) == 0);
593 g_object_unref(pdh->conn);
595 dbus_handle_unlock(dh);
605 #define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0)
606 #define buf_block_size 8192
608 #define buf_check_space_realloc(buf, nwrite, buf_len) do {\
609 if ((nwrite >= buf_len - 1024)) {\
610 if (buf_len >= buf_block_size * 10) {\
611 _E("buf is too big to allocate. %d", buf_len);\
613 _E("buf_check_space_realloc");\
615 buf_len += buf_block_size;\
616 tmp = (char *)realloc(buf, buf_len);\
618 _E("failed to realloc");\
625 /* cal index of end of brace */
626 static int _check_brace(const char * expr)
637 if (expr[0] != '(' && expr[0] != '{')
640 for (int i = 0 ; i < len; ++i) {
642 if (expr[i] == '(' || expr[i] == '{') {
643 qu[qucnt++] = expr[i];
644 if (qucnt >= sizeof(qu)) {
645 _E("queue is too large. %s", expr);
651 if (expr[i] == ')' || expr[i] == '}') {
659 if (expr[i] == ')') {
664 } else if (expr[i] == '}') {
684 static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces)
689 const dbus_method_s *pmethod;
690 int buf_len = buf_block_size;
693 _E("interfaces is null");
697 // todo : check dbus naming rule for interface name. ?
698 if (!interfaces->name) {
699 _E("wrong interface name");
702 if (!interfaces->list_methods) {
707 buf = (char *)malloc(buf_len);
709 _E("buf is null. not enough memory\n");
713 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "<node>""\n""\t""<interface name='%s'>""\n", interfaces->name);
716 for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) {
717 pmethod = (const dbus_method_s *)item->data;
721 /* check free space of buf */
722 buf_check_space_realloc(buf, nwrite, buf_len);
724 if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) {
725 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'/>""\n", pmethod->member);
729 /* <method name='###'> */
730 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'>""\n", pmethod->member);
733 len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0;
734 for (int m = 0; m < len_args; ++m) {
736 // array a(), as, ay ?
737 if (pmethod->signature_in[m] == 'a') {
739 ei = _check_brace(pmethod->signature_in + m + 1);
741 char tmp[128] = {0,};
742 strncpy(tmp, pmethod->signature_in + m, ei + 1);
743 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='in'/>""\n", tmp, m);
747 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m);
752 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='in'/>""\n", pmethod->signature_in[m], m);
756 len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0;
757 for (int m = 0; m < len_args; ++m) {
759 // todo: container type
760 if (pmethod->signature_out[m] == 'a') {
762 ei = _check_brace(pmethod->signature_out + m + 1);
764 char tmp[128] = {0,};
765 strncpy(tmp, pmethod->signature_out + m, ei + 1);
766 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%s' name='arg%d' direction='out'/>""\n", tmp, m);
770 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m);
775 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], m);
779 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""</method>""\n");
782 nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""</interface>""\n""</node>""");
786 /* todo: delete log */
791 _E("%s", buf + nwrite - 512);
796 static gint _compare_dbus_object(gconstpointer a, gconstpointer b)
798 dbus_object_handle_s * pa = (dbus_object_handle_s *)a;
799 if (!pa->path || !((const char*)b))
801 return strcmp(pa->path, (const char*)b);
804 static gint _compare_dbus_interface(gconstpointer a, gconstpointer b)
806 dbus_interface_s * pa = (dbus_interface_s *)a;
807 if (!pa->name || !((const char*)b))
809 return strcmp(pa->name, (const char*)b);
812 static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b)
814 dbus_interface_s * pa = (dbus_interface_s *)a;
815 if (!pa->reg_id || !((guint*)b))
817 return !(pa->reg_id == *((guint*)b));
820 static gint _compare_dbus_method(gconstpointer a, gconstpointer b)
822 dbus_method_s *pa = (dbus_method_s*)a;
823 if (!pa->member || !((const char*)b))
825 return strcmp(pa->member, (const char*)b);
828 dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path)
830 if (!list_obj || !obj_path)
833 GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object);
837 return (dbus_object_handle_s *)item->data;
840 dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name)
842 if (!list_iface || !iface_name)
845 GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface);
849 return (dbus_interface_s *)item->data;
852 dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id)
854 if (!list_iface || !id)
857 GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id);
861 return (dbus_interface_s *)item->data;
864 dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name)
866 if (!list_methods || !method_name)
869 GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method);
873 return (dbus_method_s *)item->data;
876 static void _free_func_object(gpointer data)
878 dbus_interface_s *ih = (dbus_interface_s *)data;
879 dbus_object_handle_s *oh = NULL;
882 _E("interface handle is null");
883 assert(0); // something wrong
887 _E("unregister interface %s", ih->name);
889 /* just free list, not data(static dbus_method_s) */
890 g_list_free(ih->list_methods);
894 _E("object handle is null");
895 assert(0); // something wrong
899 /* remove ih from list_ifaces */
900 oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
902 /* interface_s is copy of interface_u */
905 /* remove oh from list_object */
906 if (!oh->list_ifaces) {
907 oh->dh->list_object = g_list_remove(oh->dh->list_object, oh);
912 static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface)
914 dbus_object_handle_s *oh = NULL;
916 if (!dh || !obj_path || !iface) {
917 _E("failed to attache object. wrong parameter");
921 /* find object handle */
923 oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
926 oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s));
928 _E("failed to calloc");
935 dh->list_object = g_list_prepend(dh->list_object, oh);
939 /* attach interface */
940 oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface);
948 libgio verify path and interface of incoming message.
949 --> just check method name.
951 # parameters - member of invocation struct
952 every parameters of this function are member of GDBusMethodInvocation *invocation.
953 There are no reason to using g_dbus_method_invocation_get_* apis to get inforamtion from message.
954 just use params - sender, path, iface, name and param.
957 # user defined handler #
959 1. synchronous handling
962 return g_variant_new("(i)", ret);
965 2) without return value
967 return dbus_handle_new_g_variant_tuple(); // g_variant_new_tuple(NULL, 0)
970 2. asynchronous handling
971 handler MUST call 'g_dbus_method_invocation_return_value' itself. otherwise, LEAK !!
977 # if handler return NULL, assume asynchronous handling. do nothing.
983 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
985 2) without return value
986 g_dbus_method_invocation_return_value(invocation, NULL);
991 static void _method_call_handler(GDBusConnection *conn,
997 GDBusMethodInvocation *invocation,
1000 dbus_interface_s *iface_s = (dbus_interface_s *)user_data;
1001 const dbus_method_s *methods;
1002 GVariant *result = NULL;
1005 methods = _dbus_handle_lookup_method(iface_s->list_methods, name);
1007 result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh));
1009 /* async, maybe they will reply...maybe.. */
1016 g_dbus_method_invocation_return_value(invocation, result);
1019 static GDBusInterfaceVTable path_vtable = {_method_call_handler};
1023 before register object, attach object into dbus handle
1024 _dbus_handle_attach_object()
1026 static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface)
1032 GDBusNodeInfo * nodeinfo = NULL;
1033 GDBusInterfaceInfo *ifaceinfo = NULL;
1035 if (!obj_path || !iface) {
1036 _E("wrong parameter\n");
1040 dh = _dbus_handle_get_default_connection();
1042 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1047 _E("connection is null\n");
1051 ret = _get_xml_from_interfaces(&buf, iface);
1053 _E("failed to make xml format");
1057 /* todo: delete this */
1059 if (strlen(buf) <= 512) {
1062 _E("%s", buf + strlen(buf) - 512);
1066 nodeinfo = g_dbus_node_info_new_for_xml(buf, &err);
1067 if (!nodeinfo || err) {
1068 _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf);
1073 ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name);
1075 _E("failed to g_dbus_node_info_lookup_interface");
1081 path own single interface
1082 if interface is already registered, then failed.
1083 g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered
1085 ret = g_dbus_connection_register_object(dh->conn,
1093 _E("failed to register object:err:%s:\n", err->message);
1098 iface->reg_id = ret;
1099 iface->modified = FALSE;
1102 /* todo: detach object */
1103 //_dbus_handle_detach_object(dh, obj_path, iface);
1104 /* attach interface before register object */
1105 /*ret = _dbus_handle_detach_object(dh, obj_path, iface);
1107 _E("failed to attach object");
1112 g_dbus_node_info_unref(nodeinfo);
1122 register same interface at once
1124 if interface is constructed by multiple methods,
1125 also it is not possible to make methods struct at once,
1127 use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all().
1131 int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1135 dbus_interface_s *iface = NULL;
1137 if (!obj_path || !iface_u) {
1138 _E("wrong parameter\n");
1142 dh = _dbus_handle_get_default_connection();
1144 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1149 _E("connection is null\n");
1153 /* check registered interface */
1154 if (dh->list_object) {
1155 dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1157 dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1159 _E("path %s, interface %s already registered", obj_path, iface_u->name);
1165 iface = _iface_u_to_s(iface_u);
1167 _E("failed to _iface_u_to_s");
1171 /* attach interface before register object */
1172 ret = _dbus_handle_attach_object(dh, obj_path, iface);
1174 _E("failed to attach object");
1178 ret = _dbus_handle_register_dbus_object(dh, obj_path, iface);
1180 _E("failed to register dbus object%d", ret);
1187 int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path)
1190 dbus_object_handle_s *oh = NULL;
1197 dh = _dbus_handle_get_default_connection();
1199 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1203 if (!dh->list_object) {
1204 _E("list_object is empty");
1208 oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1210 _E("no object with name %s", obj_path);
1214 /* unregister every interface of object*/
1215 for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) {
1216 dbus_interface_s *ih = item->data;
1218 _E("this is error");
1222 /* remove ih from list_ifaces */
1224 item = g_list_previous(item);
1226 /* remove and free link */
1227 oh->list_ifaces = g_list_remove(oh->list_ifaces, ih);
1229 /* free list_methods */
1230 g_list_free(ih->list_methods);
1237 /* unregister object by id */
1238 ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id);
1240 _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id);
1247 add object temporarily.
1248 dbus_handle_register_dbus_object_all register every objects on connection.
1250 return registered method count
1252 int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u)
1255 dbus_object_handle_s *oh = NULL;
1256 dbus_interface_s *ih = NULL;
1259 if (!obj_path || !iface_u) {
1260 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1263 if (iface_u && (!iface_u->name || !iface_u->methods)) {
1264 _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u);
1268 cnt = iface_u->nr_methods;
1271 dh = _dbus_handle_get_default_connection();
1273 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1279 _E("failed to register method. connection is null\n");
1283 /* if there are no object list, just add */
1284 if (!dh->list_object) {
1285 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1286 _E("failed to attach object");
1292 oh = _dbus_handle_lookup_object(dh->list_object, obj_path);
1293 /* if there are no matched object, just add */
1295 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1296 _E("failed to attach object");
1302 /* this is an error, interface must have one or more item ? */
1303 if (!oh->list_ifaces) {
1304 _E("error. list_ifaces is null\n");
1309 ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name);
1310 /* if there are no matched interface, just add */
1312 if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) {
1313 _E("failed to attach object");
1320 1. unregister interface
1321 2. update interface and methods
1322 3. register interface
1325 _E("interface already registered, ignore new interface");
1329 /* attach new methods */
1331 for (int i = 0; i < iface_u->nr_methods; ++i) {
1332 GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method);
1334 //_D("attached %s", iface_u->methods[i].member);
1335 ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i));
1341 ih->modified = TRUE;
1344 /*todo: delete debugging log */
1345 //if (dh && dh->list_object)
1346 // _D("obj list len %d", g_list_length(dh->list_object));
1347 //if (oh && oh->list_ifaces)
1348 // _D("iface list len %d", g_list_length(oh->list_ifaces));
1349 //if (ih && ih->list_methods)
1350 // _D("method list len %d", g_list_length(ih->list_methods));
1355 int dbus_handle_register_dbus_object_all(dbus_handle_h handle)
1358 dbus_object_handle_s *oh = NULL;
1359 dbus_interface_s *ih = NULL;
1363 dh = _dbus_handle_get_default_connection();
1365 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1370 _E("connection is null\n");
1374 if (!dh->list_object) {
1375 _E("obj list is empty");
1379 /*if (dh && dh->list_object)
1380 _D("obj list len %d", g_list_length(dh->list_object));*/
1382 for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) {
1383 oh = (dbus_object_handle_s *)item->data;
1386 _E("something wrong");
1389 if (!oh->list_ifaces) {
1390 _E("path %s: list_ifaces are null", oh->path);
1394 //_D("iface list len %d", g_list_length(oh->list_ifaces));
1396 for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) {
1397 ih = (dbus_interface_s *)li->data;
1399 /* if there are no modification, goto next */
1403 /* todo: if already registered interface, unregister first */
1405 /*_E("interface %s:", ih->name);
1406 if (ih && ih->list_methods)
1407 _D("method list len %d", g_list_length(ih->list_methods));*/
1409 ret = _dbus_handle_register_dbus_object(dh, oh->path, ih);
1411 _E("failed to register dbus object%d", ret);
1418 // todo: delete all updates
1423 guint subscribe_dbus_signal(dbus_handle_h handle, const char *path,
1424 const char *iface, const char *name,
1425 GDBusSignalCallback cb, void *data,
1426 destroy_notified free_func)
1431 dh = _dbus_handle_get_default_connection();
1433 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1439 _E("connection is null. check bus status");
1442 return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, free_func);
1445 void unsubscribe_dbus_signal(dbus_handle_h handle, guint id)
1449 dh = _dbus_handle_get_default_connection();
1451 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1457 _E("connection is null. check bus status");
1461 g_dbus_connection_signal_unsubscribe(dh->conn, id);
1464 static void _signal_reply_sync_cb(GDBusConnection *conn,
1465 const gchar *sender,
1472 sig_ctx *ctx = data;
1474 _E("user data is null");
1478 ctx->param = g_variant_ref(param);
1479 ctx->quit_reason = CTX_QUIT_NORMAL;
1481 if (ctx->timeout_src) {
1482 g_source_destroy(ctx->timeout_src);
1483 ctx->timeout_src = NULL;
1485 g_main_loop_quit(ctx->loop);
1488 sig_ctx *dbus_handle_new_signal_ctx(void)
1492 ctx = (sig_ctx *)malloc(sizeof(sig_ctx));
1494 _E("failed to alloc mem");
1500 ctx->context = g_main_context_new();
1501 if (!ctx->context) {
1502 _E("failed to alloc context");
1506 ctx->loop = g_main_loop_new(ctx->context, FALSE);
1508 _E("failed to alloc main loop");
1509 g_main_context_unref(ctx->context);
1513 ctx->timeout_src = NULL;
1515 ctx->quit_reason = CTX_QUIT_UNKNOWN;
1516 ctx->user_data = NULL;
1521 void dbus_handle_free_signal_ctx(sig_ctx *ctx)
1527 g_variant_unref(ctx->param);
1531 unsubscribe_dbus_signal(NULL, ctx->sig_id);
1534 if (ctx->timeout_src) {
1535 g_source_destroy(ctx->timeout_src);
1536 ctx->timeout_src = NULL;
1539 g_main_context_pop_thread_default(ctx->context);
1540 g_main_context_unref(ctx->context);
1541 ctx->context = NULL;
1544 g_main_loop_unref(ctx->loop);
1550 static gboolean _cb_ctx_timeout(gpointer user_data)
1552 sig_ctx *ctx = user_data;
1555 _E("user_data is null");
1559 ctx->quit_reason = CTX_QUIT_TIMEOUT;
1560 /* if cb return FALSE, source will be destroyed */
1561 ctx->timeout_src = NULL;
1563 unsubscribe_dbus_signal(NULL, ctx->sig_id);
1566 g_main_loop_quit(ctx->loop);
1571 #define CTX_MAX_TIMEOUT 25000
1573 int dbus_handle_signal_ctx_add_timeout(sig_ctx *ctx, int timeout_msec)
1575 GSource *src = NULL;
1579 if (timeout_msec < -1)
1582 if (timeout_msec == -1 || timeout_msec >= CTX_MAX_TIMEOUT)
1583 timeout_msec = CTX_MAX_TIMEOUT;
1585 src = g_timeout_source_new(timeout_msec);
1589 g_source_set_callback(src, _cb_ctx_timeout, ctx, NULL);
1590 g_source_attach(src, ctx->context);
1591 g_source_unref(src);
1593 ctx->timeout_src = src;
1598 guint subscribe_dbus_signal_ctx(dbus_handle_h handle, sig_ctx *ctx,
1599 const char *sender, const char *path,
1600 const char *iface, const char *name,
1601 GDBusSignalCallback _cb)
1606 _E("wrong param ctx is null");
1611 dh = _dbus_handle_get_default_connection();
1613 _E("failed to get default connection, bustype:%d",
1614 (int)dbus_handle_get_default_bus_type());
1620 _E("connection is null. check bus status");
1625 _cb = _signal_reply_sync_cb;
1627 /* change context before subscribe */
1628 g_main_context_push_thread_default(ctx->context);
1630 ctx->sig_id = g_dbus_connection_signal_subscribe(dh->conn,
1631 sender, iface, name, path, NULL,
1632 G_DBUS_SIGNAL_FLAGS_NONE, _cb,
1636 _E("failed to subscribe signal");
1641 int dbus_handle_signal_ctx_wait(sig_ctx *ctx)
1643 if (!ctx || !ctx->loop)
1646 g_main_loop_run(ctx->loop);
1648 _D("quit g_main_loop");
1650 return ctx->quit_reason;
1653 int _check_type_string_is_container(const char *signature)
1658 switch (signature[0]) {
1673 /* todo: looks like garbage... */
1674 static GVariant* _append_variant(const char *signature, const char *param[])
1681 unsigned long long int64_type;
1684 char container[255];// The maximum length of a signature is 255.
1685 const char *sig = signature;
1686 GVariantBuilder *builder = NULL;
1688 if (!signature || !param)
1691 /* workaround for user fault "(i) != i" but we treat this as same signature */
1692 /* G_VARIANT_TYPE("si") return NULL */
1693 /* todo: actually user have to use correct signature */
1694 if (!_check_type_string_is_container(signature)) {
1695 snprintf(container, sizeof(container) - 1, "(%s)", signature);
1698 if (!g_variant_type_is_container(G_VARIANT_TYPE(sig)))
1699 _E("signature (%s) is not container type", signature);
1701 builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
1704 for (ch = (char *)sig, i = 0; i < len; ++i, ++ch) {
1710 bool_type = (atoi(param[pi++]) == 0 ? FALSE : TRUE);
1711 g_variant_builder_add(builder, "b", bool_type);
1714 int_type = atoi(param[pi++]);
1715 g_variant_builder_add(builder, "i", int_type);
1718 int_type = strtoul(param[pi++], NULL, 10);
1719 g_variant_builder_add(builder, "u", int_type);
1722 int64_type = atoll(param[pi++]);
1723 g_variant_builder_add(builder, "t", int64_type);
1726 g_variant_builder_add(builder, "s", param[pi++]);
1732 g_variant_builder_add(builder, "^ay", param[pi++]);
1743 ret = g_variant_builder_end(builder);
1744 g_variant_builder_clear(builder);
1745 g_variant_builder_unref(builder);
1750 int dbus_handle_emit_dbus_signal(const char *dest,
1756 dbus_handle_s *dh = NULL;
1760 dh = _dbus_handle_get_default_connection();
1762 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1766 ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1768 _E("%d %s\n", ret, err ? err->message : "NULL");
1775 int dbus_handle_emit_dbus_signal_sync(const char *dest,
1781 dbus_handle_s *dh = NULL;
1785 dh = _dbus_handle_get_default_connection();
1787 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1791 ret = g_dbus_connection_emit_signal(dh->conn, dest, path, iface, name, param, &err);
1793 _E("%d %s\n", ret, err ? err->message : "NULL");
1797 ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1799 _E("%d %s\n", ret, err ? err->message : "NULL");
1806 int dbus_handle_flush_sync(dbus_handle_h handle)
1813 dh = _dbus_handle_get_default_connection();
1815 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1820 ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err);
1822 _E("%d %s\n", ret, err ? err->message : "NULL");
1829 GVariant *dbus_handle_method_sync_with_reply_var(const char *dest,
1836 GVariant * ret = NULL;
1837 dbus_handle_s *dh = NULL;
1839 if (!dest || !path || !iface || !method) {
1840 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1842 g_variant_unref(var);
1846 dh = _dbus_handle_get_default_connection();
1848 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1850 g_variant_unref(var);
1854 ret = g_dbus_connection_call_sync(dh->conn,
1855 dest, path, iface, method,
1857 G_DBUS_CALL_FLAGS_NONE,
1863 _E("failed to g_dbus_connection_call_sync:%s", err->message);
1864 if (g_error_matches(err, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED))
1865 ret = g_variant_new("(i)", -EPERM);
1871 _E("failed to g_dbus_connection_call_sync");
1879 GVariant *dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path,
1880 const char *iface, const char *method, GVariant *var, int timeout)
1883 GVariant * ret = NULL;
1884 dbus_handle_s *dh = NULL;
1886 if (!dest || !path || !iface || !method) {
1887 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1889 g_variant_unref(var);
1893 dh = _dbus_handle_get_default_connection();
1895 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1897 g_variant_unref(var);
1901 ret = g_dbus_connection_call_sync(dh->conn,
1902 dest, path, iface, method,
1904 G_DBUS_CALL_FLAGS_NONE,
1910 _E("failed to g_dbus_connection_call_sync:%s", err->message);
1913 _E("failed to g_dbus_connection_call_sync");
1921 gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size)
1923 GUnixFDList *fd_list = NULL;
1926 fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation));
1929 _E("failed to g_unix_fd_list_get_length: fd_list is null");
1933 length = g_unix_fd_list_get_length(fd_list);
1935 _E("failed to g_unix_fd_list_get_length: list size is 0");
1941 return g_unix_fd_list_steal_fds(fd_list, NULL);
1944 GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply(const char *dest,
1948 const char *signature,
1949 const char *param[],
1956 GVariant * var = NULL;
1957 GVariant * ret = NULL;
1958 dbus_handle_s *dh = NULL;
1959 GUnixFDList *g_infdlist = NULL;
1960 GUnixFDList *g_outfdlist = NULL;
1962 if (!dest || !path || !iface || !method) {
1963 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
1966 if (in_fdlist && in_size == 0) {
1967 _E("wrong in_fdlist is not null but in_size is 0");
1971 dh = _dbus_handle_get_default_connection();
1973 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
1977 if (signature && param)
1978 var = _append_variant(signature, param);
1982 g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
1984 _E("failed to g_unix_fd_list_new_from_array\n");
1987 //g_infdlist = g_unix_fd_list_new();
1988 //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
1991 ret = g_dbus_connection_call_with_unix_fd_list_sync(dh->conn,
1992 dest, path, iface, method,
1994 G_DBUS_CALL_FLAGS_NONE,
1996 g_infdlist, &g_outfdlist,
2001 _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message);
2004 _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:");
2006 g_variant_unref(var);
2008 g_object_unref(g_infdlist);
2013 /* fds to out array */
2015 *out_size = g_unix_fd_list_get_length(g_outfdlist);
2019 *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
2024 g_object_unref(g_outfdlist);
2029 GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply_var(const char *dest,
2040 GVariant * ret = NULL;
2041 dbus_handle_s *dh = NULL;
2042 GUnixFDList *g_infdlist = NULL;
2043 GUnixFDList *g_outfdlist = NULL;
2045 if (!dest || !path || !iface || !method) {
2046 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2049 if (in_fdlist && in_size == 0) {
2050 _E("wrong in_fdlist is not null but in_size is 0");
2054 dh = _dbus_handle_get_default_connection();
2056 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2062 g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size);
2064 _E("failed to g_unix_fd_list_new_from_array\n");
2067 //g_infdlist = g_unix_fd_list_new();
2068 //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) {
2072 ret = g_dbus_connection_call_with_unix_fd_list_sync(dh->conn,
2073 dest, path, iface, method,
2075 G_DBUS_CALL_FLAGS_NONE,
2077 g_infdlist, &g_outfdlist,
2081 _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message);
2084 _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:");
2086 g_variant_unref(param);
2088 g_object_unref(g_infdlist);
2093 /* copy fds to out array */
2095 *out_size = g_unix_fd_list_get_length(g_outfdlist);
2098 *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL);
2102 g_object_unref(g_outfdlist);
2106 int dbus_handle_method_sync(const char *dest,
2110 const char *signature,
2111 const char *param[])
2114 gboolean result_bool;
2115 GVariant *reply = NULL;
2116 GVariant * var = NULL;
2118 dbus_handle_s *dh = NULL;
2120 if (!dest || !path || !iface || !method) {
2121 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2125 dh = _dbus_handle_get_default_connection();
2127 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2131 if (signature && param)
2132 var = _append_variant(signature, param);
2134 reply = g_dbus_connection_call_sync(dh->conn,
2135 dest, path, iface, method,
2136 var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
2137 if (!reply || err) {
2139 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2142 _E("failed to g_dbus_connection_call_sync");
2143 g_variant_unref(var);
2148 if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
2149 g_variant_get(reply, "(i)", &result);
2150 } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
2151 g_variant_get(reply, "(b)", &result_bool);
2152 result = (int)result_bool;
2157 g_variant_unref(reply);
2162 int dbus_handle_method_sync_var(const char *dest,
2169 gboolean result_bool;
2170 GVariant *reply = NULL;
2172 if (!dest || !path || !iface || !method) {
2173 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2177 reply = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param);
2181 if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) {
2182 g_variant_get(reply, "(i)", &result);
2183 } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) {
2184 g_variant_get(reply, "(b)", &result_bool);
2185 result = (int)result_bool;
2190 g_variant_unref(reply);
2195 int dbus_handle_method_sync_timeout(const char *dest,
2199 const char *signature,
2200 const char *param[],
2203 dbus_handle_s *dh = NULL;
2205 GVariant * var = NULL;
2206 GVariant * reply = NULL;
2209 if (!dest || !path || !iface || !method) {
2210 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2214 dh = _dbus_handle_get_default_connection();
2216 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2220 if (signature && param)
2221 var = _append_variant(signature, param);
2223 reply = g_dbus_connection_call_sync(dh->conn,
2224 dest, path, iface, method,
2226 G_DBUS_CALL_FLAGS_NONE,
2230 if (!reply || err) {
2231 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2236 if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0)
2237 g_variant_get(reply, "(i)", &result);
2241 g_variant_unref(reply);
2246 int dbus_handle_method_async(const char *dest,
2250 const char *signature,
2251 const char *param[])
2253 GVariant * var = NULL;
2254 dbus_handle_s *dh = NULL;
2256 if (!dest || !path || !iface || !method) {
2257 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2261 dh = _dbus_handle_get_default_connection();
2263 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2267 if (signature && param)
2268 var = _append_variant(signature, param);
2270 g_dbus_connection_call(dh->conn,
2271 dest, path, iface, method,
2273 G_DBUS_CALL_FLAGS_NONE,
2282 int dbus_handle_method_async_var(const char *dest,
2288 dbus_handle_s *dh = NULL;
2290 if (!dest || !path || !iface || !method) {
2291 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2295 dh = _dbus_handle_get_default_connection();
2297 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2301 g_dbus_connection_call(dh->conn,
2302 dest, path, iface, method,
2304 G_DBUS_CALL_FLAGS_NONE,
2313 /* callback should free gvariant */
2314 static void _cb_pending(GDBusConnection *conn,
2318 GVariant *reply = NULL;
2320 pending_call_data *data = (pending_call_data *)user_data;
2322 reply = g_dbus_connection_call_finish(conn, res, &err);
2323 if (!reply || err) {
2325 g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
2326 "Error during g_dbus_connection_call");
2328 if (data && data->func)
2329 data->func(NULL, data->data, err);
2333 if (data && data->func)
2334 data->func(reply, data->data, err);
2342 int dbus_handle_method_async_with_reply(const char *dest,
2346 const char *signature,
2347 const char *param[],
2352 dbus_handle_s *dh = NULL;
2353 pending_call_data *pdata = NULL;
2354 GVariant * var = NULL;
2357 if (!dest || !path || !iface || !method) {
2358 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2362 if (timeout_msec < -1) {
2363 _E("wrong timeout %d", timeout_msec);
2367 dh = _dbus_handle_get_default_connection();
2369 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2373 if (signature && param)
2374 var = _append_variant(signature, param);
2377 pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
2386 g_dbus_connection_call(dh->conn,
2387 dest, path, iface, method,
2389 G_DBUS_CALL_FLAGS_NONE,
2392 (GAsyncReadyCallback)_cb_pending,
2398 g_variant_unref(var);
2402 int dbus_handle_method_async_with_reply_var(const char *dest,
2411 dbus_handle_s *dh = NULL;
2412 pending_call_data *pdata = NULL;
2415 if (!dest || !path || !iface || !method) {
2416 _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method);
2420 if (timeout_msec < -1) {
2421 _E("wrong timeout %d", timeout_msec);
2425 dh = _dbus_handle_get_default_connection();
2427 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2432 pdata = (pending_call_data*)malloc(sizeof(pending_call_data));
2441 g_dbus_connection_call(dh->conn,
2442 dest, path, iface, method,
2444 G_DBUS_CALL_FLAGS_NONE,
2447 (GAsyncReadyCallback)_cb_pending,
2453 g_variant_unref(param);
2457 int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender)
2460 GVariant *vret = NULL;
2464 _E("connection is null");
2468 _E("sender is null");
2472 vret = g_dbus_connection_call_sync(conn,
2473 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID",
2474 g_variant_new("(s)", sender), NULL,
2475 G_DBUS_CALL_FLAGS_NONE,
2480 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2485 g_variant_get(vret, "(u)", &pid);
2486 g_variant_unref(vret);
2491 int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender)
2496 dh = _dbus_handle_get_default_connection();
2498 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2503 _E("wrong dbus handle. connection is null");
2508 return dbus_connection_get_sender_pid(dh->conn, sender);
2511 int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds)
2514 GVariant *vret = NULL;
2516 GVariantIter *iter = NULL;
2521 dh = _dbus_handle_get_default_connection();
2523 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2527 vret = g_dbus_connection_call_sync(dh->conn,
2530 DBUS_INTERFACE_NAME,
2531 "GetConnectionCredentials",
2532 g_variant_new("(s)", name),
2534 G_DBUS_CALL_FLAGS_NONE,
2539 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2543 g_variant_get(vret, "(a{sv})", &iter);
2545 while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) {
2546 if (!g_strcmp0(item, "UnixUserID")) {
2547 g_variant_get(sub, "u", &creds->uid);
2548 //_D("UnixUserID %u", creds->uid);
2549 } else if (!g_strcmp0(item, "ProcessID")) {
2550 g_variant_get(sub, "u", &creds->pid);
2551 //_D("ProcessID %u", creds->pid);
2552 } else if (!g_strcmp0(item, "LinuxSecurityLabel")) {
2553 g_variant_get(sub, "^ay", &creds->sec_label);
2554 //_D("%s", creds->sec_label);
2559 g_variant_iter_free(iter);
2561 g_variant_unref(vret);
2566 void _destroy_notify_watch_name(gpointer data)
2572 int dbus_handle_watch_name(const char *name,
2573 GBusNameAppearedCallback name_appeared_handler,
2574 GBusNameVanishedCallback name_vanished_handler,
2576 GDestroyNotify user_data_free_func)
2581 _E("wrong name name is null");
2584 if (!name_appeared_handler && !name_vanished_handler) {
2585 _E("both function pointers are null");
2589 id = g_bus_watch_name(dbus_handle_get_default_bus_type(),
2591 G_BUS_NAME_WATCHER_FLAGS_NONE,
2592 name_appeared_handler,
2593 name_vanished_handler,
2595 user_data_free_func ? user_data_free_func : _destroy_notify_watch_name);
2597 _E("failed to g_bus_watch_name");
2604 void dbus_handle_unwatch_name(guint id)
2607 _E("wrong id %d", id);
2610 g_bus_unwatch_name(id);
2613 int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size)
2616 char buf[PATH_MAX + 1];
2619 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
2620 fd = open(buf, O_RDONLY);
2626 ret = read(fd, buf, PATH_MAX);
2631 buf[PATH_MAX] = '\0';
2633 filename = strrchr(buf, '/');
2634 if (filename == NULL)
2637 filename = filename + 1;
2639 if (cmdline_size < strlen(filename) + 1) {
2644 strncpy(cmdline, filename, cmdline_size - 1);
2645 cmdline[cmdline_size - 1] = '\0';
2650 char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name)
2654 GVariant *vret = NULL;
2655 GVariantIter *iter = NULL;
2656 gchar **strv = NULL;
2661 _E("wrong parameter bus_name is null");
2666 dh = _dbus_handle_get_default_connection();
2668 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2673 vret = g_dbus_connection_call_sync(dh->conn,
2674 "org.freedesktop.DBus",
2676 "org.freedesktop.DBus",
2678 g_variant_new("(s)", bus_name),
2680 G_DBUS_CALL_FLAGS_NONE,
2685 _E("failed to g_dbus_connection_call_sync:%s", err->message);
2690 g_variant_get(vret, "(as)", &iter);
2691 strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1);
2694 while (g_variant_iter_loop(iter, "s", &str))
2695 strv[i++] = g_strdup(str);
2698 g_variant_iter_free(iter);
2699 g_variant_unref(vret);
2704 void dbus_handle_check_owner_name(dbus_handle_h handle, const char *owner_name)
2707 char exe_name[PATH_MAX];
2713 dh = _dbus_handle_get_default_connection();
2715 _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type());
2720 strv = dbus_handle_get_owner_list(dh, owner_name);
2722 _E("failed to get owner list of %s", owner_name);
2726 for (i = 0; strv[i] != NULL; ++i) {
2727 pid = dbus_handle_get_sender_pid(dh, strv[i]);
2728 if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0)
2730 _I("%s(%d)", exe_name, pid);
2736 int check_systemd_active(void)
2739 GVariant *msg = NULL;
2740 GVariant *var = NULL;
2743 _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState");
2745 msg = dbus_handle_method_sync_with_reply_var("org.freedesktop.systemd1",
2746 "/org/freedesktop/systemd1/unit/default_2etarget",
2747 "org.freedesktop.DBus.Properties",
2749 g_variant_new("(ss)", "org.freedesktop.systemd1.Unit", "ActiveState"));
2753 if (!g_variant_get_safe(msg, "(v)", &var)) {
2754 _E("reply is not variant type");
2758 if (!g_variant_get_safe(var, "(s)", &state)) {
2759 _E("variant doesn't have string (%s)", g_variant_get_type_string(var));
2764 if (strncmp(state, "active", 6) == 0)
2770 g_variant_unref(var);
2772 g_variant_unref(msg);
2777 GVariant *dbus_handle_make_simple_array(const char *sig, int *param)
2779 GVariantBuilder *builder = NULL;
2780 GVariant *var = NULL;
2784 builder = g_variant_builder_new(G_VARIANT_TYPE(sig));
2786 _E("failed to g_variant_builder_new");
2791 g_variant_builder_add(builder, "i", param[i++]);
2793 snprintf(format, sizeof(format) - 1, "(%s)", sig);
2794 var = g_variant_new(format, builder);
2795 g_variant_builder_unref(builder);