]> git.meshlink.io Git - catta/blob - avahi-client/entrygroup.c
50afb126c41589f873fb1762b26a60ce2ff24049
[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 = NULL, *reply = NULL;
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 = NULL, *reply = NULL;
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_rdata(DBusMessage *message, const void *rdata, size_t size) {
334     DBusMessageIter iter, sub;
335  
336     assert(message);
337  
338     dbus_message_iter_init_append(message, &iter);
339  
340     if (!(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &sub)) ||
341         !(dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &rdata, size)) ||
342         !(dbus_message_iter_close_container(&iter, &sub)))
343         return -1;
344     
345     return 0;
346 }
347
348 static int append_string_list(DBusMessage *message, AvahiStringList *txt) {
349     DBusMessageIter iter, sub;
350     int r = -1;
351     AvahiStringList *p;
352
353     assert(message);
354
355     dbus_message_iter_init_append(message, &iter);
356
357     /* Reverse the string list, so that we can pass it in-order to the server */
358     txt = avahi_string_list_reverse(txt);
359     
360     if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub))
361         goto fail;
362
363     /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */
364     for (p = txt; p != NULL; p = p->next) {
365         DBusMessageIter sub2;
366         const uint8_t *data = p->text;
367         
368         if (!(dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2)) ||
369             !(dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size)) ||
370             !(dbus_message_iter_close_container(&sub, &sub2)))
371             goto fail;
372     }
373
374     if (!dbus_message_iter_close_container(&iter, &sub))
375         goto fail;
376
377     r = 0;
378
379 fail:
380
381     /* Reverse the string list to the original state */
382     txt = avahi_string_list_reverse(txt);
383
384     return r;
385 }
386
387 int avahi_entry_group_add_service_strlst(
388     AvahiEntryGroup *group,
389     AvahiIfIndex interface,
390     AvahiProtocol protocol,
391     AvahiPublishFlags flags,
392     const char *name,
393     const char *type,
394     const char *domain,
395     const char *host,
396     uint16_t port,
397     AvahiStringList *txt) {
398     
399     DBusMessage *message = NULL, *reply = NULL;
400     int r = AVAHI_OK;
401     DBusError error;
402     AvahiClient *client;
403     int32_t i_interface, i_protocol;
404     uint32_t u_flags;
405
406     assert(group);
407     assert(name);
408     assert(type);
409
410     client = group->client;
411
412     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
413         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
414
415     if (!domain)
416         domain = "";
417
418     if (!host)
419         host = "";
420     
421     dbus_error_init(&error);
422     
423     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService"))) {
424         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
425         goto fail;
426     }
427
428     i_interface = (int32_t) interface;
429     i_protocol = (int32_t) protocol;
430     u_flags = (uint32_t) flags;
431
432     if (!dbus_message_append_args(
433             message,
434             DBUS_TYPE_INT32, &i_interface,
435             DBUS_TYPE_INT32, &i_protocol,
436             DBUS_TYPE_UINT32, &u_flags,
437             DBUS_TYPE_STRING, &name,
438             DBUS_TYPE_STRING, &type,
439             DBUS_TYPE_STRING, &domain,
440             DBUS_TYPE_STRING, &host,
441             DBUS_TYPE_UINT16, &port,
442             DBUS_TYPE_INVALID) ||
443         append_string_list(message, txt) < 0) {
444         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
445         goto fail;
446     }
447     
448     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
449         dbus_error_is_set (&error)) {
450         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
451         goto fail;
452     }
453     
454     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
455         dbus_error_is_set (&error)) {
456         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
457         goto fail;
458     }
459
460     dbus_message_unref(message);
461     dbus_message_unref(reply);
462
463     return AVAHI_OK;
464
465 fail:
466     
467     if (dbus_error_is_set(&error)) {
468         r = avahi_client_set_dbus_error(client, &error);
469         dbus_error_free(&error);
470     }
471
472     if (message)
473         dbus_message_unref(message);
474
475     if (reply)
476         dbus_message_unref(reply);
477
478     return r;
479 }
480
481 int avahi_entry_group_add_service(
482     AvahiEntryGroup *group,
483     AvahiIfIndex interface,
484     AvahiProtocol protocol,
485     AvahiPublishFlags flags,
486     const char *name,
487     const char *type,
488     const char *domain,
489     const char *host,
490     uint16_t port,
491     ...) {
492     
493     va_list va;
494     int r;
495     AvahiStringList *txt;
496
497     assert(group);
498
499     va_start(va, port);
500     txt = avahi_string_list_new_va(va);
501     r = avahi_entry_group_add_service_strlst(group, interface, protocol, flags, name, type, domain, host, port, txt);
502     avahi_string_list_free(txt);
503     va_end(va);
504     return r;
505 }
506
507 int avahi_entry_group_add_service_subtype(
508     AvahiEntryGroup *group,
509     AvahiIfIndex interface,
510     AvahiProtocol protocol,
511     AvahiPublishFlags flags,
512     const char *name,
513     const char *type,
514     const char *domain,
515     const char *subtype) {
516
517     DBusMessage *message = NULL, *reply = NULL;
518     int r = AVAHI_OK;
519     DBusError error;
520     AvahiClient *client;
521     int32_t i_interface, i_protocol;
522     uint32_t u_flags;
523
524     assert(group);
525     assert(name);
526     assert(type);
527     assert(subtype);
528
529     client = group->client;
530
531     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
532         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
533
534     if (!domain)
535         domain = "";
536
537     dbus_error_init(&error);
538     
539     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype"))) {
540         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
541         goto fail;
542     }
543
544     i_interface = (int32_t) interface;
545     i_protocol = (int32_t) protocol;
546     u_flags = (uint32_t) flags;
547
548     if (!dbus_message_append_args(
549             message,
550             DBUS_TYPE_INT32, &i_interface,
551             DBUS_TYPE_INT32, &i_protocol,
552             DBUS_TYPE_UINT32, &u_flags,
553             DBUS_TYPE_STRING, &name,
554             DBUS_TYPE_STRING, &type,
555             DBUS_TYPE_STRING, &domain,
556             DBUS_TYPE_STRING, &subtype,
557             DBUS_TYPE_INVALID)) {
558         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
559         goto fail;
560     }
561     
562     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
563         dbus_error_is_set (&error)) {
564         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
565         goto fail;
566     }
567     
568     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
569         dbus_error_is_set (&error)) {
570         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
571         goto fail;
572     }
573
574     dbus_message_unref(message);
575     dbus_message_unref(reply);
576
577     return AVAHI_OK;
578
579 fail:
580     
581     if (dbus_error_is_set(&error)) {
582         r = avahi_client_set_dbus_error(client, &error);
583         dbus_error_free(&error);
584     }
585
586     if (message)
587         dbus_message_unref(message);
588
589     if (reply)
590         dbus_message_unref(reply);
591
592     return r;
593
594 }
595
596 int avahi_entry_group_update_service_txt(
597     AvahiEntryGroup *group,
598     AvahiIfIndex interface,
599     AvahiProtocol protocol,
600     AvahiPublishFlags flags,
601     const char *name,     
602     const char *type,     
603     const char *domain,   
604     ...) {
605
606     va_list va;
607     int r;
608     AvahiStringList *txt;
609
610     va_start(va, domain);
611     txt = avahi_string_list_new_va(va);
612     r = avahi_entry_group_update_service_txt_strlst(group, interface, protocol, flags, name, type, domain, txt);
613     avahi_string_list_free(txt);
614     va_end(va);
615     return r;
616 }
617
618 int avahi_entry_group_update_service_txt_strlst(
619     AvahiEntryGroup *group,
620     AvahiIfIndex interface,
621     AvahiProtocol protocol,
622     AvahiPublishFlags flags,
623     const char *name,     
624     const char *type,     
625     const char *domain,   
626     AvahiStringList *txt) {
627
628     DBusMessage *message = NULL, *reply = NULL;
629     int r = AVAHI_OK;
630     DBusError error;
631     AvahiClient *client;
632     int32_t i_interface, i_protocol;
633     uint32_t u_flags;
634
635     assert(group);
636     assert(name);
637     assert(type);
638
639     client = group->client;
640
641     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
642         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
643
644     if (!domain)
645         domain = "";
646     
647     dbus_error_init(&error);
648     
649     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt"))) {
650         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
651         goto fail;
652     }
653
654     i_interface = (int32_t) interface;
655     i_protocol = (int32_t) protocol;
656     u_flags = (uint32_t) flags;
657
658     if (!dbus_message_append_args(
659             message,
660             DBUS_TYPE_INT32, &i_interface,
661             DBUS_TYPE_INT32, &i_protocol,
662             DBUS_TYPE_UINT32, &u_flags,
663             DBUS_TYPE_STRING, &name,
664             DBUS_TYPE_STRING, &type,
665             DBUS_TYPE_STRING, &domain,
666             DBUS_TYPE_INVALID) ||
667         append_string_list(message, txt) < 0) {
668         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
669         goto fail;
670     }
671
672     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
673         dbus_error_is_set (&error)) {
674         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
675         goto fail;
676     }
677     
678     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
679         dbus_error_is_set (&error)) {
680         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
681         goto fail;
682     }
683
684     dbus_message_unref(message);
685     dbus_message_unref(reply);
686
687     return AVAHI_OK;
688
689 fail:
690     
691     if (dbus_error_is_set(&error)) {
692         r = avahi_client_set_dbus_error(client, &error);
693         dbus_error_free(&error);
694     }
695
696     if (message)
697         dbus_message_unref(message);
698
699     if (reply)
700         dbus_message_unref(reply);
701
702     return r;
703     
704     
705 }
706
707 /** Add a host/address pair */
708 int avahi_entry_group_add_address(
709     AvahiEntryGroup *group,
710     AvahiIfIndex interface,
711     AvahiProtocol protocol,
712     AvahiPublishFlags flags,
713     const char *name,
714     const AvahiAddress *a) {
715
716     DBusMessage *message = NULL, *reply = NULL;
717     int r = AVAHI_OK;
718     DBusError error;
719     AvahiClient *client;
720     int32_t i_interface, i_protocol;
721     uint32_t u_flags;
722     char s_address[AVAHI_ADDRESS_STR_MAX];
723     char *p_address = s_address;
724
725     assert(name);
726
727     client = group->client;
728
729     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
730         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
731
732     dbus_error_init(&error);
733     
734     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress"))) {
735         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
736         goto fail;
737     }
738
739     i_interface = (int32_t) interface;
740     i_protocol = (int32_t) protocol;
741     u_flags = (uint32_t) flags;
742         
743     if (!avahi_address_snprint (s_address, sizeof (s_address), a))
744     {
745         r = avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS);
746         goto fail;
747     }
748
749     if (!dbus_message_append_args(
750             message,
751             DBUS_TYPE_INT32, &i_interface,
752             DBUS_TYPE_INT32, &i_protocol,
753             DBUS_TYPE_UINT32, &u_flags,
754             DBUS_TYPE_STRING, &name,
755             DBUS_TYPE_STRING, &p_address,
756             DBUS_TYPE_INVALID)) {
757         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
758         goto fail;
759     }
760     
761     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
762         dbus_error_is_set (&error)) {
763         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
764         goto fail;
765     }
766     
767     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
768         dbus_error_is_set (&error)) {
769         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
770         goto fail;
771     }
772
773     dbus_message_unref(message);
774     dbus_message_unref(reply);
775
776     return AVAHI_OK;
777
778 fail:
779     
780     if (dbus_error_is_set(&error)) {
781         r = avahi_client_set_dbus_error(client, &error);
782         dbus_error_free(&error);
783     }
784
785     if (message)
786         dbus_message_unref(message);
787
788     if (reply)
789         dbus_message_unref(reply);
790
791     return r;
792 }
793
794 /** Add an arbitrary record */
795 int avahi_entry_group_add_record(
796     AvahiEntryGroup *group,
797     AvahiIfIndex interface,
798     AvahiProtocol protocol,
799     AvahiPublishFlags flags,
800     const char *name,
801     uint16_t clazz,
802     uint16_t type,
803     uint32_t ttl,
804     const void *rdata,
805     size_t size) {
806
807     DBusMessage *message = NULL, *reply = NULL;
808     int r = AVAHI_OK;
809     DBusError error;
810     AvahiClient *client;
811     int32_t i_interface, i_protocol;
812     uint32_t u_flags;
813
814     assert(name);
815
816     client = group->client;
817
818     if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED)
819         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
820
821     dbus_error_init(&error);
822     
823     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord"))) {
824         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
825         goto fail;
826     }
827
828     i_interface = (int32_t) interface;
829     i_protocol = (int32_t) protocol;
830     u_flags = (uint32_t) flags;
831         
832     if (!dbus_message_append_args(
833             message,
834             DBUS_TYPE_INT32, &i_interface,
835             DBUS_TYPE_INT32, &i_protocol,
836             DBUS_TYPE_UINT32, &u_flags,
837             DBUS_TYPE_STRING, &name,
838             DBUS_TYPE_UINT16, &clazz,
839             DBUS_TYPE_UINT16, &type,
840             DBUS_TYPE_UINT32, &ttl,
841             DBUS_TYPE_INVALID) || append_rdata(message, rdata, size) < 0) {
842         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
843         goto fail;
844     }
845     
846     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
847         dbus_error_is_set (&error)) {
848         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
849         goto fail;
850     }
851     
852     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
853         dbus_error_is_set (&error)) {
854         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
855         goto fail;
856     }
857
858     dbus_message_unref(message);
859     dbus_message_unref(reply);
860
861     return AVAHI_OK;
862
863 fail:
864     
865     if (dbus_error_is_set(&error)) {
866         r = avahi_client_set_dbus_error(client, &error);
867         dbus_error_free(&error);
868     }
869
870     if (message)
871         dbus_message_unref(message);
872
873     if (reply)
874         dbus_message_unref(reply);
875
876     return r;
877 }