gdbus: Use macros to add annotations
[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 void add_interface(struct generic_data *data, const char *name,
511                                 const GDBusMethodTable *methods,
512                                 const GDBusSignalTable *signals,
513                                 const GDBusPropertyTable *properties,
514                                 void *user_data,
515                                 GDBusDestroyFunction destroy)
516 {
517         struct interface_data *iface;
518
519         iface = g_new0(struct interface_data, 1);
520         iface->name = g_strdup(name);
521         iface->methods = methods;
522         iface->signals = signals;
523         iface->properties = properties;
524         iface->user_data = user_data;
525         iface->destroy = destroy;
526
527         data->interfaces = g_slist_append(data->interfaces, iface);
528 }
529
530 static struct generic_data *object_path_ref(DBusConnection *connection,
531                                                         const char *path)
532 {
533         struct generic_data *data;
534
535         if (dbus_connection_get_object_path_data(connection, path,
536                                                 (void *) &data) == TRUE) {
537                 if (data != NULL) {
538                         data->refcount++;
539                         return data;
540                 }
541         }
542
543         data = g_new0(struct generic_data, 1);
544         data->refcount = 1;
545
546         data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
547
548         if (!dbus_connection_register_object_path(connection, path,
549                                                 &generic_table, data)) {
550                 g_free(data->introspect);
551                 g_free(data);
552                 return NULL;
553         }
554
555         invalidate_parent_data(connection, path);
556
557         add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
558                         introspect_methods, NULL, NULL, data, NULL);
559
560         return data;
561 }
562
563 static gboolean remove_interface(struct generic_data *data, const char *name)
564 {
565         struct interface_data *iface;
566
567         iface = find_interface(data->interfaces, name);
568         if (iface == NULL)
569                 return FALSE;
570
571         data->interfaces = g_slist_remove(data->interfaces, iface);
572
573         if (iface->destroy)
574                 iface->destroy(iface->user_data);
575
576         g_free(iface->name);
577         g_free(iface);
578
579         return TRUE;
580 }
581
582 static void object_path_unref(DBusConnection *connection, const char *path)
583 {
584         struct generic_data *data = NULL;
585
586         if (dbus_connection_get_object_path_data(connection, path,
587                                                 (void *) &data) == FALSE)
588                 return;
589
590         if (data == NULL)
591                 return;
592
593         data->refcount--;
594
595         if (data->refcount > 0)
596                 return;
597
598         remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
599
600         invalidate_parent_data(connection, path);
601
602         dbus_connection_unregister_object_path(connection, path);
603 }
604
605 static gboolean check_signal(DBusConnection *conn, const char *path,
606                                 const char *interface, const char *name,
607                                 const GDBusArgInfo **args)
608 {
609         struct generic_data *data = NULL;
610         struct interface_data *iface;
611         const GDBusSignalTable *signal;
612
613         *args = NULL;
614         if (!dbus_connection_get_object_path_data(conn, path,
615                                         (void *) &data) || data == NULL) {
616                 error("dbus_connection_emit_signal: path %s isn't registered",
617                                 path);
618                 return FALSE;
619         }
620
621         iface = find_interface(data->interfaces, interface);
622         if (iface == NULL) {
623                 error("dbus_connection_emit_signal: %s does not implement %s",
624                                 path, interface);
625                 return FALSE;
626         }
627
628         for (signal = iface->signals; signal && signal->name; signal++) {
629                 if (!strcmp(signal->name, name)) {
630                         *args = signal->args;
631                         return TRUE;
632                 }
633         }
634
635         error("No signal named %s on interface %s", name, interface);
636         return FALSE;
637 }
638
639 static dbus_bool_t emit_signal_valist(DBusConnection *conn,
640                                                 const char *path,
641                                                 const char *interface,
642                                                 const char *name,
643                                                 int first,
644                                                 va_list var_args)
645 {
646         DBusMessage *signal;
647         dbus_bool_t ret;
648         const GDBusArgInfo *args;
649
650         if (!check_signal(conn, path, interface, name, &args))
651                 return FALSE;
652
653         signal = dbus_message_new_signal(path, interface, name);
654         if (signal == NULL) {
655                 error("Unable to allocate new %s.%s signal", interface,  name);
656                 return FALSE;
657         }
658
659         ret = dbus_message_append_args_valist(signal, first, var_args);
660         if (!ret)
661                 goto fail;
662
663         if (g_dbus_args_have_signature(args, signal) == FALSE) {
664                 error("%s.%s: got unexpected signature '%s'", interface, name,
665                                         dbus_message_get_signature(signal));
666                 ret = FALSE;
667                 goto fail;
668         }
669
670         ret = dbus_connection_send(conn, signal, NULL);
671
672 fail:
673         dbus_message_unref(signal);
674
675         return ret;
676 }
677
678 gboolean g_dbus_register_interface(DBusConnection *connection,
679                                         const char *path, const char *name,
680                                         const GDBusMethodTable *methods,
681                                         const GDBusSignalTable *signals,
682                                         const GDBusPropertyTable *properties,
683                                         void *user_data,
684                                         GDBusDestroyFunction destroy)
685 {
686         struct generic_data *data;
687
688         data = object_path_ref(connection, path);
689         if (data == NULL)
690                 return FALSE;
691
692         if (find_interface(data->interfaces, name)) {
693                 object_path_unref(connection, path);
694                 return FALSE;
695         }
696
697         add_interface(data, name, methods, signals,
698                         properties, user_data, destroy);
699
700         g_free(data->introspect);
701         data->introspect = NULL;
702
703         return TRUE;
704 }
705
706 gboolean g_dbus_unregister_interface(DBusConnection *connection,
707                                         const char *path, const char *name)
708 {
709         struct generic_data *data = NULL;
710
711         if (path == NULL)
712                 return FALSE;
713
714         if (dbus_connection_get_object_path_data(connection, path,
715                                                 (void *) &data) == FALSE)
716                 return FALSE;
717
718         if (data == NULL)
719                 return FALSE;
720
721         if (remove_interface(data, name) == FALSE)
722                 return FALSE;
723
724         g_free(data->introspect);
725         data->introspect = NULL;
726
727         object_path_unref(connection, path);
728
729         return TRUE;
730 }
731
732 gboolean g_dbus_register_security(const GDBusSecurityTable *security)
733 {
734         if (security_table != NULL)
735                 return FALSE;
736
737         security_table = security;
738
739         return TRUE;
740 }
741
742 gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
743 {
744         security_table = NULL;
745
746         return TRUE;
747 }
748
749 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
750                                         const char *format, va_list args)
751 {
752         char str[1024];
753
754         vsnprintf(str, sizeof(str), format, args);
755
756         return dbus_message_new_error(message, name, str);
757 }
758
759 DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
760                                                 const char *format, ...)
761 {
762         va_list args;
763         DBusMessage *reply;
764
765         va_start(args, format);
766
767         reply = g_dbus_create_error_valist(message, name, format, args);
768
769         va_end(args);
770
771         return reply;
772 }
773
774 DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
775                                                 int type, va_list args)
776 {
777         DBusMessage *reply;
778
779         reply = dbus_message_new_method_return(message);
780         if (reply == NULL)
781                 return NULL;
782
783         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
784                 dbus_message_unref(reply);
785                 return NULL;
786         }
787
788         return reply;
789 }
790
791 DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
792 {
793         va_list args;
794         DBusMessage *reply;
795
796         va_start(args, type);
797
798         reply = g_dbus_create_reply_valist(message, type, args);
799
800         va_end(args);
801
802         return reply;
803 }
804
805 gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
806 {
807         dbus_bool_t result;
808
809         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
810                 dbus_message_set_no_reply(message, TRUE);
811
812         result = dbus_connection_send(connection, message, NULL);
813
814         dbus_message_unref(message);
815
816         return result;
817 }
818
819 gboolean g_dbus_send_reply_valist(DBusConnection *connection,
820                                 DBusMessage *message, int type, va_list args)
821 {
822         DBusMessage *reply;
823
824         reply = dbus_message_new_method_return(message);
825         if (reply == NULL)
826                 return FALSE;
827
828         if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
829                 dbus_message_unref(reply);
830                 return FALSE;
831         }
832
833         return g_dbus_send_message(connection, reply);
834 }
835
836 gboolean g_dbus_send_reply(DBusConnection *connection,
837                                 DBusMessage *message, int type, ...)
838 {
839         va_list args;
840         gboolean result;
841
842         va_start(args, type);
843
844         result = g_dbus_send_reply_valist(connection, message, type, args);
845
846         va_end(args);
847
848         return result;
849 }
850
851 gboolean g_dbus_emit_signal(DBusConnection *connection,
852                                 const char *path, const char *interface,
853                                 const char *name, int type, ...)
854 {
855         va_list args;
856         gboolean result;
857
858         va_start(args, type);
859
860         result = emit_signal_valist(connection, path, interface,
861                                                         name, type, args);
862
863         va_end(args);
864
865         return result;
866 }
867
868 gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
869                                 const char *path, const char *interface,
870                                 const char *name, int type, va_list args)
871 {
872         return emit_signal_valist(connection, path, interface,
873                                                         name, type, args);
874 }