]> git.meshlink.io Git - catta/blob - avahi-client/entrygroup.c
* remove AVAHI_PUBLISH_IS_PROXY, it was a bad idea
[catta] / avahi-client / entrygroup.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <dbus/dbus.h>
31
32 #include <avahi-client/client.h>
33 #include <avahi-common/dbus.h>
34 #include <avahi-common/llist.h>
35 #include <avahi-common/error.h>
36 #include <avahi-common/malloc.h>
37
38 #include "client.h"
39 #include "internal.h"
40
41 void avahi_entry_group_set_state(AvahiEntryGroup *group, AvahiEntryGroupState state) {
42     assert(group);
43
44     if (group->state == state)
45         return;
46
47     group->state = state;
48
49     if (group->callback)
50         group->callback(group, state, group->userdata);
51 }
52
53 static int retrieve_state(AvahiEntryGroup *group) {
54     DBusMessage *message, *reply;
55     DBusError error;
56     int r = AVAHI_OK;
57     int32_t state;
58     AvahiClient *client;
59     
60     dbus_error_init(&error);
61
62     assert(group);
63     client = group->client;
64     
65     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState"))) {
66         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
67         goto fail;
68     }
69         
70     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
71         dbus_error_is_set (&error)) {
72         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
73         goto fail;
74     }
75     
76     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID) ||
77         dbus_error_is_set (&error)) {
78         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
79         goto fail;
80     }
81
82     dbus_message_unref(message);
83     dbus_message_unref(reply);
84
85     avahi_entry_group_set_state(group, (AvahiEntryGroupState) state);
86     
87     return AVAHI_OK;
88     
89 fail:
90     if (dbus_error_is_set(&error)) {
91         r = avahi_client_set_dbus_error(client, &error);
92         dbus_error_free(&error);
93     }
94
95     if (message)
96         dbus_message_unref(message);
97
98     if (reply)
99         dbus_message_unref(reply);
100
101     return r;
102 }
103
104 AvahiEntryGroup* avahi_entry_group_new (AvahiClient *client, AvahiEntryGroupCallback callback, void *userdata) {
105     AvahiEntryGroup *group = NULL;
106     DBusMessage *message = NULL, *reply = NULL;
107     DBusError error;
108     char *path;
109
110     assert(client);
111
112     dbus_error_init (&error);
113
114     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
115         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
116         goto fail;
117     }
118
119     if (!(group = avahi_new(AvahiEntryGroup, 1))) {
120         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
121         goto fail;
122     }
123     
124     group->client = client;
125     group->callback = callback;
126     group->userdata = userdata;
127     group->state = AVAHI_ENTRY_GROUP_UNCOMMITED;
128     group->path = NULL;
129     AVAHI_LLIST_PREPEND(AvahiEntryGroup, groups, client->groups, group);
130     
131     if (!(message = dbus_message_new_method_call(
132               AVAHI_DBUS_NAME,
133               AVAHI_DBUS_PATH_SERVER,
134               AVAHI_DBUS_INTERFACE_SERVER,
135               "EntryGroupNew"))) {
136         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
137         goto fail;
138     }
139
140     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
141         dbus_error_is_set (&error)) {
142         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
143         goto fail;
144     }
145
146     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
147         dbus_error_is_set (&error)) {
148         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
149         goto fail;
150     }
151     
152     if (!(group->path = avahi_strdup (path))) {
153
154         /* FIXME: We don't remove the object on the server side */
155
156         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
157         goto fail;
158     }
159
160     if (retrieve_state(group) < 0)
161         goto fail;
162
163     dbus_message_unref(message);
164     dbus_message_unref(reply);
165
166     return group;
167
168 fail:
169     if (dbus_error_is_set(&error)) {
170         avahi_client_set_dbus_error(client, &error);
171         dbus_error_free(&error);
172     }
173
174     if (group)
175         avahi_entry_group_free(group);
176     
177     if (message)
178         dbus_message_unref(message);
179
180     if (reply)
181         dbus_message_unref(reply);
182     
183     return NULL;
184 }
185
186 static int entry_group_simple_method_call(AvahiEntryGroup *group, const char *method) {
187     DBusMessage *message = NULL, *reply = NULL;
188     DBusError error;
189     int r = AVAHI_OK;
190     AvahiClient *client;
191     
192     dbus_error_init(&error);
193
194     assert(group);
195     client = group->client;
196     
197     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, method))) {
198         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
199         goto fail;
200     }
201         
202     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
203         dbus_error_is_set (&error)) {
204         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
205         goto fail;
206     }
207     
208     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
209         dbus_error_is_set (&error)) {
210         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
211         goto fail;
212     }
213
214     dbus_message_unref(message);
215     dbus_message_unref(reply);
216
217     return AVAHI_OK;
218     
219 fail:
220     if (dbus_error_is_set(&error)) {
221         r = avahi_client_set_dbus_error(client, &error);
222         dbus_error_free(&error);
223     }
224
225     if (message)
226         dbus_message_unref(message);
227
228     if (reply)
229         dbus_message_unref(reply);
230
231     return r;
232 }
233
234 int avahi_entry_group_free(AvahiEntryGroup *group) {
235     AvahiClient *client = group->client;
236     int r = AVAHI_OK;
237         
238     assert(group);
239     
240     if (group->path && client->state != AVAHI_CLIENT_DISCONNECTED)
241         r = entry_group_simple_method_call(group, "Free");
242     
243     AVAHI_LLIST_REMOVE(AvahiEntryGroup, groups, client->groups, group);
244
245     avahi_free(group->path);
246     avahi_free(group);
247
248     return r;
249 }
250
251 int avahi_entry_group_commit(AvahiEntryGroup *group) {
252     assert(group);
253     
254     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
255         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
256
257     return entry_group_simple_method_call(group, "Commit");
258 }
259
260 int avahi_entry_group_reset(AvahiEntryGroup *group) {
261     assert(group);
262     
263     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
264         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
265
266     return entry_group_simple_method_call(group, "Reset");
267 }
268
269 int avahi_entry_group_get_state (AvahiEntryGroup *group) {
270     assert (group);
271
272     return group->state;
273 }
274
275 AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup *group) {
276     assert(group);
277     
278     return group->client;
279 }
280
281 int avahi_entry_group_is_empty (AvahiEntryGroup *group) {
282     DBusMessage *message, *reply;
283     DBusError error;
284     int r = AVAHI_OK;
285     int b;
286     AvahiClient *client;
287     
288     assert(group);
289     client = group->client;
290
291     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
292         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
293
294     dbus_error_init(&error);
295     
296     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty"))) {
297         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
298         goto fail;
299     }
300         
301     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
302         dbus_error_is_set (&error)) {
303         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
304         goto fail;
305     }
306     
307     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID) ||
308         dbus_error_is_set (&error)) {
309         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
310         goto fail;
311     }
312
313     dbus_message_unref(message);
314     dbus_message_unref(reply);
315
316     return !!b;
317     
318 fail:
319     if (dbus_error_is_set(&error)) {
320         r = avahi_client_set_dbus_error(client, &error);
321         dbus_error_free(&error);
322     }
323
324     if (message)
325         dbus_message_unref(message);
326
327     if (reply)
328         dbus_message_unref(reply);
329
330     return r;
331 }
332
333 static int append_string_list(DBusMessage *message, AvahiStringList *txt) {
334     DBusMessageIter iter, sub;
335     int r = -1;
336     AvahiStringList *p;
337
338     assert(message);
339
340     dbus_message_iter_init_append(message, &iter);
341
342     /* Reverse the string list, so that we can pass it in-order to the server */
343     txt = avahi_string_list_reverse(txt);
344     
345     if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub))
346         goto fail;
347
348     /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */
349     for (p = txt; p != NULL; p = p->next) {
350         DBusMessageIter sub2;
351         const uint8_t *data = p->text;
352         
353         if (!(dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2)) ||
354             !(dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size)) ||
355             !(dbus_message_iter_close_container(&sub, &sub2)))
356             goto fail;
357     }
358
359     if (!dbus_message_iter_close_container(&iter, &sub))
360         goto fail;
361
362     r = 0;
363
364 fail:
365
366     /* Reverse the string list to the original state */
367     txt = avahi_string_list_reverse(txt);
368
369     return r;
370 }
371
372 int avahi_entry_group_add_service_strlst(
373     AvahiEntryGroup *group,
374     AvahiIfIndex interface,
375     AvahiProtocol protocol,
376     AvahiPublishFlags flags,
377     const char *name,
378     const char *type,
379     const char *domain,
380     const char *host,
381     uint16_t port,
382     AvahiStringList *txt) {
383     
384     DBusMessage *message = NULL, *reply = NULL;
385     int r = AVAHI_OK;
386     DBusError error;
387     AvahiClient *client;
388     int32_t i_interface, i_protocol;
389     uint32_t u_flags;
390
391     assert(group);
392     assert(name);
393     assert(type);
394
395     client = group->client;
396
397     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
398         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
399
400     if (!domain)
401         domain = "";
402
403     if (!host)
404         host = "";
405     
406     dbus_error_init(&error);
407     
408     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService"))) {
409         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
410         goto fail;
411     }
412
413     i_interface = (int32_t) interface;
414     i_protocol = (int32_t) protocol;
415     u_flags = (uint32_t) flags;
416
417     if (!dbus_message_append_args(
418             message,
419             DBUS_TYPE_INT32, &i_interface,
420             DBUS_TYPE_INT32, &i_protocol,
421             DBUS_TYPE_UINT32, &u_flags,
422             DBUS_TYPE_STRING, &name,
423             DBUS_TYPE_STRING, &type,
424             DBUS_TYPE_STRING, &domain,
425             DBUS_TYPE_STRING, &host,
426             DBUS_TYPE_UINT16, &port,
427             DBUS_TYPE_INVALID) ||
428         append_string_list(message, txt) < 0) {
429         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
430         goto fail;
431     }
432     
433     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
434         dbus_error_is_set (&error)) {
435         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
436         goto fail;
437     }
438     
439     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
440         dbus_error_is_set (&error)) {
441         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
442         goto fail;
443     }
444
445     dbus_message_unref(message);
446     dbus_message_unref(reply);
447
448     return AVAHI_OK;
449
450 fail:
451     
452     if (dbus_error_is_set(&error)) {
453         r = avahi_client_set_dbus_error(client, &error);
454         dbus_error_free(&error);
455     }
456
457     if (message)
458         dbus_message_unref(message);
459
460     if (reply)
461         dbus_message_unref(reply);
462
463     return r;
464 }
465
466 int avahi_entry_group_add_service(
467     AvahiEntryGroup *group,
468     AvahiIfIndex interface,
469     AvahiProtocol protocol,
470     AvahiPublishFlags flags,
471     const char *name,
472     const char *type,
473     const char *domain,
474     const char *host,
475     uint16_t port,
476     ...) {
477     
478     va_list va;
479     int r;
480
481     assert(group);
482
483     va_start(va, port);
484     r = avahi_entry_group_add_service_va(group, interface, protocol, flags, name, type, domain, host, port, va);
485     va_end(va);
486     return r;
487 }
488
489 int avahi_entry_group_add_service_va(
490     AvahiEntryGroup *group,
491     AvahiIfIndex interface,
492     AvahiProtocol protocol,
493     AvahiPublishFlags flags,
494     const char *name,
495     const char *type,
496     const char *domain,
497     const char *host,
498     uint16_t port,
499     va_list va) {
500
501     int r;
502     AvahiStringList *txt;
503
504     assert(group);
505
506     txt = avahi_string_list_new_va(va);
507     r = avahi_entry_group_add_service_strlst(group, interface, protocol, flags, name, type, domain, host, port, txt);
508     avahi_string_list_free(txt);
509
510     return r;
511 }
512
513 int avahi_entry_group_add_service_subtype(
514     AvahiEntryGroup *group,
515     AvahiIfIndex interface,
516     AvahiProtocol protocol,
517     AvahiPublishFlags flags,
518     const char *name,
519     const char *type,
520     const char *domain,
521     const char *subtype) {
522
523     DBusMessage *message = NULL, *reply = NULL;
524     int r = AVAHI_OK;
525     DBusError error;
526     AvahiClient *client;
527     int32_t i_interface, i_protocol;
528     uint32_t u_flags;
529
530     assert(group);
531     assert(name);
532     assert(type);
533     assert(subtype);
534
535     client = group->client;
536
537     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
538         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
539
540     if (!domain)
541         domain = "";
542
543     dbus_error_init(&error);
544     
545     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype"))) {
546         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
547         goto fail;
548     }
549
550     i_interface = (int32_t) interface;
551     i_protocol = (int32_t) protocol;
552     u_flags = (uint32_t) flags;
553
554     if (!dbus_message_append_args(
555             message,
556             DBUS_TYPE_INT32, &i_interface,
557             DBUS_TYPE_INT32, &i_protocol,
558             DBUS_TYPE_UINT32, &u_flags,
559             DBUS_TYPE_STRING, &name,
560             DBUS_TYPE_STRING, &type,
561             DBUS_TYPE_STRING, &domain,
562             DBUS_TYPE_STRING, &subtype,
563             DBUS_TYPE_INVALID)) {
564         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
565         goto fail;
566     }
567     
568     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
569         dbus_error_is_set (&error)) {
570         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
571         goto fail;
572     }
573     
574     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
575         dbus_error_is_set (&error)) {
576         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
577         goto fail;
578     }
579
580     dbus_message_unref(message);
581     dbus_message_unref(reply);
582
583     return AVAHI_OK;
584
585 fail:
586     
587     if (dbus_error_is_set(&error)) {
588         r = avahi_client_set_dbus_error(client, &error);
589         dbus_error_free(&error);
590     }
591
592     if (message)
593         dbus_message_unref(message);
594
595     if (reply)
596         dbus_message_unref(reply);
597
598     return r;
599
600 }
601
602 int avahi_entry_group_update_service_txt(
603     AvahiEntryGroup *group,
604     AvahiIfIndex interface,
605     AvahiProtocol protocol,
606     AvahiPublishFlags flags,
607     const char *name,     
608     const char *type,     
609     const char *domain,   
610     ...) {
611
612     va_list va;
613     int r;
614
615     va_start(va, domain);
616     r = avahi_entry_group_update_service_txt_va(group, interface, protocol, flags, name, type, domain, va);
617     va_end(va);
618     return r;
619 }
620
621 int avahi_entry_group_update_service_txt_va(
622     AvahiEntryGroup *group,
623     AvahiIfIndex interface,
624     AvahiProtocol protocol,
625     AvahiPublishFlags flags,
626     const char *name,     
627     const char *type,     
628     const char *domain,   
629     va_list va) {
630
631     int r;
632     AvahiStringList *txt;
633
634     txt = avahi_string_list_new_va(va);
635     r = avahi_entry_group_update_service_txt_strlst(group, interface, protocol, flags, name, type, domain, txt);
636     avahi_string_list_free(txt);
637
638     return r;
639 }
640
641 int avahi_entry_group_update_service_txt_strlst(
642     AvahiEntryGroup *group,
643     AvahiIfIndex interface,
644     AvahiProtocol protocol,
645     AvahiPublishFlags flags,
646     const char *name,     
647     const char *type,     
648     const char *domain,   
649     AvahiStringList *txt) {
650
651     DBusMessage *message = NULL, *reply = NULL;
652     int r = AVAHI_OK;
653     DBusError error;
654     AvahiClient *client;
655     int32_t i_interface, i_protocol;
656     uint32_t u_flags;
657
658     assert(group);
659     assert(name);
660     assert(type);
661
662     client = group->client;
663
664     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
665         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
666
667     if (!domain)
668         domain = "";
669     
670     dbus_error_init(&error);
671     
672     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt"))) {
673         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
674         goto fail;
675     }
676
677     i_interface = (int32_t) interface;
678     i_protocol = (int32_t) protocol;
679     u_flags = (uint32_t) flags;
680
681     if (!dbus_message_append_args(
682             message,
683             DBUS_TYPE_INT32, &i_interface,
684             DBUS_TYPE_INT32, &i_protocol,
685             DBUS_TYPE_UINT32, &u_flags,
686             DBUS_TYPE_STRING, &name,
687             DBUS_TYPE_STRING, &type,
688             DBUS_TYPE_STRING, &domain,
689             DBUS_TYPE_INVALID) ||
690         append_string_list(message, txt) < 0) {
691         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
692         goto fail;
693     }
694
695     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
696         dbus_error_is_set (&error)) {
697         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
698         goto fail;
699     }
700     
701     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
702         dbus_error_is_set (&error)) {
703         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
704         goto fail;
705     }
706
707     dbus_message_unref(message);
708     dbus_message_unref(reply);
709
710     return AVAHI_OK;
711
712 fail:
713     
714     if (dbus_error_is_set(&error)) {
715         r = avahi_client_set_dbus_error(client, &error);
716         dbus_error_free(&error);
717     }
718
719     if (message)
720         dbus_message_unref(message);
721
722     if (reply)
723         dbus_message_unref(reply);
724
725     return r;
726     
727     
728 }
729
730 /** Add a host/address pair */
731 int avahi_entry_group_add_address(
732     AvahiEntryGroup *group,
733     AvahiIfIndex interface,
734     AvahiProtocol protocol,
735     AvahiPublishFlags flags,
736     const char *name,
737     const AvahiAddress *a) {
738
739     DBusMessage *message = NULL, *reply = NULL;
740     int r = AVAHI_OK;
741     DBusError error;
742     AvahiClient *client;
743     int32_t i_interface, i_protocol;
744     uint32_t u_flags;
745     char s_address[AVAHI_ADDRESS_STR_MAX];
746     char *p_address = s_address;
747
748     assert(name);
749
750     client = group->client;
751
752     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
753         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
754
755     dbus_error_init(&error);
756     
757     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress"))) {
758         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
759         goto fail;
760     }
761
762     i_interface = (int32_t) interface;
763     i_protocol = (int32_t) protocol;
764     u_flags = (uint32_t) flags;
765         
766     if (!avahi_address_snprint (s_address, sizeof (s_address), a))
767     {
768         r = avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS);
769         goto fail;
770     }
771
772     if (!dbus_message_append_args(
773             message,
774             DBUS_TYPE_INT32, &i_interface,
775             DBUS_TYPE_INT32, &i_protocol,
776             DBUS_TYPE_UINT32, &u_flags,
777             DBUS_TYPE_STRING, &name,
778             DBUS_TYPE_STRING, &p_address,
779             DBUS_TYPE_INVALID)) {
780         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
781         goto fail;
782     }
783     
784     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
785         dbus_error_is_set (&error)) {
786         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
787         goto fail;
788     }
789     
790     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
791         dbus_error_is_set (&error)) {
792         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
793         goto fail;
794     }
795
796     dbus_message_unref(message);
797     dbus_message_unref(reply);
798
799     return AVAHI_OK;
800
801 fail:
802     
803     if (dbus_error_is_set(&error)) {
804         r = avahi_client_set_dbus_error(client, &error);
805         dbus_error_free(&error);
806     }
807
808     if (message)
809         dbus_message_unref(message);
810
811     if (reply)
812         dbus_message_unref(reply);
813
814     return r;
815 }