]> git.meshlink.io Git - catta/blob - avahi-client/browser.c
* add new flags parameter to avahi_client_new()
[catta] / avahi-client / browser.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 #include <avahi-common/domain.h>
38
39 #include "client.h"
40 #include "internal.h"
41 #include "xdg-config.h"
42
43 static void parse_environment(AvahiDomainBrowser *b) {
44     char buf[AVAHI_DOMAIN_NAME_MAX*3], *e, *t, *p;
45
46     assert(b);
47     
48     if (!(e = getenv("AVAHI_BROWSE_DOMAINS")))
49         return;
50
51     snprintf(buf, sizeof(buf), "%s", e);
52
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);
57     }
58 }
59
60 static void parse_domain_file(AvahiDomainBrowser *b) {
61     FILE *f;
62     char buf[AVAHI_DOMAIN_NAME_MAX];
63     
64     assert(b);
65
66     if (!(f = avahi_xdg_config_open("avahi/browse-domains")))
67         return;
68     
69     
70     while (fgets(buf, sizeof(buf)-1, f)) {
71         char domain[AVAHI_DOMAIN_NAME_MAX];
72         buf[strcspn(buf, "\n\r")] = 0;
73         
74         if (avahi_normalize_name(buf, domain, sizeof(domain)))
75             b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain);
76     }
77 }
78
79 static void domain_browser_ref(AvahiDomainBrowser *db) {
80     assert(db);
81     assert(db->ref >= 1);
82     db->ref++;
83 }
84
85 static void defer_timeout_callback(AvahiTimeout *t, void *userdata) {
86     AvahiDomainBrowser *db = userdata;
87     AvahiStringList *l;
88     assert(t);
89
90     db->client->poll_api->timeout_free(db->defer_timeout);
91     db->defer_timeout = NULL;
92
93     domain_browser_ref(db);
94
95     for (l = db->static_browse_domains; l; l = l->next) {
96
97         if (db->ref <= 1)
98             break;
99
100         db->callback(db, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_BROWSER_NEW, (char*) l->text, AVAHI_LOOKUP_RESULT_STATIC, db->userdata);
101     }
102
103     avahi_domain_browser_free(db);
104 }
105
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) {
115     
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;
122
123     assert(client);
124     assert(callback);
125
126     dbus_error_init (&error);
127
128     if (!avahi_client_is_connected(client)) {
129         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
130         goto fail;
131     }
132
133     if (!domain)
134         domain = "";
135
136     if (!(db = avahi_new (AvahiDomainBrowser, 1))) {
137         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
138         goto fail;
139     }
140
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;
150
151     AVAHI_LLIST_PREPEND(AvahiDomainBrowser, domain_browsers, client->domain_browsers, db);
152
153     if (!(client->flags & AVAHI_CLIENT_IGNORE_USER_CONFIG)) {
154         parse_environment(db);
155         parse_domain_file(db);
156     }
157
158     db->static_browse_domains = avahi_string_list_reverse(db->static_browse_domains);
159     
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;
163     }
164
165     i_interface = (int32_t) interface;
166     i_protocol = (int32_t) protocol;
167     u_flags = (uint32_t) flags;
168     bt = btype;
169
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;
180     }
181
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;
186     }
187
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;
193     }
194
195     if (!(db->path = avahi_strdup(path))) {
196
197         /* FIXME: We don't remove the object on the server side */
198
199         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
200         goto fail;
201     }
202
203     if (db->static_browse_domains) {
204         struct timeval tv = { 0, 0 };
205
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;
209         }
210     }
211     
212     dbus_message_unref(message);
213     dbus_message_unref(reply);
214     
215     return db;
216
217 fail:
218
219     if (dbus_error_is_set(&error)) {
220         avahi_client_set_dbus_error(client, &error);
221         dbus_error_free(&error);
222     }
223
224     if (db)
225         avahi_domain_browser_free(db);
226     
227     if (message)
228         dbus_message_unref(message);
229
230     if (reply)
231         dbus_message_unref(reply);
232
233     return NULL;
234 }
235
236 AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b) {
237     assert(b);
238     return b->client;
239 }
240
241 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
242     AvahiClient *client;
243     int r = AVAHI_OK;
244     
245     assert(b);
246     assert(b->ref >= 1);
247
248     if (--(b->ref) >= 1)
249         return AVAHI_OK;
250     
251     client = b->client;
252
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");
255
256     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
257
258     if (b->defer_timeout)
259         b->client->poll_api->timeout_free(b->defer_timeout);
260     
261     avahi_string_list_free(b->static_browse_domains);
262     avahi_free(b->path);
263     avahi_free(b);
264
265     return r;
266 }
267
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;
276
277     assert(client);
278     assert(message);
279     
280     dbus_error_init (&error);
281
282     if (!(path = dbus_message_get_path(message)))
283         goto fail;
284
285     for (db = client->domain_browsers; db; db = db->domain_browsers_next)
286         if (strcmp (db->path, path) == 0)
287             break;
288
289     if (!db)
290         goto fail;
291
292     interface = db->interface;
293     protocol = db->protocol;
294
295     switch (event) {
296         case AVAHI_BROWSER_NEW:
297         case AVAHI_BROWSER_REMOVE:
298             
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;
309             }
310
311             break;
312             
313         case AVAHI_BROWSER_CACHE_EXHAUSTED:
314         case AVAHI_BROWSER_ALL_FOR_NOW:
315             break;
316
317         case AVAHI_BROWSER_FAILURE: {
318             char *etxt;
319             
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;
327             }
328             
329             avahi_client_set_errno(db->client, avahi_error_dbus_to_number(etxt));
330             break;
331         }
332     }
333
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;
339             }
340     
341     db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, (AvahiLookupResultFlags) flags, db->userdata);
342
343     return DBUS_HANDLER_RESULT_HANDLED;
344
345 fail:
346     dbus_error_free (&error);
347     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
348 }
349
350 /* AvahiServiceTypeBrowser */
351 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
352     AvahiClient *client,
353     AvahiIfIndex interface,
354     AvahiProtocol protocol,
355     const char *domain,
356     AvahiLookupFlags flags, 
357     AvahiServiceTypeBrowserCallback callback,
358     void *userdata) {
359         
360     AvahiServiceTypeBrowser *b = NULL;
361     DBusMessage *message = NULL, *reply = NULL;
362     DBusError error;
363     char *path;
364     int32_t i_interface, i_protocol;
365     uint32_t u_flags;
366
367     assert(client);
368     assert(callback);
369
370     dbus_error_init(&error);
371
372     if (!avahi_client_is_connected(client)) {
373         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
374         goto fail;
375     }
376
377     if (!domain)
378         domain = "";
379
380     if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
381         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
382         goto fail;
383     }
384
385     b->client = client;
386     b->callback = callback;
387     b->userdata = userdata;
388     b->path = NULL;
389     b->domain = NULL;
390     b->interface = interface;
391     b->protocol = protocol;
392
393     AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
394
395     if (domain[0])
396         if (!(b->domain = avahi_strdup(domain))) {
397             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
398             goto fail;
399         }
400           
401     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew"))) {
402         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
403         goto fail;
404     }
405     
406     i_interface = (int32_t) interface;
407     i_protocol = (int32_t) protocol;
408     u_flags = (uint32_t) flags;
409
410     if (!dbus_message_append_args(
411             message,
412             DBUS_TYPE_INT32, &i_interface,
413             DBUS_TYPE_INT32, &i_protocol,
414             DBUS_TYPE_STRING, &domain,
415             DBUS_TYPE_UINT32, &u_flags,
416             DBUS_TYPE_INVALID)) {
417         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
418         goto fail;
419     }
420
421     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
422         dbus_error_is_set(&error)) {
423         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
424         goto fail;
425     }
426
427     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
428         dbus_error_is_set(&error) ||
429         !path) {
430         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
431         goto fail;
432     }
433
434     if (!(b->path = avahi_strdup(path))) {
435
436         /* FIXME: We don't remove the object on the server side */
437
438         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
439         goto fail;
440     }
441
442     dbus_message_unref(message);
443     dbus_message_unref(reply);
444
445     return b;
446
447 fail:
448     
449     if (dbus_error_is_set(&error)) {
450         avahi_client_set_dbus_error(client, &error);
451         dbus_error_free(&error);
452     }
453
454     if (b)
455         avahi_service_type_browser_free(b);
456     
457     if (message)
458         dbus_message_unref(message);
459
460     if (reply)
461         dbus_message_unref(reply);
462
463     return NULL;
464 }
465
466 AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *b) {
467     assert(b);
468     return b->client;
469 }
470
471 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
472     AvahiClient *client;
473     int r = AVAHI_OK;
474
475     assert(b);
476     client = b->client;
477
478     if (b->path && avahi_client_is_connected(b->client))
479         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
480
481     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
482
483     avahi_free(b->path);
484     avahi_free(b->domain);
485     avahi_free(b);
486     return r;
487 }
488
489 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
490     AvahiServiceTypeBrowser *b = NULL;
491     DBusError error;
492     const char *path;
493     char *domain, *type = NULL;
494     int32_t interface, protocol;
495     uint32_t flags = 0;
496
497     assert(client);
498     assert(message);
499     
500     dbus_error_init (&error);
501
502     if (!(path = dbus_message_get_path(message)))
503         goto fail;
504
505     for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
506         if (strcmp (b->path, path) == 0)
507             break;
508
509     if (!b)
510         goto fail;
511
512     domain = b->domain;
513     interface = b->interface;
514     protocol = b->protocol;
515     
516     switch (event) {
517         case AVAHI_BROWSER_NEW:
518         case AVAHI_BROWSER_REMOVE:
519             if (!dbus_message_get_args(
520                     message, &error,
521                     DBUS_TYPE_INT32, &interface,
522                     DBUS_TYPE_INT32, &protocol,
523                     DBUS_TYPE_STRING, &type,
524                     DBUS_TYPE_STRING, &domain,
525                     DBUS_TYPE_UINT32, &flags,
526                     DBUS_TYPE_INVALID) ||
527                 dbus_error_is_set(&error)) {
528                 fprintf(stderr, "Failed to parse browser event.\n");
529                 goto fail;
530             }
531             break;
532             
533         case AVAHI_BROWSER_CACHE_EXHAUSTED:
534         case AVAHI_BROWSER_ALL_FOR_NOW:
535             break;
536
537         case AVAHI_BROWSER_FAILURE: {
538             char *etxt;
539             
540             if (!dbus_message_get_args(
541                     message, &error,
542                     DBUS_TYPE_STRING, &etxt,
543                     DBUS_TYPE_INVALID) ||
544                 dbus_error_is_set (&error)) {
545                 fprintf(stderr, "Failed to parse browser event.\n");
546                 goto fail;
547             }
548             
549             avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
550             break;
551         }
552     }
553
554     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
555
556     return DBUS_HANDLER_RESULT_HANDLED;
557
558 fail:
559     dbus_error_free (&error);
560     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
561 }
562
563 /* AvahiServiceBrowser */
564
565 AvahiServiceBrowser* avahi_service_browser_new(
566     AvahiClient *client,
567     AvahiIfIndex interface,
568     AvahiProtocol protocol,
569     const char *type,
570     const char *domain,
571     AvahiLookupFlags flags, 
572     AvahiServiceBrowserCallback callback,
573     void *userdata) {
574     
575     AvahiServiceBrowser *b = NULL;
576     DBusMessage *message = NULL, *reply = NULL;
577     DBusError error;
578     char *path;
579     int32_t i_protocol, i_interface;
580     uint32_t u_flags;
581
582     assert(client);
583     assert(type);
584     assert(callback);
585
586     dbus_error_init(&error);
587
588     if (!avahi_client_is_connected(client)) {
589         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
590         goto fail;
591     }
592
593     if (!domain)
594         domain = "";
595
596     if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
597         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
598         goto fail;
599     }
600     
601     b->client = client;
602     b->callback = callback;
603     b->userdata = userdata;
604     b->path = NULL;
605     b->type = b->domain = NULL;
606     b->interface = interface;
607     b->protocol = protocol;
608
609     AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
610
611     if (!(b->type = avahi_strdup(type))) {
612         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
613         goto fail;
614     }
615     
616     if (domain && domain[0])
617         if (!(b->domain = avahi_strdup(domain))) {
618             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
619             goto fail;
620         }
621     
622     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew"))) {
623         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
624         goto fail;
625     }
626
627     i_interface = (int32_t) interface;
628     i_protocol = (int32_t) protocol;
629     u_flags = (uint32_t) flags;
630
631     if (!dbus_message_append_args(
632             message,
633             DBUS_TYPE_INT32, &i_interface,
634             DBUS_TYPE_INT32, &i_protocol,
635             DBUS_TYPE_STRING, &type,
636             DBUS_TYPE_STRING, &domain,
637             DBUS_TYPE_UINT32, &u_flags,
638             DBUS_TYPE_INVALID)) {
639         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
640         goto fail;
641     }
642
643     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
644         dbus_error_is_set(&error)) {
645         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
646         goto fail;
647     }
648
649     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
650         dbus_error_is_set(&error) ||
651         !path) {
652         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
653         goto fail;
654     }
655
656     if (!(b->path = avahi_strdup(path))) {
657
658         /* FIXME: We don't remove the object on the server side */
659
660         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
661         goto fail;
662     }
663
664     dbus_message_unref(message);
665     dbus_message_unref(reply);
666     
667     return b;
668
669 fail:
670     if (dbus_error_is_set(&error)) {
671         avahi_client_set_dbus_error(client, &error);
672         dbus_error_free(&error);
673     }
674
675     if (b)
676         avahi_service_browser_free(b);
677     
678     if (message)
679         dbus_message_unref(message);
680
681     if (reply)
682         dbus_message_unref(reply);
683
684     return NULL;
685 }
686
687 AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *b) {
688     assert(b);
689     return b->client;
690 }
691
692 int avahi_service_browser_free (AvahiServiceBrowser *b) {
693     AvahiClient *client;
694     int r = AVAHI_OK;
695
696     assert(b);
697     client = b->client;
698
699     if (b->path && avahi_client_is_connected(b->client))
700         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
701
702     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
703
704     avahi_free(b->path);
705     avahi_free(b->type);
706     avahi_free(b->domain);
707     avahi_free(b);
708     return r;
709 }
710
711 DBusHandlerResult avahi_service_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
712     AvahiServiceBrowser *b = NULL;
713     DBusError error;
714     const char *path;
715     char *name = NULL, *type, *domain;
716     int32_t interface, protocol;
717     uint32_t flags = 0;
718
719     dbus_error_init (&error);
720
721     if (!(path = dbus_message_get_path(message)))
722         goto fail;
723
724     for (b = client->service_browsers; b; b = b->service_browsers_next)
725         if (strcmp (b->path, path) == 0)
726             break;
727
728     if (!b)
729         goto fail;
730
731     type = b->type;
732     domain = b->domain;
733     interface = b->interface;
734     protocol = b->protocol;
735
736     switch (event) {
737         case AVAHI_BROWSER_NEW:
738         case AVAHI_BROWSER_REMOVE:
739             
740             if (!dbus_message_get_args (
741                     message, &error,
742                     DBUS_TYPE_INT32, &interface,
743                     DBUS_TYPE_INT32, &protocol,
744                     DBUS_TYPE_STRING, &name,
745                     DBUS_TYPE_STRING, &type,
746                     DBUS_TYPE_STRING, &domain,
747                     DBUS_TYPE_UINT32, &flags,
748                     DBUS_TYPE_INVALID) ||
749                 dbus_error_is_set(&error)) {
750                 fprintf(stderr, "Failed to parse browser event.\n");
751                 goto fail;
752             }
753             break;
754
755         case AVAHI_BROWSER_CACHE_EXHAUSTED:
756         case AVAHI_BROWSER_ALL_FOR_NOW:
757             break;
758
759         case AVAHI_BROWSER_FAILURE: {
760             char *etxt;
761             
762             if (!dbus_message_get_args(
763                     message, &error,
764                     DBUS_TYPE_STRING, &etxt,
765                     DBUS_TYPE_INVALID) ||
766                 dbus_error_is_set (&error)) {
767                 fprintf(stderr, "Failed to parse browser event.\n");
768                 goto fail;
769             }
770             
771             avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
772             break;
773         }
774     }
775
776     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
777
778     return DBUS_HANDLER_RESULT_HANDLED;
779
780 fail:
781     dbus_error_free (&error);
782     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
783 }
784
785