4 This file is part of avahi.
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.
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.
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
30 #include <dbus/dbus.h>
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>
41 void avahi_entry_group_set_state(AvahiEntryGroup *group, AvahiEntryGroupState state) {
44 if (group->state == state)
50 group->callback(group, state, group->userdata);
53 static int retrieve_state(AvahiEntryGroup *group) {
54 DBusMessage *message = NULL, *reply = NULL;
60 dbus_error_init(&error);
63 client = group->client;
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);
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);
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);
82 dbus_message_unref(message);
83 dbus_message_unref(reply);
85 avahi_entry_group_set_state(group, (AvahiEntryGroupState) state);
90 if (dbus_error_is_set(&error)) {
91 r = avahi_client_set_dbus_error(client, &error);
92 dbus_error_free(&error);
96 dbus_message_unref(message);
99 dbus_message_unref(reply);
104 AvahiEntryGroup* avahi_entry_group_new (AvahiClient *client, AvahiEntryGroupCallback callback, void *userdata) {
105 AvahiEntryGroup *group = NULL;
106 DBusMessage *message = NULL, *reply = NULL;
112 dbus_error_init (&error);
114 if (!avahi_client_is_connected(client)) {
115 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
119 if (!(group = avahi_new(AvahiEntryGroup, 1))) {
120 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
124 group->client = client;
125 group->callback = callback;
126 group->userdata = userdata;
127 group->state = AVAHI_ENTRY_GROUP_UNCOMMITED;
129 AVAHI_LLIST_PREPEND(AvahiEntryGroup, groups, client->groups, group);
131 if (!(message = dbus_message_new_method_call(
133 AVAHI_DBUS_PATH_SERVER,
134 AVAHI_DBUS_INTERFACE_SERVER,
136 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
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);
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);
152 if (!(group->path = avahi_strdup (path))) {
154 /* FIXME: We don't remove the object on the server side */
156 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
160 if (retrieve_state(group) < 0)
163 dbus_message_unref(message);
164 dbus_message_unref(reply);
169 if (dbus_error_is_set(&error)) {
170 avahi_client_set_dbus_error(client, &error);
171 dbus_error_free(&error);
175 avahi_entry_group_free(group);
178 dbus_message_unref(message);
181 dbus_message_unref(reply);
186 static int entry_group_simple_method_call(AvahiEntryGroup *group, const char *method) {
187 DBusMessage *message = NULL, *reply = NULL;
192 dbus_error_init(&error);
195 client = group->client;
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);
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);
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);
214 dbus_message_unref(message);
215 dbus_message_unref(reply);
220 if (dbus_error_is_set(&error)) {
221 r = avahi_client_set_dbus_error(client, &error);
222 dbus_error_free(&error);
226 dbus_message_unref(message);
229 dbus_message_unref(reply);
234 int avahi_entry_group_free(AvahiEntryGroup *group) {
235 AvahiClient *client = group->client;
240 if (group->path && avahi_client_is_connected(client))
241 r = entry_group_simple_method_call(group, "Free");
243 AVAHI_LLIST_REMOVE(AvahiEntryGroup, groups, client->groups, group);
245 avahi_free(group->path);
251 int avahi_entry_group_commit(AvahiEntryGroup *group) {
255 if (!group->path || !avahi_client_is_connected(group->client))
256 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
258 if ((ret = entry_group_simple_method_call(group, "Commit")) < 0)
261 avahi_entry_group_set_state(group, AVAHI_ENTRY_GROUP_REGISTERING);
265 int avahi_entry_group_reset(AvahiEntryGroup *group) {
269 if (!group->path || !avahi_client_is_connected(group->client))
270 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
272 if ((ret = entry_group_simple_method_call(group, "Reset")) < 0)
275 avahi_entry_group_set_state(group, AVAHI_ENTRY_GROUP_UNCOMMITED);
279 int avahi_entry_group_get_state (AvahiEntryGroup *group) {
285 AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup *group) {
288 return group->client;
291 int avahi_entry_group_is_empty (AvahiEntryGroup *group) {
292 DBusMessage *message = NULL, *reply = NULL;
299 client = group->client;
301 if (!group->path || !avahi_client_is_connected(group->client))
302 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
304 dbus_error_init(&error);
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);
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);
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);
323 dbus_message_unref(message);
324 dbus_message_unref(reply);
329 if (dbus_error_is_set(&error)) {
330 r = avahi_client_set_dbus_error(client, &error);
331 dbus_error_free(&error);
335 dbus_message_unref(message);
338 dbus_message_unref(reply);
343 static int append_rdata(DBusMessage *message, const void *rdata, size_t size) {
344 DBusMessageIter iter, sub;
348 dbus_message_iter_init_append(message, &iter);
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)))
358 static int append_string_list(DBusMessage *message, AvahiStringList *txt) {
359 DBusMessageIter iter, sub;
365 dbus_message_iter_init_append(message, &iter);
367 /* Reverse the string list, so that we can pass it in-order to the server */
368 txt = avahi_string_list_reverse(txt);
370 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub))
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;
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)))
384 if (!dbus_message_iter_close_container(&iter, &sub))
391 /* Reverse the string list to the original state */
392 txt = avahi_string_list_reverse(txt);
397 int avahi_entry_group_add_service_strlst(
398 AvahiEntryGroup *group,
399 AvahiIfIndex interface,
400 AvahiProtocol protocol,
401 AvahiPublishFlags flags,
407 AvahiStringList *txt) {
409 DBusMessage *message = NULL, *reply = NULL;
413 int32_t i_interface, i_protocol;
420 client = group->client;
422 if (!group->path || !avahi_client_is_connected(group->client))
423 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
431 dbus_error_init(&error);
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);
438 i_interface = (int32_t) interface;
439 i_protocol = (int32_t) protocol;
440 u_flags = (uint32_t) flags;
442 if (!dbus_message_append_args(
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);
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);
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);
470 dbus_message_unref(message);
471 dbus_message_unref(reply);
477 if (dbus_error_is_set(&error)) {
478 r = avahi_client_set_dbus_error(client, &error);
479 dbus_error_free(&error);
483 dbus_message_unref(message);
486 dbus_message_unref(reply);
491 int avahi_entry_group_add_service(
492 AvahiEntryGroup *group,
493 AvahiIfIndex interface,
494 AvahiProtocol protocol,
495 AvahiPublishFlags flags,
505 AvahiStringList *txt;
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);
517 int avahi_entry_group_add_service_subtype(
518 AvahiEntryGroup *group,
519 AvahiIfIndex interface,
520 AvahiProtocol protocol,
521 AvahiPublishFlags flags,
525 const char *subtype) {
527 DBusMessage *message = NULL, *reply = NULL;
531 int32_t i_interface, i_protocol;
539 client = group->client;
541 if (!group->path || !avahi_client_is_connected(group->client))
542 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
547 dbus_error_init(&error);
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);
554 i_interface = (int32_t) interface;
555 i_protocol = (int32_t) protocol;
556 u_flags = (uint32_t) flags;
558 if (!dbus_message_append_args(
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);
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);
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);
584 dbus_message_unref(message);
585 dbus_message_unref(reply);
591 if (dbus_error_is_set(&error)) {
592 r = avahi_client_set_dbus_error(client, &error);
593 dbus_error_free(&error);
597 dbus_message_unref(message);
600 dbus_message_unref(reply);
606 int avahi_entry_group_update_service_txt(
607 AvahiEntryGroup *group,
608 AvahiIfIndex interface,
609 AvahiProtocol protocol,
610 AvahiPublishFlags flags,
618 AvahiStringList *txt;
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);
628 int avahi_entry_group_update_service_txt_strlst(
629 AvahiEntryGroup *group,
630 AvahiIfIndex interface,
631 AvahiProtocol protocol,
632 AvahiPublishFlags flags,
636 AvahiStringList *txt) {
638 DBusMessage *message = NULL, *reply = NULL;
642 int32_t i_interface, i_protocol;
649 client = group->client;
651 if (!group->path || !avahi_client_is_connected(group->client))
652 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
657 dbus_error_init(&error);
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);
664 i_interface = (int32_t) interface;
665 i_protocol = (int32_t) protocol;
666 u_flags = (uint32_t) flags;
668 if (!dbus_message_append_args(
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);
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);
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);
694 dbus_message_unref(message);
695 dbus_message_unref(reply);
701 if (dbus_error_is_set(&error)) {
702 r = avahi_client_set_dbus_error(client, &error);
703 dbus_error_free(&error);
707 dbus_message_unref(message);
710 dbus_message_unref(reply);
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,
722 const AvahiAddress *a) {
724 DBusMessage *message = NULL, *reply = NULL;
728 int32_t i_interface, i_protocol;
730 char s_address[AVAHI_ADDRESS_STR_MAX];
731 char *p_address = s_address;
735 client = group->client;
737 if (!group->path || !avahi_client_is_connected(group->client))
738 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
740 dbus_error_init(&error);
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);
747 i_interface = (int32_t) interface;
748 i_protocol = (int32_t) protocol;
749 u_flags = (uint32_t) flags;
751 if (!avahi_address_snprint (s_address, sizeof (s_address), a))
753 r = avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS);
757 if (!dbus_message_append_args(
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);
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);
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);
781 dbus_message_unref(message);
782 dbus_message_unref(reply);
788 if (dbus_error_is_set(&error)) {
789 r = avahi_client_set_dbus_error(client, &error);
790 dbus_error_free(&error);
794 dbus_message_unref(message);
797 dbus_message_unref(reply);
802 /** Add an arbitrary record */
803 int avahi_entry_group_add_record(
804 AvahiEntryGroup *group,
805 AvahiIfIndex interface,
806 AvahiProtocol protocol,
807 AvahiPublishFlags flags,
815 DBusMessage *message = NULL, *reply = NULL;
819 int32_t i_interface, i_protocol;
824 client = group->client;
826 if (!group->path || !avahi_client_is_connected(group->client))
827 return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
829 dbus_error_init(&error);
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);
836 i_interface = (int32_t) interface;
837 i_protocol = (int32_t) protocol;
838 u_flags = (uint32_t) flags;
840 if (!dbus_message_append_args(
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);
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);
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);
866 dbus_message_unref(message);
867 dbus_message_unref(reply);
873 if (dbus_error_is_set(&error)) {
874 r = avahi_client_set_dbus_error(client, &error);
875 dbus_error_free(&error);
879 dbus_message_unref(message);
882 dbus_message_unref(reply);