Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / gdbus / object.c
1 /*
2  *
3  *  D-Bus helper library
4  *
5  *  Copyright (C) 2004-2011  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <glib.h>
32 #include <dbus/dbus.h>
33
34 #include "gdbus.h"
35
36 #ifdef __TIZEN_PATCH__
37 #if 0
38 #include <syslog.h>
39 static void gdbus_dbg(const char *format, ...)
40 {
41         va_list ap;
42
43         va_start(ap, format);
44
45         vsyslog(LOG_DEBUG, format, ap);
46
47         va_end(ap);
48 }
49 #endif
50 #else
51 #define info(fmt...)
52 #endif
53
54 #define error(fmt...)
55 #define debug(fmt...)
56
57 #define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager"
58
59 #ifndef DBUS_ERROR_UNKNOWN_PROPERTY
60 #define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
61 #endif
62
63 #ifndef DBUS_ERROR_PROPERTY_READ_ONLY
64 #define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
65 #endif
66
67 struct generic_data {
68         unsigned int refcount;
69         DBusConnection *conn;
70         char *path;
71         GSList *interfaces;
72         GSList *objects;
73         GSList *added;
74         GSList *removed;
75         guint process_id;
76         gboolean pending_prop;
77         char *introspect;
78         struct generic_data *parent;
79 };
80
81 struct interface_data {
82         char *name;
83         const GDBusMethodTable *methods;
84         const GDBusSignalTable *signals;
85         const GDBusPropertyTable *properties;
86         GSList *pending_prop;
87         void *user_data;
88         GDBusDestroyFunction destroy;
89 };
90
91 struct security_data {
92         GDBusPendingReply pending;
93         DBusMessage *message;
94         const GDBusMethodTable *method;
95         void *iface_user_data;
96 };
97
98 struct property_data {
99         DBusConnection *conn;
100         GDBusPendingPropertySet id;
101         DBusMessage *message;
102 };
103
104 static int global_flags = 0;
105 static struct generic_data *root;
106 static GSList *pending = NULL;
107
108 #ifdef __TIZEN_PATCH__
109 #define ADAPTER_INTERFACE       "org.bluez.Adapter1"
110
111 static char *adapter_path = NULL;
112 #endif
113
114 static gboolean process_changes(gpointer user_data);
115 static void process_properties_from_interface(struct generic_data *data,
116                                                 struct interface_data *iface);
117 static void process_property_changes(struct generic_data *data);
118
119 static void print_arguments(GString *gstr, const GDBusArgInfo *args,
120                                                 const char *direction)
121 {
122         for (; args && args->name; args++) {
123                 g_string_append_printf(gstr,
124                                         "<arg name=\"%s\" type=\"%s\"",
125                                         args->name, args->signature);
126
127                 if (direction)
128                         g_string_append_printf(gstr,
129                                         " direction=\"%s\"/>\n", direction);
130                 else
131                         g_string_append_printf(gstr, "/>\n");
132
133         }
134 }
135
136 #define G_DBUS_ANNOTATE(name_, value_)                          \
137         "<annotation name=\"org.freedesktop.DBus." name_ "\" "  \
138         "value=\"" value_ "\"/>"
139
140 #define G_DBUS_ANNOTATE_DEPRECATED \
141         G_DBUS_ANNOTATE("Deprecated", "true")
142
143 #define G_DBUS_ANNOTATE_NOREPLY \
144         G_DBUS_ANNOTATE("Method.NoReply", "true")
145
146 static gboolean check_experimental(int flags, int flag)
147 {
148         if (!(flags & flag))
149                 return FALSE;
150
151         return !(global_flags & G_DBUS_FLAG_ENABLE_EXPERIMENTAL);
152 }
153
154 static void generate_interface_xml(GString *gstr, struct interface_data *iface)
155 {
156         const GDBusMethodTable *method;
157         const GDBusSignalTable *signal;
158         const GDBusPropertyTable *property;
159
160         for (method = iface->methods; method && method->name; method++) {
161                 if (check_experimental(method->flags,
162                                         G_DBUS_METHOD_FLAG_EXPERIMENTAL))
163                         continue;
164
165                 g_string_append_printf(gstr, "<method name=\"%s\">",
166                                                                 method->name);
167                 print_arguments(gstr, method->in_args, "in");
168                 print_arguments(gstr, method->out_args, "out");
169
170                 if (method->flags & G_DBUS_METHOD_FLAG_DEPRECATED)
171                         g_string_append_printf(gstr,
172                                                 G_DBUS_ANNOTATE_DEPRECATED);
173
174                 if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY)
175                         g_string_append_printf(gstr, G_DBUS_ANNOTATE_NOREPLY);
176
177                 g_string_append_printf(gstr, "</method>");
178         }
179
180         for (signal = iface->signals; signal && signal->name; signal++) {
181                 if (check_experimental(signal->flags,
182                                         G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
183                         continue;
184
185                 g_string_append_printf(gstr, "<signal name=\"%s\">",
186                                                                 signal->name);
187                 print_arguments(gstr, signal->args, NULL);
188
189                 if (signal->flags & G_DBUS_SIGNAL_FLAG_DEPRECATED)
190                         g_string_append_printf(gstr,
191                                                 G_DBUS_ANNOTATE_DEPRECATED);
192
193                 g_string_append_printf(gstr, "</signal>\n");
194         }
195
196         for (property = iface->properties; property && property->name;
197                                                                 property++) {
198                 if (check_experimental(property->flags,
199                                         G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
200                         continue;
201
202                 g_string_append_printf(gstr, "<property name=\"%s\""
203                                         " type=\"%s\" access=\"%s%s\">",
204                                         property->name, property->type,
205                                         property->get ? "read" : "",
206                                         property->set ? "write" : "");
207
208                 if (property->flags & G_DBUS_PROPERTY_FLAG_DEPRECATED)
209                         g_string_append_printf(gstr,
210                                                 G_DBUS_ANNOTATE_DEPRECATED);
211
212                 g_string_append_printf(gstr, "</property>");
213         }
214 }
215
216 static void generate_introspection_xml(DBusConnection *conn,
217                                 struct generic_data *data, const char *path)
218 {
219         GSList *list;
220         GString *gstr;
221         char **children;
222         int i;
223
224         g_free(data->introspect);
225
226         gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
227
228         g_string_append_printf(gstr, "<node>");
229
230         for (list = data->interfaces; list; list = list->next) {
231                 struct interface_data *iface = list->data;
232
233                 g_string_append_printf(gstr, "<interface name=\"%s\">",
234                                                                 iface->name);
235
236                 generate_interface_xml(gstr, iface);
237
238                 g_string_append_printf(gstr, "</interface>");
239         }
240
241         if (!dbus_connection_list_registered(conn, path, &children))
242                 goto done;
243
244         for (i = 0; children[i]; i++)
245                 g_string_append_printf(gstr, "<node name=\"%s\"/>",
246                                                                 children[i]);
247
248         dbus_free_string_array(children);
249
250 done:
251         g_string_append_printf(gstr, "</node>");
252
253         data->introspect = g_string_free(gstr, FALSE);
254 }
255
256 static DBusMessage *introspect(DBusConnection *connection,
257                                 DBusMessage *message, void *user_data)
258 {
259         struct generic_data *data = user_data;
260         DBusMessage *reply;
261
262         if (data->introspect == NULL)
263                 generate_introspection_xml(connection, data,
264                                                 dbus_message_get_path(message));
265
266         reply = dbus_message_new_method_return(message);
267         if (reply == NULL)
268                 return NULL;
269
270         dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect,
271                                         DBUS_TYPE_INVALID);
272
273         return reply;
274 }
275
276 static DBusHandlerResult process_message(DBusConnection *connection,
277                         DBusMessage *message, const GDBusMethodTable *method,
278                                                         void *iface_user_data)
279 {
280         DBusMessage *reply;
281
282         reply = method->function(connection, message, iface_user_data);
283
284         if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY ||
285                                         dbus_message_get_no_reply(message)) {
286                 if (reply != NULL)
287                         dbus_message_unref(reply);
288                 return DBUS_HANDLER_RESULT_HANDLED;
289         }
290
291         if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
292                 if (reply == NULL)
293                         return DBUS_HANDLER_RESULT_HANDLED;
294         }
295
296         if (reply == NULL)
297                 return DBUS_HANDLER_RESULT_NEED_MEMORY;
298
299         g_dbus_send_message(connection, reply);
300
301         return DBUS_HANDLER_RESULT_HANDLED;
302 }
303
304 static GDBusPendingReply next_pending = 1;
305 static GSList *pending_security = NULL;
306
307 static const GDBusSecurityTable *security_table = NULL;
308
309 void g_dbus_pending_success(DBusConnection *connection,
310                                         GDBusPendingReply pending)
311 {
312         GSList *list;
313
314         for (list = pending_security; list; list = list->next) {
315                 struct security_data *secdata = list->data;
316
317                 if (secdata->pending != pending)
318                         continue;
319
320                 pending_security = g_slist_remove(pending_security, secdata);
321
322                 process_message(connection, secdata->message,
323                                 secdata->method, secdata->iface_user_data);
324
325                 dbus_message_unref(secdata->message);
326                 g_free(secdata);
327                 return;
328         }
329 }
330
331 void g_dbus_pending_error_valist(DBusConnection *connection,
332                                 GDBusPendingReply pending, const char *name,
333                                         const char *format, va_list args)
334 {
335         GSList *list;
336
337         for (list = pending_security; list; list = list->next) {
338                 struct security_data *secdata = list->data;
339
340                 if (secdata->pending != pending)
341                         continue;
342
343                 pending_security = g_slist_remove(pending_security, secdata);
344
345                 g_dbus_send_error_valist(connection, secdata->message,
346                                                         name, format, args);
347
348                 dbus_message_unref(secdata->message);
349                 g_free(secdata);
350                 return;
351         }
352 }
353
354 void g_dbus_pending_error(DBusConnection *connection,
355                                 GDBusPendingReply pending,
356                                 const char *name, const char *format, ...)
357 {
358         va_list args;
359
360         va_start(args, format);
361
362         g_dbus_pending_error_valist(connection, pending, name, format, args);
363
364         va_end(args);
365 }
366
367 int polkit_check_authorization(DBusConnection *conn,
368                                 const char *action, gboolean interaction,
369                                 void (*function) (dbus_bool_t authorized,
370                                                         void *user_data),
371                                                 void *user_data, int timeout);
372
373 struct builtin_security_data {
374         DBusConnection *conn;
375         GDBusPendingReply pending;
376 };
377
378 static void builtin_security_result(dbus_bool_t authorized, void *user_data)
379 {
380         struct builtin_security_data *data = user_data;
381
382         if (authorized == TRUE)
383                 g_dbus_pending_success(data->conn, data->pending);
384         else
385                 g_dbus_pending_error(data->conn, data->pending,
386                                                 DBUS_ERROR_AUTH_FAILED, NULL);
387
388         g_free(data);
389 }
390
391 static void builtin_security_function(DBusConnection *conn,
392                                                 const char *action,
393                                                 gboolean interaction,
394                                                 GDBusPendingReply pending)
395 {
396         struct builtin_security_data *data;
397
398         data = g_new0(struct builtin_security_data, 1);
399         data->conn = conn;
400         data->pending = pending;
401
402         if (polkit_check_authorization(conn, action, interaction,
403                                 builtin_security_result, data, 30000) < 0)
404                 g_dbus_pending_error(conn, pending, NULL, NULL);
405 }
406
407 static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
408                         const GDBusMethodTable *method, void *iface_user_data)
409 {
410         const GDBusSecurityTable *security;
411
412         for (security = security_table; security && security->privilege;
413                                                                 security++) {
414                 struct security_data *secdata;
415                 gboolean interaction;
416
417                 if (security->privilege != method->privilege)
418                         continue;
419
420                 secdata = g_new(struct security_data, 1);
421                 secdata->pending = next_pending++;
422                 secdata->message = dbus_message_ref(msg);
423                 secdata->method = method;
424                 secdata->iface_user_data = iface_user_data;
425
426                 pending_security = g_slist_prepend(pending_security, secdata);
427
428                 if (security->flags & G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION)
429                         interaction = TRUE;
430                 else
431                         interaction = FALSE;
432
433                 if (!(security->flags & G_DBUS_SECURITY_FLAG_BUILTIN) &&
434                                                         security->function)
435                         security->function(conn, security->action,
436                                                 interaction, secdata->pending);
437                 else
438                         builtin_security_function(conn, security->action,
439                                                 interaction, secdata->pending);
440
441                 return TRUE;
442         }
443
444         return FALSE;
445 }
446
447 static GDBusPendingPropertySet next_pending_property = 1;
448 static GSList *pending_property_set;
449
450 static struct property_data *remove_pending_property_data(
451                                                 GDBusPendingPropertySet id)
452 {
453         struct property_data *propdata;
454         GSList *l;
455
456         for (l = pending_property_set; l != NULL; l = l->next) {
457                 propdata = l->data;
458                 if (propdata->id != id)
459                         continue;
460
461                 break;
462         }
463
464         if (l == NULL)
465                 return NULL;
466
467         pending_property_set = g_slist_delete_link(pending_property_set, l);
468
469         return propdata;
470 }
471
472 void g_dbus_pending_property_success(GDBusPendingPropertySet id)
473 {
474         struct property_data *propdata;
475
476         propdata = remove_pending_property_data(id);
477         if (propdata == NULL)
478                 return;
479
480         g_dbus_send_reply(propdata->conn, propdata->message,
481                                                         DBUS_TYPE_INVALID);
482         dbus_message_unref(propdata->message);
483         g_free(propdata);
484 }
485
486 void g_dbus_pending_property_error_valist(GDBusPendingReply id,
487                                         const char *name, const char *format,
488                                         va_list args)
489 {
490         struct property_data *propdata;
491
492         propdata = remove_pending_property_data(id);
493         if (propdata == NULL)
494                 return;
495
496         g_dbus_send_error_valist(propdata->conn, propdata->message, name,
497                                                                 format, args);
498
499         dbus_message_unref(propdata->message);
500         g_free(propdata);
501 }
502
503 void g_dbus_pending_property_error(GDBusPendingReply id, const char *name,
504                                                 const char *format, ...)
505 {
506         va_list args;
507
508         va_start(args, format);
509
510         g_dbus_pending_property_error_valist(id, name, format, args);
511
512         va_end(args);
513 }
514
515 static void reset_parent(gpointer data, gpointer user_data)
516 {
517         struct generic_data *child = data;
518         struct generic_data *parent = user_data;
519
520         child->parent = parent;
521 }
522
523 static void append_property(struct interface_data *iface,
524                         const GDBusPropertyTable *p, DBusMessageIter *dict)
525 {
526         DBusMessageIter entry, value;
527
528         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL,
529                                                                 &entry);
530         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &p->name);
531         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, p->type,
532                                                                 &value);
533
534         p->get(p, &value, iface->user_data);
535
536         dbus_message_iter_close_container(&entry, &value);
537         dbus_message_iter_close_container(dict, &entry);
538 }
539
540 static void append_properties(struct interface_data *data,
541                                                         DBusMessageIter *iter)
542 {
543         DBusMessageIter dict;
544         const GDBusPropertyTable *p;
545
546         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
547                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
548                                 DBUS_TYPE_STRING_AS_STRING
549                                 DBUS_TYPE_VARIANT_AS_STRING
550                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
551
552         for (p = data->properties; p && p->name; p++) {
553                 if (check_experimental(p->flags,
554                                         G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
555                         continue;
556
557                 if (p->get == NULL)
558                         continue;
559
560                 if (p->exists != NULL && !p->exists(p, data->user_data))
561                         continue;
562
563                 append_property(data, p, &dict);
564         }
565
566         dbus_message_iter_close_container(iter, &dict);
567 }
568
569 static void append_interface(gpointer data, gpointer user_data)
570 {
571         struct interface_data *iface = data;
572         DBusMessageIter *array = user_data;
573         DBusMessageIter entry;
574
575         dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
576                                                                 &entry);
577         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &iface->name);
578         append_properties(data, &entry);
579         dbus_message_iter_close_container(array, &entry);
580 }
581
582 static void emit_interfaces_added(struct generic_data *data)
583 {
584         DBusMessage *signal;
585         DBusMessageIter iter, array;
586
587         if (root == NULL || data == root)
588                 return;
589
590         signal = dbus_message_new_signal(root->path,
591                                         DBUS_INTERFACE_OBJECT_MANAGER,
592                                         "InterfacesAdded");
593         if (signal == NULL)
594                 return;
595
596         dbus_message_iter_init_append(signal, &iter);
597         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
598                                                                 &data->path);
599
600         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
601                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
602                                 DBUS_TYPE_STRING_AS_STRING
603                                 DBUS_TYPE_ARRAY_AS_STRING
604                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
605                                 DBUS_TYPE_STRING_AS_STRING
606                                 DBUS_TYPE_VARIANT_AS_STRING
607                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
608                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
609
610         g_slist_foreach(data->added, append_interface, &array);
611         g_slist_free(data->added);
612         data->added = NULL;
613
614         dbus_message_iter_close_container(&iter, &array);
615
616         /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
617         dbus_connection_send(data->conn, signal, NULL);
618         dbus_message_unref(signal);
619 }
620
621 static struct interface_data *find_interface(GSList *interfaces,
622                                                 const char *name)
623 {
624         GSList *list;
625
626         if (name == NULL)
627                 return NULL;
628
629         for (list = interfaces; list; list = list->next) {
630                 struct interface_data *iface = list->data;
631                 if (!strcmp(name, iface->name))
632                         return iface;
633         }
634
635         return NULL;
636 }
637
638 static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args,
639                                                         DBusMessage *message)
640 {
641         const char *sig = dbus_message_get_signature(message);
642         const char *p = NULL;
643
644         for (; args && args->signature && *sig; args++) {
645                 p = args->signature;
646
647                 for (; *sig && *p; sig++, p++) {
648                         if (*p != *sig)
649                                 return FALSE;
650                 }
651         }
652
653         if (*sig || (p && *p) || (args && args->signature))
654                 return FALSE;
655
656         return TRUE;
657 }
658
659 static void add_pending(struct generic_data *data)
660 {
661         if (data->process_id > 0)
662                 return;
663
664         data->process_id = g_idle_add(process_changes, data);
665
666         pending = g_slist_append(pending, data);
667 }
668
669 static gboolean remove_interface(struct generic_data *data, const char *name)
670 {
671         struct interface_data *iface;
672
673         iface = find_interface(data->interfaces, name);
674         if (iface == NULL)
675                 return FALSE;
676
677         process_properties_from_interface(data, iface);
678
679         data->interfaces = g_slist_remove(data->interfaces, iface);
680
681 #ifdef __TIZEN_PATCH__
682         if (g_strcmp0(iface->name, ADAPTER_INTERFACE) == 0) {
683                 g_free(adapter_path);
684                 adapter_path = NULL;
685         }
686 #endif
687
688         if (iface->destroy) {
689                 iface->destroy(iface->user_data);
690                 iface->user_data = NULL;
691         }
692
693         /*
694          * Interface being removed was just added, on the same mainloop
695          * iteration? Don't send any signal
696          */
697         if (g_slist_find(data->added, iface)) {
698                 data->added = g_slist_remove(data->added, iface);
699                 g_free(iface->name);
700                 g_free(iface);
701                 return TRUE;
702         }
703
704         if (data->parent == NULL) {
705                 g_free(iface->name);
706                 g_free(iface);
707                 return TRUE;
708         }
709
710         data->removed = g_slist_prepend(data->removed, iface->name);
711         g_free(iface);
712
713         add_pending(data);
714
715         return TRUE;
716 }
717
718 static struct generic_data *invalidate_parent_data(DBusConnection *conn,
719                                                 const char *child_path)
720 {
721         struct generic_data *data = NULL, *child = NULL, *parent = NULL;
722         char *parent_path, *slash;
723
724         parent_path = g_strdup(child_path);
725         slash = strrchr(parent_path, '/');
726         if (slash == NULL)
727                 goto done;
728
729         if (slash == parent_path && parent_path[1] != '\0')
730                 parent_path[1] = '\0';
731         else
732                 *slash = '\0';
733
734         if (!strlen(parent_path))
735                 goto done;
736
737         if (dbus_connection_get_object_path_data(conn, parent_path,
738                                                         (void *) &data) == FALSE) {
739                 goto done;
740         }
741
742         parent = invalidate_parent_data(conn, parent_path);
743
744         if (data == NULL) {
745                 data = parent;
746                 if (data == NULL)
747                         goto done;
748         }
749
750         g_free(data->introspect);
751         data->introspect = NULL;
752
753         if (!dbus_connection_get_object_path_data(conn, child_path,
754                                                         (void *) &child))
755                 goto done;
756
757         if (child == NULL || g_slist_find(data->objects, child) != NULL)
758                 goto done;
759
760         data->objects = g_slist_prepend(data->objects, child);
761         child->parent = data;
762
763 done:
764         g_free(parent_path);
765         return data;
766 }
767
768 static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *properties,
769                                                         const char *name)
770 {
771         const GDBusPropertyTable *p;
772
773         for (p = properties; p && p->name; p++) {
774                 if (strcmp(name, p->name) != 0)
775                         continue;
776
777                 if (check_experimental(p->flags,
778                                         G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
779                         break;
780
781                 return p;
782         }
783
784         return NULL;
785 }
786
787 static DBusMessage *properties_get(DBusConnection *connection,
788                                         DBusMessage *message, void *user_data)
789 {
790         struct generic_data *data = user_data;
791         struct interface_data *iface;
792         const GDBusPropertyTable *property;
793         const char *interface, *name;
794         DBusMessageIter iter, value;
795         DBusMessage *reply;
796
797         if (!dbus_message_get_args(message, NULL,
798                                         DBUS_TYPE_STRING, &interface,
799                                         DBUS_TYPE_STRING, &name,
800                                         DBUS_TYPE_INVALID))
801                 return NULL;
802
803         iface = find_interface(data->interfaces, interface);
804         if (iface == NULL)
805                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
806                                 "No such interface '%s'", interface);
807
808         property = find_property(iface->properties, name);
809         if (property == NULL)
810                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
811                                 "No such property '%s'", name);
812
813         if (property->exists != NULL &&
814                         !property->exists(property, iface->user_data))
815                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
816                                         "No such property '%s'", name);
817
818         if (property->get == NULL)
819                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
820                                 "Property '%s' is not readable", name);
821
822         reply = dbus_message_new_method_return(message);
823         if (reply == NULL)
824                 return NULL;
825
826         dbus_message_iter_init_append(reply, &iter);
827         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
828                                                 property->type, &value);
829
830         if (!property->get(property, &value, iface->user_data)) {
831                 dbus_message_unref(reply);
832                 return NULL;
833         }
834
835         dbus_message_iter_close_container(&iter, &value);
836
837         return reply;
838 }
839
840 static DBusMessage *properties_get_all(DBusConnection *connection,
841                                         DBusMessage *message, void *user_data)
842 {
843         struct generic_data *data = user_data;
844         struct interface_data *iface;
845         const char *interface;
846         DBusMessageIter iter;
847         DBusMessage *reply;
848
849         if (!dbus_message_get_args(message, NULL,
850                                         DBUS_TYPE_STRING, &interface,
851                                         DBUS_TYPE_INVALID))
852                 return NULL;
853
854         iface = find_interface(data->interfaces, interface);
855         if (iface == NULL)
856                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
857                                         "No such interface '%s'", interface);
858
859         reply = dbus_message_new_method_return(message);
860         if (reply == NULL)
861                 return NULL;
862
863         dbus_message_iter_init_append(reply, &iter);
864
865         append_properties(iface, &iter);
866
867         return reply;
868 }
869
870 static DBusMessage *properties_set(DBusConnection *connection,
871                                         DBusMessage *message, void *user_data)
872 {
873         struct generic_data *data = user_data;
874         DBusMessageIter iter, sub;
875         struct interface_data *iface;
876         const GDBusPropertyTable *property;
877         const char *name, *interface;
878         struct property_data *propdata;
879         gboolean valid_signature;
880         char *signature;
881
882         if (!dbus_message_iter_init(message, &iter))
883                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
884                                                         "No arguments given");
885
886         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
887                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
888                                         "Invalid argument type: '%c'",
889                                         dbus_message_iter_get_arg_type(&iter));
890
891         dbus_message_iter_get_basic(&iter, &interface);
892         dbus_message_iter_next(&iter);
893
894         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
895                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
896                                         "Invalid argument type: '%c'",
897                                         dbus_message_iter_get_arg_type(&iter));
898
899         dbus_message_iter_get_basic(&iter, &name);
900         dbus_message_iter_next(&iter);
901
902         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
903                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
904                                         "Invalid argument type: '%c'",
905                                         dbus_message_iter_get_arg_type(&iter));
906
907         dbus_message_iter_recurse(&iter, &sub);
908
909         iface = find_interface(data->interfaces, interface);
910         if (iface == NULL)
911                 return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
912                                         "No such interface '%s'", interface);
913
914         property = find_property(iface->properties, name);
915         if (property == NULL)
916                 return g_dbus_create_error(message,
917                                                 DBUS_ERROR_UNKNOWN_PROPERTY,
918                                                 "No such property '%s'", name);
919
920         if (property->set == NULL)
921                 return g_dbus_create_error(message,
922                                         DBUS_ERROR_PROPERTY_READ_ONLY,
923                                         "Property '%s' is not writable", name);
924
925         if (property->exists != NULL &&
926                         !property->exists(property, iface->user_data))
927                 return g_dbus_create_error(message,
928                                                 DBUS_ERROR_UNKNOWN_PROPERTY,
929                                                 "No such property '%s'", name);
930
931         signature = dbus_message_iter_get_signature(&sub);
932         valid_signature = strcmp(signature, property->type) ? FALSE : TRUE;
933         dbus_free(signature);
934         if (!valid_signature)
935                 return g_dbus_create_error(message,
936                                         DBUS_ERROR_INVALID_SIGNATURE,
937                                         "Invalid signature for '%s'", name);
938
939         propdata = g_new(struct property_data, 1);
940         propdata->id = next_pending_property++;
941         propdata->message = dbus_message_ref(message);
942         propdata->conn = connection;
943         pending_property_set = g_slist_prepend(pending_property_set, propdata);
944
945         property->set(property, &sub, propdata->id, iface->user_data);
946
947         return NULL;
948 }
949
950 static const GDBusMethodTable properties_methods[] = {
951         { GDBUS_METHOD("Get",
952                         GDBUS_ARGS({ "interface", "s" }, { "name", "s" }),
953                         GDBUS_ARGS({ "value", "v" }),
954                         properties_get) },
955         { GDBUS_ASYNC_METHOD("Set",
956                         GDBUS_ARGS({ "interface", "s" }, { "name", "s" },
957                                                         { "value", "v" }),
958                         NULL,
959                         properties_set) },
960         { GDBUS_METHOD("GetAll",
961                         GDBUS_ARGS({ "interface", "s" }),
962                         GDBUS_ARGS({ "properties", "a{sv}" }),
963                         properties_get_all) },
964         { }
965 };
966
967 static const GDBusSignalTable properties_signals[] = {
968         { GDBUS_SIGNAL("PropertiesChanged",
969                         GDBUS_ARGS({ "interface", "s" },
970                                         { "changed_properties", "a{sv}" },
971                                         { "invalidated_properties", "as"})) },
972         { }
973 };
974
975 static void append_name(gpointer data, gpointer user_data)
976 {
977         char *name = data;
978         DBusMessageIter *iter = user_data;
979
980         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &name);
981 }
982
983 static void emit_interfaces_removed(struct generic_data *data)
984 {
985         DBusMessage *signal;
986         DBusMessageIter iter, array;
987
988         if (root == NULL || data == root)
989                 return;
990
991         signal = dbus_message_new_signal(root->path,
992                                         DBUS_INTERFACE_OBJECT_MANAGER,
993                                         "InterfacesRemoved");
994         if (signal == NULL)
995                 return;
996
997         dbus_message_iter_init_append(signal, &iter);
998         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
999                                                                 &data->path);
1000         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1001                                         DBUS_TYPE_STRING_AS_STRING, &array);
1002
1003         g_slist_foreach(data->removed, append_name, &array);
1004         g_slist_free_full(data->removed, g_free);
1005         data->removed = NULL;
1006
1007         dbus_message_iter_close_container(&iter, &array);
1008
1009         /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
1010         dbus_connection_send(data->conn, signal, NULL);
1011         dbus_message_unref(signal);
1012 }
1013
1014 static void remove_pending(struct generic_data *data)
1015 {
1016         if (data->process_id > 0) {
1017                 g_source_remove(data->process_id);
1018                 data->process_id = 0;
1019         }
1020
1021         pending = g_slist_remove(pending, data);
1022 }
1023
1024 static gboolean process_changes(gpointer user_data)
1025 {
1026         struct generic_data *data = user_data;
1027
1028         remove_pending(data);
1029
1030         if (data->added != NULL)
1031                 emit_interfaces_added(data);
1032
1033         /* Flush pending properties */
1034         if (data->pending_prop == TRUE)
1035                 process_property_changes(data);
1036
1037         if (data->removed != NULL)
1038                 emit_interfaces_removed(data);
1039
1040         data->process_id = 0;
1041
1042         return FALSE;
1043 }
1044
1045 static void generic_unregister(DBusConnection *connection, void *user_data)
1046 {
1047         struct generic_data *data = user_data;
1048         struct generic_data *parent = data->parent;
1049
1050         if (parent != NULL)
1051                 parent->objects = g_slist_remove(parent->objects, data);
1052
1053         if (data->process_id > 0) {
1054                 g_source_remove(data->process_id);
1055                 data->process_id = 0;
1056                 process_changes(data);
1057         }
1058
1059         g_slist_foreach(data->objects, reset_parent, data->parent);
1060         g_slist_free(data->objects);
1061
1062         dbus_connection_unref(data->conn);
1063         g_free(data->introspect);
1064         g_free(data->path);
1065         g_free(data);
1066 }
1067
1068 static DBusHandlerResult generic_message(DBusConnection *connection,
1069                                         DBusMessage *message, void *user_data)
1070 {
1071         struct generic_data *data = user_data;
1072         struct interface_data *iface;
1073         const GDBusMethodTable *method;
1074         const char *interface;
1075
1076         interface = dbus_message_get_interface(message);
1077
1078         iface = find_interface(data->interfaces, interface);
1079         if (iface == NULL)
1080                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1081
1082         for (method = iface->methods; method &&
1083                         method->name && method->function; method++) {
1084
1085                 if (dbus_message_is_method_call(message, iface->name,
1086                                                         method->name) == FALSE)
1087                         continue;
1088
1089                 if (check_experimental(method->flags,
1090                                         G_DBUS_METHOD_FLAG_EXPERIMENTAL))
1091                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1092
1093                 if (g_dbus_args_have_signature(method->in_args,
1094                                                         message) == FALSE)
1095                         continue;
1096
1097                 if (check_privilege(connection, message, method,
1098                                                 iface->user_data) == TRUE)
1099                         return DBUS_HANDLER_RESULT_HANDLED;
1100 #ifdef __TIZEN_PATCH__
1101 #if 0
1102                 gdbus_dbg("%s: %s.%s()", dbus_message_get_path(message),
1103                                                         iface->name, method->name);
1104 #endif
1105 #endif
1106                 return process_message(connection, message, method,
1107                                                         iface->user_data);
1108         }
1109
1110         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1111 }
1112
1113 static DBusObjectPathVTable generic_table = {
1114         .unregister_function    = generic_unregister,
1115         .message_function       = generic_message,
1116 };
1117
1118 static const GDBusMethodTable introspect_methods[] = {
1119         { GDBUS_METHOD("Introspect", NULL,
1120                         GDBUS_ARGS({ "xml", "s" }), introspect) },
1121         { }
1122 };
1123
1124 static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
1125 {
1126         DBusMessageIter array;
1127
1128         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1129                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1130                                 DBUS_TYPE_STRING_AS_STRING
1131                                 DBUS_TYPE_ARRAY_AS_STRING
1132                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1133                                 DBUS_TYPE_STRING_AS_STRING
1134                                 DBUS_TYPE_VARIANT_AS_STRING
1135                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
1136                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
1137
1138         g_slist_foreach(data->interfaces, append_interface, &array);
1139
1140         dbus_message_iter_close_container(iter, &array);
1141 }
1142
1143 static void append_object(gpointer data, gpointer user_data)
1144 {
1145         struct generic_data *child = data;
1146         DBusMessageIter *array = user_data;
1147         DBusMessageIter entry;
1148
1149         dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
1150                                                                 &entry);
1151         dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
1152                                                                 &child->path);
1153         append_interfaces(child, &entry);
1154         dbus_message_iter_close_container(array, &entry);
1155
1156         g_slist_foreach(child->objects, append_object, user_data);
1157 }
1158
1159 static DBusMessage *get_objects(DBusConnection *connection,
1160                                 DBusMessage *message, void *user_data)
1161 {
1162         struct generic_data *data = user_data;
1163         DBusMessage *reply;
1164         DBusMessageIter iter;
1165         DBusMessageIter array;
1166
1167         reply = dbus_message_new_method_return(message);
1168         if (reply == NULL)
1169                 return NULL;
1170
1171         dbus_message_iter_init_append(reply, &iter);
1172
1173         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1174                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1175                                         DBUS_TYPE_OBJECT_PATH_AS_STRING
1176                                         DBUS_TYPE_ARRAY_AS_STRING
1177                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1178                                         DBUS_TYPE_STRING_AS_STRING
1179                                         DBUS_TYPE_ARRAY_AS_STRING
1180                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1181                                         DBUS_TYPE_STRING_AS_STRING
1182                                         DBUS_TYPE_VARIANT_AS_STRING
1183                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING
1184                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING
1185                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1186                                         &array);
1187
1188         g_slist_foreach(data->objects, append_object, &array);
1189
1190         dbus_message_iter_close_container(&iter, &array);
1191
1192         return reply;
1193 }
1194
1195 #ifdef __TIZEN_PATCH__
1196 static DBusMessage *default_adapter(DBusConnection *conn,
1197                                         DBusMessage *msg, void *data)
1198 {
1199         DBusMessage *reply;
1200
1201         if (!adapter_path)
1202                 return g_dbus_create_error(msg,
1203                                 "org.bluez.Error" ".NoSuchAdapter",
1204                                 "No such adapter");
1205
1206         reply = dbus_message_new_method_return(msg);
1207         if (!reply)
1208                 return NULL;
1209
1210         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &adapter_path,
1211                                 DBUS_TYPE_INVALID);
1212
1213         return reply;
1214 }
1215 #endif
1216
1217 static const GDBusMethodTable manager_methods[] = {
1218         { GDBUS_METHOD("GetManagedObjects", NULL,
1219                 GDBUS_ARGS({ "objects", "a{oa{sa{sv}}}" }), get_objects) },
1220 #ifdef __TIZEN_PATCH__
1221         { GDBUS_METHOD("DefaultAdapter",
1222                         NULL, GDBUS_ARGS({ "adapter", "o" }),
1223                         default_adapter) },
1224 #endif
1225         { }
1226 };
1227
1228 static const GDBusSignalTable manager_signals[] = {
1229         { GDBUS_SIGNAL("InterfacesAdded",
1230                 GDBUS_ARGS({ "object", "o" },
1231                                 { "interfaces", "a{sa{sv}}" })) },
1232         { GDBUS_SIGNAL("InterfacesRemoved",
1233                 GDBUS_ARGS({ "object", "o" }, { "interfaces", "as" })) },
1234         { }
1235 };
1236
1237 static gboolean add_interface(struct generic_data *data,
1238                                 const char *name,
1239                                 const GDBusMethodTable *methods,
1240                                 const GDBusSignalTable *signals,
1241                                 const GDBusPropertyTable *properties,
1242                                 void *user_data,
1243                                 GDBusDestroyFunction destroy)
1244 {
1245         struct interface_data *iface;
1246         const GDBusMethodTable *method;
1247         const GDBusSignalTable *signal;
1248         const GDBusPropertyTable *property;
1249
1250         for (method = methods; method && method->name; method++) {
1251                 if (!check_experimental(method->flags,
1252                                         G_DBUS_METHOD_FLAG_EXPERIMENTAL))
1253                         goto done;
1254         }
1255
1256         for (signal = signals; signal && signal->name; signal++) {
1257                 if (!check_experimental(signal->flags,
1258                                         G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
1259                         goto done;
1260         }
1261
1262         for (property = properties; property && property->name; property++) {
1263                 if (!check_experimental(property->flags,
1264                                         G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
1265                         goto done;
1266         }
1267
1268         /* Nothing to register */
1269         return FALSE;
1270
1271 done:
1272         iface = g_new0(struct interface_data, 1);
1273         iface->name = g_strdup(name);
1274         iface->methods = methods;
1275         iface->signals = signals;
1276         iface->properties = properties;
1277         iface->user_data = user_data;
1278         iface->destroy = destroy;
1279
1280         data->interfaces = g_slist_append(data->interfaces, iface);
1281         if (data->parent == NULL)
1282                 return TRUE;
1283
1284         data->added = g_slist_append(data->added, iface);
1285
1286         add_pending(data);
1287
1288         return TRUE;
1289 }
1290
1291 static struct generic_data *object_path_ref(DBusConnection *connection,
1292                                                         const char *path)
1293 {
1294         struct generic_data *data;
1295
1296         if (dbus_connection_get_object_path_data(connection, path,
1297                                                 (void *) &data) == TRUE) {
1298                 if (data != NULL) {
1299                         data->refcount++;
1300                         return data;
1301                 }
1302         }
1303
1304         data = g_new0(struct generic_data, 1);
1305         data->conn = dbus_connection_ref(connection);
1306         data->path = g_strdup(path);
1307         data->refcount = 1;
1308
1309         data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
1310
1311         if (!dbus_connection_register_object_path(connection, path,
1312                                                 &generic_table, data)) {
1313                 dbus_connection_unref(data->conn);
1314                 g_free(data->path);
1315                 g_free(data->introspect);
1316                 g_free(data);
1317                 return NULL;
1318         }
1319
1320         invalidate_parent_data(connection, path);
1321
1322         add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, introspect_methods,
1323                                                 NULL, NULL, data, NULL);
1324
1325         return data;
1326 }
1327
1328 static void object_path_unref(DBusConnection *connection, const char *path)
1329 {
1330         struct generic_data *data = NULL;
1331
1332         if (dbus_connection_get_object_path_data(connection, path,
1333                                                 (void *) &data) == FALSE)
1334                 return;
1335
1336         if (data == NULL)
1337                 return;
1338
1339         data->refcount--;
1340
1341         if (data->refcount > 0)
1342                 return;
1343
1344         remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
1345         remove_interface(data, DBUS_INTERFACE_PROPERTIES);
1346
1347         invalidate_parent_data(data->conn, data->path);
1348
1349         dbus_connection_unregister_object_path(data->conn, data->path);
1350 }
1351
1352 static gboolean check_signal(DBusConnection *conn, const char *path,
1353                                 const char *interface, const char *name,
1354                                 const GDBusArgInfo **args)
1355 {
1356         struct generic_data *data = NULL;
1357         struct interface_data *iface;
1358         const GDBusSignalTable *signal;
1359
1360         *args = NULL;
1361         if (!dbus_connection_get_object_path_data(conn, path,
1362                                         (void *) &data) || data == NULL) {
1363                 error("dbus_connection_emit_signal: path %s isn't registered",
1364                                 path);
1365                 return FALSE;
1366         }
1367
1368         iface = find_interface(data->interfaces, interface);
1369         if (iface == NULL) {
1370                 error("dbus_connection_emit_signal: %s does not implement %s",
1371                                 path, interface);
1372                 return FALSE;
1373         }
1374
1375         for (signal = iface->signals; signal && signal->name; signal++) {
1376                 if (strcmp(signal->name, name) != 0)
1377                         continue;
1378
1379                 if (signal->flags & G_DBUS_SIGNAL_FLAG_EXPERIMENTAL) {
1380                         const char *env = g_getenv("GDBUS_EXPERIMENTAL");
1381                         if (g_strcmp0(env, "1") != 0)
1382                                 break;
1383                 }
1384
1385                 *args = signal->args;
1386                 return TRUE;
1387         }
1388
1389         error("No signal named %s on interface %s", name, interface);
1390         return FALSE;
1391 }
1392
1393 gboolean g_dbus_register_interface(DBusConnection *connection,
1394                                         const char *path, const char *name,
1395                                         const GDBusMethodTable *methods,
1396                                         const GDBusSignalTable *signals,
1397                                         const GDBusPropertyTable *properties,
1398                                         void *user_data,
1399                                         GDBusDestroyFunction destroy)
1400 {
1401         struct generic_data *data;
1402
1403         data = object_path_ref(connection, path);
1404         if (data == NULL)
1405                 return FALSE;
1406
1407         if (find_interface(data->interfaces, name)) {
1408                 object_path_unref(connection, path);
1409                 return FALSE;
1410         }
1411
1412 #ifdef __TIZEN_PATCH__
1413         if (g_strcmp0(name, ADAPTER_INTERFACE) == 0)
1414                 adapter_path = g_strdup(path);
1415 #endif
1416
1417         if (!add_interface(data, name, methods, signals, properties, user_data,
1418                                                                 destroy)) {
1419                 object_path_unref(connection, path);
1420                 return FALSE;
1421         }
1422
1423         if (properties != NULL && !find_interface(data->interfaces,
1424                                                 DBUS_INTERFACE_PROPERTIES))
1425                 add_interface(data, DBUS_INTERFACE_PROPERTIES,
1426                                 properties_methods, properties_signals, NULL,
1427                                 data, NULL);
1428
1429         g_free(data->introspect);
1430         data->introspect = NULL;
1431
1432         return TRUE;
1433 }
1434
1435 gboolean g_dbus_unregister_interface(DBusConnection *connection,
1436                                         const char *path, const char *name)
1437 {
1438         struct generic_data *data = NULL;
1439
1440         if (path == NULL)
1441                 return FALSE;
1442
1443         if (dbus_connection_get_object_path_data(connection, path,
1444                                                 (void *) &data) == FALSE)
1445                 return FALSE;
1446
1447         if (data == NULL)
1448                 return FALSE;
1449
1450         if (remove_interface(data, name) == FALSE)
1451                 return FALSE;
1452
1453         g_free(data->introspect);
1454         data->introspect = NULL;
1455
1456         object_path_unref(connection, data->path);
1457
1458         return TRUE;
1459 }
1460
1461 gboolean g_dbus_register_security(const GDBusSecurityTable *security)
1462 {
1463         if (security_table != NULL)
1464                 return FALSE;
1465
1466         security_table = security;
1467
1468         return TRUE;
1469 }
1470
1471 gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
1472 {
1473         security_table = NULL;
1474
1475         return TRUE;
1476 }
1477
1478 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
1479                                         const char *format, va_list args)
1480 {
1481         char str[1024];
1482
1483         if (format)
1484                 vsnprintf(str, sizeof(str), format, args);
1485         else
1486                 str[0] = '\0';
1487
1488         return dbus_message_new_error(message, name, str);
1489 }
1490
1491 DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
1492                                                 const char *format, ...)
1493 {
1494         va_list args;
1495         DBusMessage *reply;
1496
1497         va_start(args, format);
1498
1499         reply = g_dbus_create_error_valist(message, name, format, args);
1500
1501         va_end(args);
1502
1503         return reply;
1504 }
1505
1506 DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
1507                                                 int type, va_list args)
1508 {
1509         DBusMessage *reply;
1510
1511         reply = dbus_message_new_method_return(message);
1512         if (reply == NULL)
1513                 return NULL;
1514
1515         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
1516                 dbus_message_unref(reply);
1517                 return NULL;
1518         }
1519
1520         return reply;
1521 }
1522
1523 DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
1524 {
1525         va_list args;
1526         DBusMessage *reply;
1527
1528         va_start(args, type);
1529
1530         reply = g_dbus_create_reply_valist(message, type, args);
1531
1532         va_end(args);
1533
1534         return reply;
1535 }
1536
1537 static void g_dbus_flush(DBusConnection *connection)
1538 {
1539         GSList *l;
1540
1541         for (l = pending; l;) {
1542                 struct generic_data *data = l->data;
1543
1544                 l = l->next;
1545                 if (data->conn != connection)
1546                         continue;
1547
1548                 process_changes(data);
1549         }
1550 }
1551
1552 gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
1553 {
1554         dbus_bool_t result = FALSE;
1555
1556         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1557                 dbus_message_set_no_reply(message, TRUE);
1558         else if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL) {
1559                 const char *path = dbus_message_get_path(message);
1560                 const char *interface = dbus_message_get_interface(message);
1561                 const char *name = dbus_message_get_member(message);
1562                 const GDBusArgInfo *args;
1563
1564                 if (!check_signal(connection, path, interface, name, &args))
1565                         goto out;
1566         }
1567
1568         /* Flush pending signal to guarantee message order */
1569         g_dbus_flush(connection);
1570
1571         result = dbus_connection_send(connection, message, NULL);
1572
1573 out:
1574         dbus_message_unref(message);
1575
1576         return result;
1577 }
1578
1579 gboolean g_dbus_send_message_with_reply(DBusConnection *connection,
1580                                         DBusMessage *message,
1581                                         DBusPendingCall **call, int timeout)
1582 {
1583         dbus_bool_t ret;
1584
1585         /* Flush pending signal to guarantee message order */
1586         g_dbus_flush(connection);
1587
1588         ret = dbus_connection_send_with_reply(connection, message, call,
1589                                                                 timeout);
1590
1591         if (ret == TRUE && call != NULL && *call == NULL) {
1592                 error("Unable to send message (passing fd blocked?)");
1593                 return FALSE;
1594         }
1595
1596         return ret;
1597 }
1598
1599 gboolean g_dbus_send_error_valist(DBusConnection *connection,
1600                                         DBusMessage *message, const char *name,
1601                                         const char *format, va_list args)
1602 {
1603         DBusMessage *error;
1604
1605         error = g_dbus_create_error_valist(message, name, format, args);
1606         if (error == NULL)
1607                 return FALSE;
1608
1609         return g_dbus_send_message(connection, error);
1610 }
1611
1612 gboolean g_dbus_send_error(DBusConnection *connection, DBusMessage *message,
1613                                 const char *name, const char *format, ...)
1614 {
1615         va_list args;
1616         gboolean result;
1617
1618         va_start(args, format);
1619
1620         result = g_dbus_send_error_valist(connection, message, name,
1621                                                         format, args);
1622
1623         va_end(args);
1624
1625         return result;
1626 }
1627
1628 gboolean g_dbus_send_reply_valist(DBusConnection *connection,
1629                                 DBusMessage *message, int type, va_list args)
1630 {
1631         DBusMessage *reply;
1632
1633         reply = dbus_message_new_method_return(message);
1634         if (reply == NULL)
1635                 return FALSE;
1636
1637         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
1638                 dbus_message_unref(reply);
1639                 return FALSE;
1640         }
1641
1642         return g_dbus_send_message(connection, reply);
1643 }
1644
1645 gboolean g_dbus_send_reply(DBusConnection *connection,
1646                                 DBusMessage *message, int type, ...)
1647 {
1648         va_list args;
1649         gboolean result;
1650
1651         va_start(args, type);
1652
1653         result = g_dbus_send_reply_valist(connection, message, type, args);
1654
1655         va_end(args);
1656
1657         return result;
1658 }
1659
1660 gboolean g_dbus_emit_signal(DBusConnection *connection,
1661                                 const char *path, const char *interface,
1662                                 const char *name, int type, ...)
1663 {
1664         va_list args;
1665         gboolean result;
1666
1667         va_start(args, type);
1668
1669         result = g_dbus_emit_signal_valist(connection, path, interface,
1670                                                         name, type, args);
1671
1672         va_end(args);
1673
1674         return result;
1675 }
1676
1677 #ifdef GATT_NO_RELAY
1678 static gboolean g_dbus_emit_signal_valist_to_dest(DBusConnection *connection,
1679                                 const char *dest, const char *path, const char *interface,
1680                                 const char *name, int type, va_list args)
1681 {
1682         DBusMessage *signal;
1683         dbus_bool_t ret;
1684         const GDBusArgInfo *args_info;
1685
1686         if (!check_signal(connection, path, interface, name, &args_info))
1687                 return FALSE;
1688
1689         signal = dbus_message_new_signal(path, interface, name);
1690         if (signal == NULL) {
1691                 error("Unable to allocate new %s.%s signal", interface,  name);
1692                 return FALSE;
1693         }
1694
1695         ret = dbus_message_append_args_valist(signal, type, args);
1696         if (!ret)
1697                 goto fail;
1698
1699         if (g_dbus_args_have_signature(args_info, signal) == FALSE) {
1700                 error("%s.%s: got unexpected signature '%s'", interface, name,
1701                                         dbus_message_get_signature(signal));
1702                 ret = FALSE;
1703                 goto fail;
1704         }
1705
1706         ret = dbus_message_set_destination(signal, dest);
1707         if (!ret)
1708                 error("Fail to set destination");
1709
1710         return g_dbus_send_message(connection, signal);
1711
1712 fail:
1713         dbus_message_unref(signal);
1714
1715         return ret;
1716 }
1717
1718 gboolean g_dbus_emit_signal_to_dest(DBusConnection *connection,
1719                                 const char *dest, const char *path,
1720                                 const char *interface, const char *name, int type, ...)
1721 {
1722         va_list args;
1723         gboolean result;
1724
1725         va_start(args, type);
1726
1727         result = g_dbus_emit_signal_valist_to_dest(connection, dest, path,
1728                                                 interface, name, type, args);
1729
1730         va_end(args);
1731
1732         return result;
1733 }
1734 #endif
1735
1736 gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
1737                                 const char *path, const char *interface,
1738                                 const char *name, int type, va_list args)
1739 {
1740         DBusMessage *signal;
1741         dbus_bool_t ret;
1742         const GDBusArgInfo *args_info;
1743
1744         if (!check_signal(connection, path, interface, name, &args_info))
1745                 return FALSE;
1746
1747         signal = dbus_message_new_signal(path, interface, name);
1748         if (signal == NULL) {
1749                 error("Unable to allocate new %s.%s signal", interface,  name);
1750                 return FALSE;
1751         }
1752
1753         ret = dbus_message_append_args_valist(signal, type, args);
1754         if (!ret)
1755                 goto fail;
1756
1757         if (g_dbus_args_have_signature(args_info, signal) == FALSE) {
1758                 error("%s.%s: got unexpected signature '%s'", interface, name,
1759                                         dbus_message_get_signature(signal));
1760                 ret = FALSE;
1761                 goto fail;
1762         }
1763
1764         return g_dbus_send_message(connection, signal);
1765
1766 fail:
1767         dbus_message_unref(signal);
1768
1769         return ret;
1770 }
1771
1772 static void process_properties_from_interface(struct generic_data *data,
1773                                                 struct interface_data *iface)
1774 {
1775         GSList *l;
1776         DBusMessage *signal;
1777         DBusMessageIter iter, dict, array;
1778         GSList *invalidated;
1779
1780         data->pending_prop = FALSE;
1781
1782         if (iface->pending_prop == NULL)
1783                 return;
1784
1785         signal = dbus_message_new_signal(data->path,
1786                         DBUS_INTERFACE_PROPERTIES, "PropertiesChanged");
1787         if (signal == NULL) {
1788                 error("Unable to allocate new " DBUS_INTERFACE_PROPERTIES
1789                                                 ".PropertiesChanged signal");
1790                 return;
1791         }
1792
1793         iface->pending_prop = g_slist_reverse(iface->pending_prop);
1794
1795         dbus_message_iter_init_append(signal, &iter);
1796         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface->name);
1797         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1798                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1799                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
1800                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1801
1802         invalidated = NULL;
1803
1804         for (l = iface->pending_prop; l != NULL; l = l->next) {
1805                 GDBusPropertyTable *p = l->data;
1806
1807                 if (p->get == NULL)
1808                         continue;
1809
1810                 if (p->exists != NULL && !p->exists(p, iface->user_data)) {
1811                         invalidated = g_slist_prepend(invalidated, p);
1812                         continue;
1813                 }
1814
1815                 append_property(iface, p, &dict);
1816         }
1817
1818         dbus_message_iter_close_container(&iter, &dict);
1819
1820         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1821                                 DBUS_TYPE_STRING_AS_STRING, &array);
1822         for (l = invalidated; l != NULL; l = g_slist_next(l)) {
1823                 GDBusPropertyTable *p = l->data;
1824
1825                 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
1826                                                                 &p->name);
1827         }
1828         g_slist_free(invalidated);
1829         dbus_message_iter_close_container(&iter, &array);
1830
1831         g_slist_free(iface->pending_prop);
1832         iface->pending_prop = NULL;
1833
1834         /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */
1835         dbus_connection_send(data->conn, signal, NULL);
1836         dbus_message_unref(signal);
1837 }
1838
1839 static void process_property_changes(struct generic_data *data)
1840 {
1841         GSList *l;
1842
1843         for (l = data->interfaces; l != NULL; l = l->next) {
1844                 struct interface_data *iface = l->data;
1845
1846                 process_properties_from_interface(data, iface);
1847         }
1848 }
1849
1850 void g_dbus_emit_property_changed_full(DBusConnection *connection,
1851                                 const char *path, const char *interface,
1852                                 const char *name,
1853                                 GDbusPropertyChangedFlags flags)
1854 {
1855         const GDBusPropertyTable *property;
1856         struct generic_data *data;
1857         struct interface_data *iface;
1858
1859         if (path == NULL)
1860                 return;
1861
1862         if (!dbus_connection_get_object_path_data(connection, path,
1863                                         (void **) &data) || data == NULL)
1864                 return;
1865
1866         iface = find_interface(data->interfaces, interface);
1867         if (iface == NULL)
1868                 return;
1869
1870         /*
1871          * If ObjectManager is attached, don't emit property changed if
1872          * interface is not yet published
1873          */
1874         if (root && g_slist_find(data->added, iface))
1875                 return;
1876
1877         property = find_property(iface->properties, name);
1878         if (property == NULL) {
1879                 error("Could not find property %s in %p", name,
1880                                                         iface->properties);
1881                 return;
1882         }
1883
1884         if (g_slist_find(iface->pending_prop, (void *) property) != NULL)
1885                 return;
1886
1887         data->pending_prop = TRUE;
1888         iface->pending_prop = g_slist_prepend(iface->pending_prop,
1889                                                 (void *) property);
1890
1891         if (flags & G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH)
1892                 process_property_changes(data);
1893         else
1894                 add_pending(data);
1895 }
1896
1897 void g_dbus_emit_property_changed(DBusConnection *connection, const char *path,
1898                                 const char *interface, const char *name)
1899 {
1900         g_dbus_emit_property_changed_full(connection, path, interface, name, 0);
1901 }
1902
1903 gboolean g_dbus_get_properties(DBusConnection *connection, const char *path,
1904                                 const char *interface, DBusMessageIter *iter)
1905 {
1906         struct generic_data *data;
1907         struct interface_data *iface;
1908
1909         if (path == NULL)
1910                 return FALSE;
1911
1912         if (!dbus_connection_get_object_path_data(connection, path,
1913                                         (void **) &data) || data == NULL)
1914                 return FALSE;
1915
1916         iface = find_interface(data->interfaces, interface);
1917         if (iface == NULL)
1918                 return FALSE;
1919
1920         append_properties(iface, iter);
1921
1922         return TRUE;
1923 }
1924
1925 gboolean g_dbus_attach_object_manager(DBusConnection *connection)
1926 {
1927         struct generic_data *data;
1928
1929         data = object_path_ref(connection, "/");
1930         if (data == NULL)
1931                 return FALSE;
1932
1933         add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER,
1934                                         manager_methods, manager_signals,
1935                                         NULL, data, NULL);
1936         root = data;
1937
1938         return TRUE;
1939 }
1940
1941 gboolean g_dbus_detach_object_manager(DBusConnection *connection)
1942 {
1943         if (!g_dbus_unregister_interface(connection, "/",
1944                                         DBUS_INTERFACE_OBJECT_MANAGER))
1945                 return FALSE;
1946
1947         root = NULL;
1948
1949         return TRUE;
1950 }
1951
1952 void g_dbus_set_flags(int flags)
1953 {
1954         global_flags = flags;
1955 }
1956
1957 int g_dbus_get_flags(void)
1958 {
1959         return global_flags;
1960 }