gdbus: Add skeleton of DBus.Properties interface
[platform/upstream/connman.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 #define info(fmt...)
37 #define error(fmt...)
38 #define debug(fmt...)
39
40 struct generic_data {
41         unsigned int refcount;
42         GSList *interfaces;
43         char *introspect;
44 };
45
46 struct interface_data {
47         char *name;
48         const GDBusMethodTable *methods;
49         const GDBusSignalTable *signals;
50         const GDBusPropertyTable *properties;
51         void *user_data;
52         GDBusDestroyFunction destroy;
53 };
54
55 struct security_data {
56         GDBusPendingReply pending;
57         DBusMessage *message;
58         const GDBusMethodTable *method;
59         void *iface_user_data;
60 };
61
62 static void print_arguments(GString *gstr, const GDBusArgInfo *args,
63                                                 const char *direction)
64 {
65         for (; args && args->name; args++) {
66                 g_string_append_printf(gstr,
67                                         "\t\t\t<arg name=\"%s\" type=\"%s\"",
68                                         args->name, args->signature);
69
70                 if (direction)
71                         g_string_append_printf(gstr,
72                                         " direction=\"%s\"/>\n", direction);
73                 else
74                         g_string_append_printf(gstr, "/>\n");
75
76         }
77 }
78
79 #define G_DBUS_ANNOTATE(prefix_, name_, value_)                         \
80         prefix_ "<annotation name=\"org.freedesktop.DBus." name_ "\" "  \
81         "value=\"" value_ "\"/>\n"
82
83 #define G_DBUS_ANNOTATE_DEPRECATED(prefix_) \
84         G_DBUS_ANNOTATE(prefix_, "Deprecated", "true")
85
86 #define G_DBUS_ANNOTATE_NOREPLY(prefix_) \
87         G_DBUS_ANNOTATE(prefix_, "Method.NoReply", "true")
88
89 static void generate_interface_xml(GString *gstr, struct interface_data *iface)
90 {
91         const GDBusMethodTable *method;
92         const GDBusSignalTable *signal;
93
94         for (method = iface->methods; method && method->name; method++) {
95                 gboolean deprecated = method->flags &
96                                                 G_DBUS_METHOD_FLAG_DEPRECATED;
97                 gboolean noreply = method->flags &
98                                                 G_DBUS_METHOD_FLAG_NOREPLY;
99
100                 if (!deprecated && !noreply &&
101                                 !(method->in_args && method->in_args->name) &&
102                                 !(method->out_args && method->out_args->name))
103                         g_string_append_printf(gstr,
104                                                 "\t\t<method name=\"%s\"/>\n",
105                                                 method->name);
106                 else {
107                         g_string_append_printf(gstr,
108                                                 "\t\t<method name=\"%s\">\n",
109                                                 method->name);
110                         print_arguments(gstr, method->in_args, "in");
111                         print_arguments(gstr, method->out_args, "out");
112
113                         if (deprecated)
114                                 g_string_append_printf(gstr,
115                                         G_DBUS_ANNOTATE_DEPRECATED("\t\t\t"));
116                         if (noreply)
117                                 g_string_append_printf(gstr,
118                                         G_DBUS_ANNOTATE_NOREPLY("\t\t\t"));
119
120                         g_string_append_printf(gstr, "\t\t</method>\n");
121                 }
122         }
123
124         for (signal = iface->signals; signal && signal->name; signal++) {
125                 gboolean deprecated = signal->flags &
126                                                 G_DBUS_SIGNAL_FLAG_DEPRECATED;
127
128                 if (!deprecated && !(signal->args && signal->args->name))
129                         g_string_append_printf(gstr,
130                                                 "\t\t<signal name=\"%s\"/>\n",
131                                                 signal->name);
132                 else {
133                         g_string_append_printf(gstr,
134                                                 "\t\t<signal name=\"%s\">\n",
135                                                 signal->name);
136                         print_arguments(gstr, signal->args, NULL);
137
138                         if (deprecated)
139                                 g_string_append_printf(gstr,
140                                         G_DBUS_ANNOTATE_DEPRECATED("\t\t\t"));
141
142                         g_string_append_printf(gstr, "\t\t</signal>\n");
143                 }
144         }
145 }
146
147 static void generate_introspection_xml(DBusConnection *conn,
148                                 struct generic_data *data, const char *path)
149 {
150         GSList *list;
151         GString *gstr;
152         char **children;
153         int i;
154
155         g_free(data->introspect);
156
157         gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
158
159         g_string_append_printf(gstr, "<node>\n");
160
161         for (list = data->interfaces; list; list = list->next) {
162                 struct interface_data *iface = list->data;
163
164                 g_string_append_printf(gstr, "\t<interface name=\"%s\">\n",
165                                                                 iface->name);
166
167                 generate_interface_xml(gstr, iface);
168
169                 g_string_append_printf(gstr, "\t</interface>\n");
170         }
171
172         if (!dbus_connection_list_registered(conn, path, &children))
173                 goto done;
174
175         for (i = 0; children[i]; i++)
176                 g_string_append_printf(gstr, "\t<node name=\"%s\"/>\n",
177                                                                 children[i]);
178
179         dbus_free_string_array(children);
180
181 done:
182         g_string_append_printf(gstr, "</node>\n");
183
184         data->introspect = g_string_free(gstr, FALSE);
185 }
186
187 static DBusMessage *introspect(DBusConnection *connection,
188                                 DBusMessage *message, void *user_data)
189 {
190         struct generic_data *data = user_data;
191         DBusMessage *reply;
192
193         if (data->introspect == NULL)
194                 generate_introspection_xml(connection, data,
195                                                 dbus_message_get_path(message));
196
197         reply = dbus_message_new_method_return(message);
198         if (reply == NULL)
199                 return NULL;
200
201         dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect,
202                                         DBUS_TYPE_INVALID);
203
204         return reply;
205 }
206
207 static DBusHandlerResult process_message(DBusConnection *connection,
208                         DBusMessage *message, const GDBusMethodTable *method,
209                                                         void *iface_user_data)
210 {
211         DBusMessage *reply;
212
213         reply = method->function(connection, message, iface_user_data);
214
215         if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
216                 if (reply != NULL)
217                         dbus_message_unref(reply);
218                 return DBUS_HANDLER_RESULT_HANDLED;
219         }
220
221         if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
222                 if (reply == NULL)
223                         return DBUS_HANDLER_RESULT_HANDLED;
224         }
225
226         if (reply == NULL)
227                 return DBUS_HANDLER_RESULT_NEED_MEMORY;
228
229         dbus_connection_send(connection, reply, NULL);
230         dbus_message_unref(reply);
231
232         return DBUS_HANDLER_RESULT_HANDLED;
233 }
234
235 static GDBusPendingReply next_pending = 1;
236 static GSList *pending_security = NULL;
237
238 static const GDBusSecurityTable *security_table = NULL;
239
240 void g_dbus_pending_success(DBusConnection *connection,
241                                         GDBusPendingReply pending)
242 {
243         GSList *list;
244
245         for (list = pending_security; list; list = list->next) {
246                 struct security_data *secdata = list->data;
247
248                 if (secdata->pending != pending)
249                         continue;
250
251                 pending_security = g_slist_remove(pending_security, secdata);
252
253                 process_message(connection, secdata->message,
254                                 secdata->method, secdata->iface_user_data);
255
256                 dbus_message_unref(secdata->message);
257                 g_free(secdata);
258                 return;
259         }
260 }
261
262 void g_dbus_pending_error_valist(DBusConnection *connection,
263                                 GDBusPendingReply pending, const char *name,
264                                         const char *format, va_list args)
265 {
266         GSList *list;
267
268         for (list = pending_security; list; list = list->next) {
269                 struct security_data *secdata = list->data;
270                 DBusMessage *reply;
271
272                 if (secdata->pending != pending)
273                         continue;
274
275                 pending_security = g_slist_remove(pending_security, secdata);
276
277                 reply = g_dbus_create_error_valist(secdata->message,
278                                                         name, format, args);
279                 if (reply != NULL) {
280                         dbus_connection_send(connection, reply, NULL);
281                         dbus_message_unref(reply);
282                 }
283
284                 dbus_message_unref(secdata->message);
285                 g_free(secdata);
286                 return;
287         }
288 }
289
290 void g_dbus_pending_error(DBusConnection *connection,
291                                 GDBusPendingReply pending,
292                                 const char *name, const char *format, ...)
293 {
294         va_list args;
295
296         va_start(args, format);
297
298         g_dbus_pending_error_valist(connection, pending, name, format, args);
299
300         va_end(args);
301 }
302
303 int polkit_check_authorization(DBusConnection *conn,
304                                 const char *action, gboolean interaction,
305                                 void (*function) (dbus_bool_t authorized,
306                                                         void *user_data),
307                                                 void *user_data, int timeout);
308
309 struct builtin_security_data {
310         DBusConnection *conn;
311         GDBusPendingReply pending;
312 };
313
314 static void builtin_security_result(dbus_bool_t authorized, void *user_data)
315 {
316         struct builtin_security_data *data = user_data;
317
318         if (authorized == TRUE)
319                 g_dbus_pending_success(data->conn, data->pending);
320         else
321                 g_dbus_pending_error(data->conn, data->pending,
322                                                 DBUS_ERROR_AUTH_FAILED, NULL);
323
324         g_free(data);
325 }
326
327 static void builtin_security_function(DBusConnection *conn,
328                                                 const char *action,
329                                                 gboolean interaction,
330                                                 GDBusPendingReply pending)
331 {
332         struct builtin_security_data *data;
333
334         data = g_new0(struct builtin_security_data, 1);
335         data->conn = conn;
336         data->pending = pending;
337
338         if (polkit_check_authorization(conn, action, interaction,
339                                 builtin_security_result, data, 30000) < 0)
340                 g_dbus_pending_error(conn, pending, NULL, NULL);
341 }
342
343 static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
344                         const GDBusMethodTable *method, void *iface_user_data)
345 {
346         const GDBusSecurityTable *security;
347
348         for (security = security_table; security && security->privilege;
349                                                                 security++) {
350                 struct security_data *secdata;
351                 gboolean interaction;
352
353                 if (security->privilege != method->privilege)
354                         continue;
355
356                 secdata = g_new(struct security_data, 1);
357                 secdata->pending = next_pending++;
358                 secdata->message = dbus_message_ref(msg);
359                 secdata->method = method;
360                 secdata->iface_user_data = iface_user_data;
361
362                 pending_security = g_slist_prepend(pending_security, secdata);
363
364                 if (security->flags & G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION)
365                         interaction = TRUE;
366                 else
367                         interaction = FALSE;
368
369                 if (!(security->flags & G_DBUS_SECURITY_FLAG_BUILTIN) &&
370                                                         security->function)
371                         security->function(conn, security->action,
372                                                 interaction, secdata->pending);
373                 else
374                         builtin_security_function(conn, security->action,
375                                                 interaction, secdata->pending);
376
377                 return TRUE;
378         }
379
380         return FALSE;
381 }
382
383 static void generic_unregister(DBusConnection *connection, void *user_data)
384 {
385         struct generic_data *data = user_data;
386
387         g_free(data->introspect);
388         g_free(data);
389 }
390
391 static struct interface_data *find_interface(GSList *interfaces,
392                                                 const char *name)
393 {
394         GSList *list;
395
396         if (name == NULL)
397                 return NULL;
398
399         for (list = interfaces; list; list = list->next) {
400                 struct interface_data *iface = list->data;
401                 if (!strcmp(name, iface->name))
402                         return iface;
403         }
404
405         return NULL;
406 }
407
408 static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args,
409                                                         DBusMessage *message)
410 {
411         const char *sig = dbus_message_get_signature(message);
412         const char *p = NULL;
413
414         for (; args && args->signature && *sig; args++) {
415                 p = args->signature;
416
417                 for (; *sig && *p; sig++, p++) {
418                         if (*p != *sig)
419                                 return FALSE;
420                 }
421         }
422
423         if (*sig || (p && *p) || (args && args->signature))
424                 return FALSE;
425
426         return TRUE;
427 }
428
429 static DBusHandlerResult generic_message(DBusConnection *connection,
430                                         DBusMessage *message, void *user_data)
431 {
432         struct generic_data *data = user_data;
433         struct interface_data *iface;
434         const GDBusMethodTable *method;
435         const char *interface;
436
437         interface = dbus_message_get_interface(message);
438
439         iface = find_interface(data->interfaces, interface);
440         if (iface == NULL)
441                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
442
443         for (method = iface->methods; method &&
444                         method->name && method->function; method++) {
445                 if (dbus_message_is_method_call(message, iface->name,
446                                                         method->name) == FALSE)
447                         continue;
448
449                 if (g_dbus_args_have_signature(method->in_args,
450                                                         message) == FALSE)
451                         continue;
452
453                 if (check_privilege(connection, message, method,
454                                                 iface->user_data) == TRUE)
455                         return DBUS_HANDLER_RESULT_HANDLED;
456
457                 return process_message(connection, message, method,
458                                                         iface->user_data);
459         }
460
461         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
462 }
463
464 static DBusObjectPathVTable generic_table = {
465         .unregister_function    = generic_unregister,
466         .message_function       = generic_message,
467 };
468
469 static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
470 {
471         struct generic_data *data = NULL;
472         char *parent_path, *slash;
473
474         parent_path = g_strdup(child_path);
475         slash = strrchr(parent_path, '/');
476         if (slash == NULL)
477                 goto done;
478
479         if (slash == parent_path && parent_path[1] != '\0')
480                 parent_path[1] = '\0';
481         else
482                 *slash = '\0';
483
484         if (!strlen(parent_path))
485                 goto done;
486
487         if (dbus_connection_get_object_path_data(conn, parent_path,
488                                                         (void *) &data) == FALSE) {
489                 goto done;
490         }
491
492         invalidate_parent_data(conn, parent_path);
493
494         if (data == NULL)
495                 goto done;
496
497         g_free(data->introspect);
498         data->introspect = NULL;
499
500 done:
501         g_free(parent_path);
502 }
503
504 static const GDBusMethodTable introspect_methods[] = {
505         { GDBUS_METHOD("Introspect", NULL,
506                         GDBUS_ARGS({ "xml", "s" }), introspect) },
507         { }
508 };
509
510 static DBusMessage *properties_get(DBusConnection *connection,
511                                         DBusMessage *message, void *user_data)
512 {
513         return NULL;
514 }
515
516 static DBusMessage *properties_get_all(DBusConnection *connection,
517                                         DBusMessage *message, void *user_data)
518 {
519         return NULL;
520 }
521
522 static DBusMessage *properties_set(DBusConnection *connection,
523                                         DBusMessage *message, void *user_data)
524 {
525         return dbus_message_new_method_return(message);
526 }
527
528 static const GDBusMethodTable properties_methods[] = {
529         { GDBUS_METHOD("Get",
530                         GDBUS_ARGS({ "interface", "s" }, { "name", "s" }),
531                         GDBUS_ARGS({ "value", "v" }),
532                         properties_get) },
533         { GDBUS_ASYNC_METHOD("Set", NULL,
534                         GDBUS_ARGS({ "interface", "s" }, { "name", "s" },
535                                                         { "value", "v" }),
536                         properties_set) },
537         { GDBUS_METHOD("GetAll",
538                         GDBUS_ARGS({ "interface", "s" }),
539                         GDBUS_ARGS({ "properties", "a{sv}" }),
540                         properties_get_all) },
541         { }
542 };
543
544 static const GDBusSignalTable properties_signals[] = {
545         { GDBUS_SIGNAL("PropertiesChanged",
546                         GDBUS_ARGS({ "interface", "s" },
547                                         { "changed_properties", "a{sv}" },
548                                         { "invalidated_properties", "as"})) },
549         { }
550 };
551
552 static void add_interface(struct generic_data *data, const char *name,
553                                 const GDBusMethodTable *methods,
554                                 const GDBusSignalTable *signals,
555                                 const GDBusPropertyTable *properties,
556                                 void *user_data,
557                                 GDBusDestroyFunction destroy)
558 {
559         struct interface_data *iface;
560
561         iface = g_new0(struct interface_data, 1);
562         iface->name = g_strdup(name);
563         iface->methods = methods;
564         iface->signals = signals;
565         iface->properties = properties;
566         iface->user_data = user_data;
567         iface->destroy = destroy;
568
569         data->interfaces = g_slist_append(data->interfaces, iface);
570 }
571
572 static struct generic_data *object_path_ref(DBusConnection *connection,
573                                                         const char *path)
574 {
575         struct generic_data *data;
576
577         if (dbus_connection_get_object_path_data(connection, path,
578                                                 (void *) &data) == TRUE) {
579                 if (data != NULL) {
580                         data->refcount++;
581                         return data;
582                 }
583         }
584
585         data = g_new0(struct generic_data, 1);
586         data->refcount = 1;
587
588         data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
589
590         if (!dbus_connection_register_object_path(connection, path,
591                                                 &generic_table, data)) {
592                 g_free(data->introspect);
593                 g_free(data);
594                 return NULL;
595         }
596
597         invalidate_parent_data(connection, path);
598
599         add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
600                         introspect_methods, NULL, NULL, data, NULL);
601
602         add_interface(data, DBUS_INTERFACE_PROPERTIES, properties_methods,
603                                         properties_signals, NULL, data, NULL);
604
605         return data;
606 }
607
608 static gboolean remove_interface(struct generic_data *data, const char *name)
609 {
610         struct interface_data *iface;
611
612         iface = find_interface(data->interfaces, name);
613         if (iface == NULL)
614                 return FALSE;
615
616         data->interfaces = g_slist_remove(data->interfaces, iface);
617
618         if (iface->destroy)
619                 iface->destroy(iface->user_data);
620
621         g_free(iface->name);
622         g_free(iface);
623
624         return TRUE;
625 }
626
627 static void object_path_unref(DBusConnection *connection, const char *path)
628 {
629         struct generic_data *data = NULL;
630
631         if (dbus_connection_get_object_path_data(connection, path,
632                                                 (void *) &data) == FALSE)
633                 return;
634
635         if (data == NULL)
636                 return;
637
638         data->refcount--;
639
640         if (data->refcount > 0)
641                 return;
642
643         remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
644         remove_interface(data, DBUS_INTERFACE_PROPERTIES);
645
646         invalidate_parent_data(connection, path);
647
648         dbus_connection_unregister_object_path(connection, path);
649 }
650
651 static gboolean check_signal(DBusConnection *conn, const char *path,
652                                 const char *interface, const char *name,
653                                 const GDBusArgInfo **args)
654 {
655         struct generic_data *data = NULL;
656         struct interface_data *iface;
657         const GDBusSignalTable *signal;
658
659         *args = NULL;
660         if (!dbus_connection_get_object_path_data(conn, path,
661                                         (void *) &data) || data == NULL) {
662                 error("dbus_connection_emit_signal: path %s isn't registered",
663                                 path);
664                 return FALSE;
665         }
666
667         iface = find_interface(data->interfaces, interface);
668         if (iface == NULL) {
669                 error("dbus_connection_emit_signal: %s does not implement %s",
670                                 path, interface);
671                 return FALSE;
672         }
673
674         for (signal = iface->signals; signal && signal->name; signal++) {
675                 if (!strcmp(signal->name, name)) {
676                         *args = signal->args;
677                         return TRUE;
678                 }
679         }
680
681         error("No signal named %s on interface %s", name, interface);
682         return FALSE;
683 }
684
685 static dbus_bool_t emit_signal_valist(DBusConnection *conn,
686                                                 const char *path,
687                                                 const char *interface,
688                                                 const char *name,
689                                                 int first,
690                                                 va_list var_args)
691 {
692         DBusMessage *signal;
693         dbus_bool_t ret;
694         const GDBusArgInfo *args;
695
696         if (!check_signal(conn, path, interface, name, &args))
697                 return FALSE;
698
699         signal = dbus_message_new_signal(path, interface, name);
700         if (signal == NULL) {
701                 error("Unable to allocate new %s.%s signal", interface,  name);
702                 return FALSE;
703         }
704
705         ret = dbus_message_append_args_valist(signal, first, var_args);
706         if (!ret)
707                 goto fail;
708
709         if (g_dbus_args_have_signature(args, signal) == FALSE) {
710                 error("%s.%s: got unexpected signature '%s'", interface, name,
711                                         dbus_message_get_signature(signal));
712                 ret = FALSE;
713                 goto fail;
714         }
715
716         ret = dbus_connection_send(conn, signal, NULL);
717
718 fail:
719         dbus_message_unref(signal);
720
721         return ret;
722 }
723
724 gboolean g_dbus_register_interface(DBusConnection *connection,
725                                         const char *path, const char *name,
726                                         const GDBusMethodTable *methods,
727                                         const GDBusSignalTable *signals,
728                                         const GDBusPropertyTable *properties,
729                                         void *user_data,
730                                         GDBusDestroyFunction destroy)
731 {
732         struct generic_data *data;
733
734         data = object_path_ref(connection, path);
735         if (data == NULL)
736                 return FALSE;
737
738         if (find_interface(data->interfaces, name)) {
739                 object_path_unref(connection, path);
740                 return FALSE;
741         }
742
743         add_interface(data, name, methods, signals,
744                         properties, user_data, destroy);
745
746         g_free(data->introspect);
747         data->introspect = NULL;
748
749         return TRUE;
750 }
751
752 gboolean g_dbus_unregister_interface(DBusConnection *connection,
753                                         const char *path, const char *name)
754 {
755         struct generic_data *data = NULL;
756
757         if (path == NULL)
758                 return FALSE;
759
760         if (dbus_connection_get_object_path_data(connection, path,
761                                                 (void *) &data) == FALSE)
762                 return FALSE;
763
764         if (data == NULL)
765                 return FALSE;
766
767         if (remove_interface(data, name) == FALSE)
768                 return FALSE;
769
770         g_free(data->introspect);
771         data->introspect = NULL;
772
773         object_path_unref(connection, path);
774
775         return TRUE;
776 }
777
778 gboolean g_dbus_register_security(const GDBusSecurityTable *security)
779 {
780         if (security_table != NULL)
781                 return FALSE;
782
783         security_table = security;
784
785         return TRUE;
786 }
787
788 gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
789 {
790         security_table = NULL;
791
792         return TRUE;
793 }
794
795 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
796                                         const char *format, va_list args)
797 {
798         char str[1024];
799
800         vsnprintf(str, sizeof(str), format, args);
801
802         return dbus_message_new_error(message, name, str);
803 }
804
805 DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
806                                                 const char *format, ...)
807 {
808         va_list args;
809         DBusMessage *reply;
810
811         va_start(args, format);
812
813         reply = g_dbus_create_error_valist(message, name, format, args);
814
815         va_end(args);
816
817         return reply;
818 }
819
820 DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
821                                                 int type, va_list args)
822 {
823         DBusMessage *reply;
824
825         reply = dbus_message_new_method_return(message);
826         if (reply == NULL)
827                 return NULL;
828
829         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
830                 dbus_message_unref(reply);
831                 return NULL;
832         }
833
834         return reply;
835 }
836
837 DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
838 {
839         va_list args;
840         DBusMessage *reply;
841
842         va_start(args, type);
843
844         reply = g_dbus_create_reply_valist(message, type, args);
845
846         va_end(args);
847
848         return reply;
849 }
850
851 gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
852 {
853         dbus_bool_t result;
854
855         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
856                 dbus_message_set_no_reply(message, TRUE);
857
858         result = dbus_connection_send(connection, message, NULL);
859
860         dbus_message_unref(message);
861
862         return result;
863 }
864
865 gboolean g_dbus_send_reply_valist(DBusConnection *connection,
866                                 DBusMessage *message, int type, va_list args)
867 {
868         DBusMessage *reply;
869
870         reply = dbus_message_new_method_return(message);
871         if (reply == NULL)
872                 return FALSE;
873
874         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
875                 dbus_message_unref(reply);
876                 return FALSE;
877         }
878
879         return g_dbus_send_message(connection, reply);
880 }
881
882 gboolean g_dbus_send_reply(DBusConnection *connection,
883                                 DBusMessage *message, int type, ...)
884 {
885         va_list args;
886         gboolean result;
887
888         va_start(args, type);
889
890         result = g_dbus_send_reply_valist(connection, message, type, args);
891
892         va_end(args);
893
894         return result;
895 }
896
897 gboolean g_dbus_emit_signal(DBusConnection *connection,
898                                 const char *path, const char *interface,
899                                 const char *name, int type, ...)
900 {
901         va_list args;
902         gboolean result;
903
904         va_start(args, type);
905
906         result = emit_signal_valist(connection, path, interface,
907                                                         name, type, args);
908
909         va_end(args);
910
911         return result;
912 }
913
914 gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
915                                 const char *path, const char *interface,
916                                 const char *name, int type, va_list args)
917 {
918         return emit_signal_valist(connection, path, interface,
919                                                         name, type, args);
920 }