Lines Matching defs:*
0 /* $Id$ */
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
19 USA.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
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>
37 #include <avahi-common/domain.h>
39 #include "client.h"
40 #include "internal.h"
41 #include "xdg-config.h"
43 static void parse_environment(AvahiDomainBrowser *b) {
44 char buf[AVAHI_DOMAIN_NAME_MAX*3], *e, *t, *p;
46 assert(b);
48 if (!(e = getenv("AVAHI_BROWSE_DOMAINS")))
49 return;
51 snprintf(buf, sizeof(buf), "%s", e);
53 for (t = strtok_r(buf, ":", &p); t; t = strtok_r(NULL, ":", &p)) {
54 char domain[AVAHI_DOMAIN_NAME_MAX];
55 if (avahi_normalize_name(t, domain, sizeof(domain)))
56 b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain);
60 static void parse_domain_file(AvahiDomainBrowser *b) {
61 FILE *f;
62 char buf[AVAHI_DOMAIN_NAME_MAX];
64 assert(b);
66 if (!(f = avahi_xdg_config_open("avahi/browse-domains")))
67 return;
70 while (fgets(buf, sizeof(buf)-1, f)) {
71 char domain[AVAHI_DOMAIN_NAME_MAX];
72 buf[strcspn(buf, "\n\r")] = 0;
74 if (avahi_normalize_name(buf, domain, sizeof(domain)))
75 b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain);
79 static void domain_browser_ref(AvahiDomainBrowser *db) {
80 assert(db);
81 assert(db->ref >= 1);
82 db->ref++;
85 static void defer_timeout_callback(AvahiTimeout *t, void *userdata) {
86 AvahiDomainBrowser *db = userdata;
87 AvahiStringList *l;
88 assert(t);
90 db->client->poll_api->timeout_free(db->defer_timeout);
91 db->defer_timeout = NULL;
93 domain_browser_ref(db);
95 for (l = db->static_browse_domains; l; l = l->next) {
97 if (db->ref <= 1)
98 break;
100 db->callback(db, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_BROWSER_NEW, (char*) l->text, AVAHI_LOOKUP_RESULT_STATIC, db->userdata);
103 avahi_domain_browser_free(db);
106 AvahiDomainBrowser* avahi_domain_browser_new(
107 AvahiClient *client,
108 AvahiIfIndex interface,
109 AvahiProtocol protocol,
110 const char *domain,
111 AvahiDomainBrowserType btype,
112 AvahiLookupFlags flags,
113 AvahiDomainBrowserCallback callback,
114 void *userdata) {
116 AvahiDomainBrowser *db = NULL;
117 DBusMessage *message = NULL, *reply = NULL;
118 DBusError error;
119 char *path;
120 int32_t i_interface, i_protocol, bt;
121 uint32_t u_flags;
123 assert(client);
124 assert(callback);
126 dbus_error_init (&error);
128 if (!avahi_client_is_connected(client)) {
129 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
130 goto fail;
133 if (!domain)
134 domain = "";
136 if (!(db = avahi_new (AvahiDomainBrowser, 1))) {
137 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
138 goto fail;
141 db->ref = 1;
142 db->client = client;
143 db->callback = callback;
144 db->userdata = userdata;
145 db->path = NULL;
146 db->interface = interface;
147 db->protocol = protocol;
148 db->static_browse_domains = NULL;
149 db->defer_timeout = NULL;
151 AVAHI_LLIST_PREPEND(AvahiDomainBrowser, domain_browsers, client->domain_browsers, db);
153 if (!(client->flags & AVAHI_CLIENT_IGNORE_USER_CONFIG)) {
154 parse_environment(db);
155 parse_domain_file(db);
158 db->static_browse_domains = avahi_string_list_reverse(db->static_browse_domains);
160 if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew"))) {
161 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
162 goto fail;
165 i_interface = (int32_t) interface;
166 i_protocol = (int32_t) protocol;
167 u_flags = (uint32_t) flags;
168 bt = btype;
170 if (!(dbus_message_append_args(
171 message,
172 DBUS_TYPE_INT32, &i_interface,
173 DBUS_TYPE_INT32, &i_protocol,
174 DBUS_TYPE_STRING, &domain,
175 DBUS_TYPE_INT32, &bt,
176 DBUS_TYPE_UINT32, &flags,
177 DBUS_TYPE_INVALID))) {
178 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
179 goto fail;
182 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
183 dbus_error_is_set(&error)) {
184 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
185 goto fail;
188 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
189 dbus_error_is_set(&error) ||
190 !path) {
191 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
192 goto fail;
195 if (!(db->path = avahi_strdup(path))) {
197 /* FIXME: We don't remove the object on the server side */
199 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
200 goto fail;
203 if (db->static_browse_domains && btype == AVAHI_DOMAIN_BROWSER_BROWSE) {
204 struct timeval tv = { 0, 0 };
206 if (!(db->defer_timeout = client->poll_api->timeout_new(client->poll_api, &tv, defer_timeout_callback, db))) {
207 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
208 goto fail;
212 dbus_message_unref(message);
213 dbus_message_unref(reply);
215 return db;
217 fail:
219 if (dbus_error_is_set(&error)) {
220 avahi_client_set_dbus_error(client, &error);
221 dbus_error_free(&error);
224 if (db)
225 avahi_domain_browser_free(db);
227 if (message)
228 dbus_message_unref(message);
230 if (reply)
231 dbus_message_unref(reply);
233 return NULL;
236 AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b) {
237 assert(b);
238 return b->client;
241 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
242 AvahiClient *client;
243 int r = AVAHI_OK;
245 assert(b);
246 assert(b->ref >= 1);
248 if (--(b->ref) >= 1)
249 return AVAHI_OK;
251 client = b->client;
253 if (b->path && avahi_client_is_connected(b->client))
254 r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
256 AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
258 if (b->defer_timeout)
259 b->client->poll_api->timeout_free(b->defer_timeout);
261 avahi_string_list_free(b->static_browse_domains);
262 avahi_free(b->path);
263 avahi_free(b);
265 return r;
268 DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
269 AvahiDomainBrowser *db = NULL;
270 DBusError error;
271 const char *path;
272 char *domain = NULL;
273 int32_t interface, protocol;
274 uint32_t flags = 0;
275 AvahiStringList *l;
277 assert(client);
278 assert(message);
280 dbus_error_init (&error);
282 if (!(path = dbus_message_get_path(message)))
283 goto fail;
285 for (db = client->domain_browsers; db; db = db->domain_browsers_next)
286 if (strcmp (db->path, path) == 0)
287 break;
289 if (!db)
290 goto fail;
292 interface = db->interface;
293 protocol = db->protocol;
295 switch (event) {
296 case AVAHI_BROWSER_NEW:
297 case AVAHI_BROWSER_REMOVE:
299 if (!dbus_message_get_args(
300 message, &error,
301 DBUS_TYPE_INT32, &interface,
302 DBUS_TYPE_INT32, &protocol,
303 DBUS_TYPE_STRING, &domain,
304 DBUS_TYPE_UINT32, &flags,
305 DBUS_TYPE_INVALID) ||
306 dbus_error_is_set (&error)) {
307 fprintf(stderr, "Failed to parse browser event.\n");
308 goto fail;
311 break;
313 case AVAHI_BROWSER_CACHE_EXHAUSTED:
314 case AVAHI_BROWSER_ALL_FOR_NOW:
315 break;
317 case AVAHI_BROWSER_FAILURE: {
318 char *etxt;
320 if (!dbus_message_get_args(
321 message, &error,
322 DBUS_TYPE_STRING, &etxt,
323 DBUS_TYPE_INVALID) ||
324 dbus_error_is_set (&error)) {
325 fprintf(stderr, "Failed to parse browser event.\n");
326 goto fail;
329 avahi_client_set_errno(db->client, avahi_error_dbus_to_number(etxt));
330 break;
334 if (domain)
335 for (l = db->static_browse_domains; l; l = l->next)
336 if (avahi_domain_equal((char*) l->text, domain)) {
337 /* We had this entry already in the static entries */
338 return DBUS_HANDLER_RESULT_HANDLED;
341 db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, (AvahiLookupResultFlags) flags, db->userdata);
343 return DBUS_HANDLER_RESULT_HANDLED;
345 fail:
346 dbus_error_free (&error);
347 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
350 /* AvahiServiceTypeBrowser */
352 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
353 AvahiClient *client,
354 AvahiIfIndex interface,
355 AvahiProtocol protocol,
356 const char *domain,
357 AvahiLookupFlags flags,
358 AvahiServiceTypeBrowserCallback callback,
359 void *userdata) {
361 AvahiServiceTypeBrowser *b = NULL;
362 DBusMessage *message = NULL, *reply = NULL;
363 DBusError error;
364 char *path;
365 int32_t i_interface, i_protocol;
366 uint32_t u_flags;
368 assert(client);
369 assert(callback);
371 dbus_error_init(&error);
373 if (!avahi_client_is_connected(client)) {
374 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
375 goto fail;
378 if (!domain)
379 domain = "";
381 if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
382 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
383 goto fail;
386 b->client = client;
387 b->callback = callback;
388 b->userdata = userdata;
389 b->path = NULL;
390 b->domain = NULL;
391 b->interface = interface;
392 b->protocol = protocol;
394 AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
396 if (domain[0])
397 if (!(b->domain = avahi_strdup(domain))) {
398 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
399 goto fail;
402 if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew"))) {
403 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
404 goto fail;
407 i_interface = (int32_t) interface;
408 i_protocol = (int32_t) protocol;
409 u_flags = (uint32_t) flags;
411 if (!dbus_message_append_args(
412 message,
413 DBUS_TYPE_INT32, &i_interface,
414 DBUS_TYPE_INT32, &i_protocol,
415 DBUS_TYPE_STRING, &domain,
416 DBUS_TYPE_UINT32, &u_flags,
417 DBUS_TYPE_INVALID)) {
418 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
419 goto fail;
422 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
423 dbus_error_is_set(&error)) {
424 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
425 goto fail;
428 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
429 dbus_error_is_set(&error) ||
430 !path) {
431 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
432 goto fail;
435 if (!(b->path = avahi_strdup(path))) {
437 /* FIXME: We don't remove the object on the server side */
439 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
440 goto fail;
443 dbus_message_unref(message);
444 dbus_message_unref(reply);
446 return b;
448 fail:
450 if (dbus_error_is_set(&error)) {
451 avahi_client_set_dbus_error(client, &error);
452 dbus_error_free(&error);
455 if (b)
456 avahi_service_type_browser_free(b);
458 if (message)
459 dbus_message_unref(message);
461 if (reply)
462 dbus_message_unref(reply);
464 return NULL;
467 AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *b) {
468 assert(b);
469 return b->client;
472 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
473 AvahiClient *client;
474 int r = AVAHI_OK;
476 assert(b);
477 client = b->client;
479 if (b->path && avahi_client_is_connected(b->client))
480 r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
482 AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
484 avahi_free(b->path);
485 avahi_free(b->domain);
486 avahi_free(b);
487 return r;
490 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
491 AvahiServiceTypeBrowser *b = NULL;
492 DBusError error;
493 const char *path;
494 char *domain, *type = NULL;
495 int32_t interface, protocol;
496 uint32_t flags = 0;
498 assert(client);
499 assert(message);
501 dbus_error_init (&error);
503 if (!(path = dbus_message_get_path(message)))
504 goto fail;
506 for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
507 if (strcmp (b->path, path) == 0)
508 break;
510 if (!b)
511 goto fail;
513 domain = b->domain;
514 interface = b->interface;
515 protocol = b->protocol;
517 switch (event) {
518 case AVAHI_BROWSER_NEW:
519 case AVAHI_BROWSER_REMOVE:
520 if (!dbus_message_get_args(
521 message, &error,
522 DBUS_TYPE_INT32, &interface,
523 DBUS_TYPE_INT32, &protocol,
524 DBUS_TYPE_STRING, &type,
525 DBUS_TYPE_STRING, &domain,
526 DBUS_TYPE_UINT32, &flags,
527 DBUS_TYPE_INVALID) ||
528 dbus_error_is_set(&error)) {
529 fprintf(stderr, "Failed to parse browser event.\n");
530 goto fail;
532 break;
534 case AVAHI_BROWSER_CACHE_EXHAUSTED:
535 case AVAHI_BROWSER_ALL_FOR_NOW:
536 break;
538 case AVAHI_BROWSER_FAILURE: {
539 char *etxt;
541 if (!dbus_message_get_args(
542 message, &error,
543 DBUS_TYPE_STRING, &etxt,
544 DBUS_TYPE_INVALID) ||
545 dbus_error_is_set (&error)) {
546 fprintf(stderr, "Failed to parse browser event.\n");
547 goto fail;
550 avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
551 break;
555 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
557 return DBUS_HANDLER_RESULT_HANDLED;
559 fail:
560 dbus_error_free (&error);
561 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
564 /* AvahiServiceBrowser */
566 AvahiServiceBrowser* avahi_service_browser_new(
567 AvahiClient *client,
568 AvahiIfIndex interface,
569 AvahiProtocol protocol,
570 const char *type,
571 const char *domain,
572 AvahiLookupFlags flags,
573 AvahiServiceBrowserCallback callback,
574 void *userdata) {
576 AvahiServiceBrowser *b = NULL;
577 DBusMessage *message = NULL, *reply = NULL;
578 DBusError error;
579 char *path;
580 int32_t i_protocol, i_interface;
581 uint32_t u_flags;
583 assert(client);
584 assert(type);
585 assert(callback);
587 dbus_error_init(&error);
589 if (!avahi_client_is_connected(client)) {
590 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
591 goto fail;
594 if (!domain)
595 domain = "";
597 if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
598 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
599 goto fail;
602 b->client = client;
603 b->callback = callback;
604 b->userdata = userdata;
605 b->path = NULL;
606 b->type = b->domain = NULL;
607 b->interface = interface;
608 b->protocol = protocol;
610 AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
612 if (!(b->type = avahi_strdup(type))) {
613 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
614 goto fail;
617 if (domain && domain[0])
618 if (!(b->domain = avahi_strdup(domain))) {
619 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
620 goto fail;
623 if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew"))) {
624 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
625 goto fail;
628 i_interface = (int32_t) interface;
629 i_protocol = (int32_t) protocol;
630 u_flags = (uint32_t) flags;
632 if (!dbus_message_append_args(
633 message,
634 DBUS_TYPE_INT32, &i_interface,
635 DBUS_TYPE_INT32, &i_protocol,
636 DBUS_TYPE_STRING, &type,
637 DBUS_TYPE_STRING, &domain,
638 DBUS_TYPE_UINT32, &u_flags,
639 DBUS_TYPE_INVALID)) {
640 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
641 goto fail;
644 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
645 dbus_error_is_set(&error)) {
646 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
647 goto fail;
650 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
651 dbus_error_is_set(&error) ||
652 !path) {
653 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
654 goto fail;
657 if (!(b->path = avahi_strdup(path))) {
659 /* FIXME: We don't remove the object on the server side */
661 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
662 goto fail;
665 dbus_message_unref(message);
666 dbus_message_unref(reply);
668 return b;
670 fail:
671 if (dbus_error_is_set(&error)) {
672 avahi_client_set_dbus_error(client, &error);
673 dbus_error_free(&error);
676 if (b)
677 avahi_service_browser_free(b);
679 if (message)
680 dbus_message_unref(message);
682 if (reply)
683 dbus_message_unref(reply);
685 return NULL;
688 AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *b) {
689 assert(b);
690 return b->client;
693 int avahi_service_browser_free (AvahiServiceBrowser *b) {
694 AvahiClient *client;
695 int r = AVAHI_OK;
697 assert(b);
698 client = b->client;
700 if (b->path && avahi_client_is_connected(b->client))
701 r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
703 AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
705 avahi_free(b->path);
706 avahi_free(b->type);
707 avahi_free(b->domain);
708 avahi_free(b);
709 return r;
712 DBusHandlerResult avahi_service_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
713 AvahiServiceBrowser *b = NULL;
714 DBusError error;
715 const char *path;
716 char *name = NULL, *type, *domain;
717 int32_t interface, protocol;
718 uint32_t flags = 0;
720 dbus_error_init (&error);
722 if (!(path = dbus_message_get_path(message)))
723 goto fail;
725 for (b = client->service_browsers; b; b = b->service_browsers_next)
726 if (strcmp (b->path, path) == 0)
727 break;
729 if (!b)
730 goto fail;
732 type = b->type;
733 domain = b->domain;
734 interface = b->interface;
735 protocol = b->protocol;
737 switch (event) {
738 case AVAHI_BROWSER_NEW:
739 case AVAHI_BROWSER_REMOVE:
741 if (!dbus_message_get_args (
742 message, &error,
743 DBUS_TYPE_INT32, &interface,
744 DBUS_TYPE_INT32, &protocol,
745 DBUS_TYPE_STRING, &name,
746 DBUS_TYPE_STRING, &type,
747 DBUS_TYPE_STRING, &domain,
748 DBUS_TYPE_UINT32, &flags,
749 DBUS_TYPE_INVALID) ||
750 dbus_error_is_set(&error)) {
751 fprintf(stderr, "Failed to parse browser event.\n");
752 goto fail;
754 break;
756 case AVAHI_BROWSER_CACHE_EXHAUSTED:
757 case AVAHI_BROWSER_ALL_FOR_NOW:
758 break;
760 case AVAHI_BROWSER_FAILURE: {
761 char *etxt;
763 if (!dbus_message_get_args(
764 message, &error,
765 DBUS_TYPE_STRING, &etxt,
766 DBUS_TYPE_INVALID) ||
767 dbus_error_is_set (&error)) {
768 fprintf(stderr, "Failed to parse browser event.\n");
769 goto fail;
772 avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
773 break;
777 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
779 return DBUS_HANDLER_RESULT_HANDLED;
781 fail:
782 dbus_error_free (&error);
783 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
786 /* AvahiRecordBrowser */
788 AvahiRecordBrowser* avahi_record_browser_new(
789 AvahiClient *client,
790 AvahiIfIndex interface,
791 AvahiProtocol protocol,
792 const char *name,
793 uint16_t clazz,
794 uint16_t type,
795 AvahiLookupFlags flags,
796 AvahiRecordBrowserCallback callback,
797 void *userdata) {
799 AvahiRecordBrowser *b = NULL;
800 DBusMessage *message = NULL, *reply = NULL;
801 DBusError error;
802 char *path;
803 int32_t i_protocol, i_interface;
804 uint32_t u_flags;
806 assert(client);
807 assert(name);
808 assert(callback);
810 dbus_error_init(&error);
812 if (!avahi_client_is_connected(client)) {
813 avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
814 goto fail;
817 if (!(b = avahi_new(AvahiRecordBrowser, 1))) {
818 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
819 goto fail;
822 b->client = client;
823 b->callback = callback;
824 b->userdata = userdata;
825 b->path = NULL;
826 b->name = NULL;
827 b->clazz = clazz;
828 b->type = type;
829 b->interface = interface;
830 b->protocol = protocol;
832 AVAHI_LLIST_PREPEND(AvahiRecordBrowser, record_browsers, client->record_browsers, b);
834 if (!(b->name = avahi_strdup(name))) {
835 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
836 goto fail;
839 if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew"))) {
840 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
841 goto fail;
844 i_interface = (int32_t) interface;
845 i_protocol = (int32_t) protocol;
846 u_flags = (uint32_t) flags;
848 if (!dbus_message_append_args(
849 message,
850 DBUS_TYPE_INT32, &i_interface,
851 DBUS_TYPE_INT32, &i_protocol,
852 DBUS_TYPE_STRING, &name,
853 DBUS_TYPE_UINT16, &clazz,
854 DBUS_TYPE_UINT16, &type,
855 DBUS_TYPE_UINT32, &u_flags,
856 DBUS_TYPE_INVALID)) {
857 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
858 goto fail;
861 if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
862 dbus_error_is_set(&error)) {
863 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
864 goto fail;
867 if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
868 dbus_error_is_set(&error) ||
869 !path) {
870 avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
871 goto fail;
874 if (!(b->path = avahi_strdup(path))) {
876 /* FIXME: We don't remove the object on the server side */
878 avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
879 goto fail;
882 dbus_message_unref(message);
883 dbus_message_unref(reply);
885 return b;
887 fail:
888 if (dbus_error_is_set(&error)) {
889 avahi_client_set_dbus_error(client, &error);
890 dbus_error_free(&error);
893 if (b)
894 avahi_record_browser_free(b);
896 if (message)
897 dbus_message_unref(message);
899 if (reply)
900 dbus_message_unref(reply);
902 return NULL;
905 AvahiClient* avahi_record_browser_get_client (AvahiRecordBrowser *b) {
906 assert(b);
907 return b->client;
910 int avahi_record_browser_free (AvahiRecordBrowser *b) {
911 AvahiClient *client;
912 int r = AVAHI_OK;
914 assert(b);
915 client = b->client;
917 if (b->path && avahi_client_is_connected(b->client))
918 r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "Free");
920 AVAHI_LLIST_REMOVE(AvahiRecordBrowser, record_browsers, b->client->record_browsers, b);
922 avahi_free(b->path);
923 avahi_free(b->name);
924 avahi_free(b);
925 return r;
928 DBusHandlerResult avahi_record_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
929 AvahiRecordBrowser *b = NULL;
930 DBusError error;
931 const char *path;
932 char *name;
933 int32_t interface, protocol;
934 uint32_t flags = 0;
935 uint16_t clazz, type;
936 void *rdata = NULL;
937 int rdata_size = 0;
939 dbus_error_init (&error);
941 if (!(path = dbus_message_get_path(message)))
942 goto fail;
944 for (b = client->record_browsers; b; b = b->record_browsers_next)
945 if (strcmp (b->path, path) == 0)
946 break;
948 if (!b)
949 goto fail;
951 interface = b->interface;
952 protocol = b->protocol;
953 clazz = b->clazz;
954 type = b->type;
955 name = b->name;
957 switch (event) {
958 case AVAHI_BROWSER_NEW:
959 case AVAHI_BROWSER_REMOVE: {
960 DBusMessageIter iter, sub;
961 int j;
963 if (!dbus_message_get_args (
964 message, &error,
965 DBUS_TYPE_INT32, &interface,
966 DBUS_TYPE_INT32, &protocol,
967 DBUS_TYPE_STRING, &name,
968 DBUS_TYPE_UINT16, &clazz,
969 DBUS_TYPE_UINT16, &type,
970 DBUS_TYPE_INVALID) ||
971 dbus_error_is_set(&error)) {
972 fprintf(stderr, "Failed to parse browser event.\n");
973 goto fail;
977 dbus_message_iter_init(message, &iter);
979 for (j = 0; j < 5; j++)
980 dbus_message_iter_next(&iter);
982 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
983 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
984 goto fail;
986 dbus_message_iter_recurse(&iter, &sub);
987 dbus_message_iter_get_fixed_array(&sub, &rdata, &rdata_size);
989 dbus_message_iter_next(&iter);
991 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
992 goto fail;
994 dbus_message_iter_get_basic(&iter, &flags);
996 break;
999 case AVAHI_BROWSER_CACHE_EXHAUSTED:
1000 case AVAHI_BROWSER_ALL_FOR_NOW:
1001 break;
1003 case AVAHI_BROWSER_FAILURE: {
1004 char *etxt;
1006 if (!dbus_message_get_args(
1007 message, &error,
1008 DBUS_TYPE_STRING, &etxt,
1009 DBUS_TYPE_INVALID) ||
1010 dbus_error_is_set (&error)) {
1011 fprintf(stderr, "Failed to parse browser event.\n");
1012 goto fail;
1015 avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
1016 break;
1020 b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, clazz, type, rdata, (size_t) rdata_size, (AvahiLookupResultFlags) flags, b->userdata);
1022 return DBUS_HANDLER_RESULT_HANDLED;
1024 fail:
1025 dbus_error_free (&error);
1026 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;