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