]> git.meshlink.io Git - catta/blob - avahi-client/browser.c
* Rename AVAHI_ERR_NOT_CONNECTED to AVAHI_ERR_DISCONNECTED
[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 (client->state == AVAHI_CLIENT_FAILURE) {
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     parse_environment(db);
154     parse_domain_file(db);
155
156     db->static_browse_domains = avahi_string_list_reverse(db->static_browse_domains);
157     
158     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew"))) {
159         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
160         goto fail;
161     }
162
163     i_interface = (int32_t) interface;
164     i_protocol = (int32_t) protocol;
165     u_flags = (uint32_t) flags;
166     bt = btype;
167
168     if (!(dbus_message_append_args(
169               message,
170               DBUS_TYPE_INT32, &i_interface,
171               DBUS_TYPE_INT32, &i_protocol,
172               DBUS_TYPE_STRING, &domain,
173               DBUS_TYPE_INT32, &bt,
174               DBUS_TYPE_UINT32, &flags,
175               DBUS_TYPE_INVALID))) {
176         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
177         goto fail;
178     }
179
180     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
181         dbus_error_is_set(&error)) {
182         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
183         goto fail;
184     }
185
186     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
187         dbus_error_is_set(&error) ||
188         !path) {
189         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
190         goto fail;
191     }
192
193     if (!(db->path = avahi_strdup(path))) {
194
195         /* FIXME: We don't remove the object on the server side */
196
197         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
198         goto fail;
199     }
200
201     if (db->static_browse_domains) {
202         struct timeval tv = { 0, 0 };
203
204         if (!(db->defer_timeout = client->poll_api->timeout_new(client->poll_api, &tv, defer_timeout_callback, db))) {
205             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
206             goto fail;
207         }
208     }
209     
210     dbus_message_unref(message);
211     dbus_message_unref(reply);
212     
213     return db;
214
215 fail:
216
217     if (dbus_error_is_set(&error)) {
218         avahi_client_set_dbus_error(client, &error);
219         dbus_error_free(&error);
220     }
221
222     if (db)
223         avahi_domain_browser_free(db);
224     
225     if (message)
226         dbus_message_unref(message);
227
228     if (reply)
229         dbus_message_unref(reply);
230
231     return NULL;
232 }
233
234 AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b) {
235     assert(b);
236     return b->client;
237 }
238
239 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
240     AvahiClient *client;
241     int r = AVAHI_OK;
242     
243     assert(b);
244     assert(b->ref >= 1);
245
246     if (--(b->ref) >= 1)
247         return AVAHI_OK;
248     
249     client = b->client;
250
251     if (b->path && client->state != AVAHI_CLIENT_FAILURE)
252         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
253
254     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
255
256     if (b->defer_timeout)
257         b->client->poll_api->timeout_free(b->defer_timeout);
258     
259     avahi_string_list_free(b->static_browse_domains);
260     avahi_free(b->path);
261     avahi_free(b);
262
263     return r;
264 }
265
266 DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
267     AvahiDomainBrowser *db = NULL;
268     DBusError error;
269     const char *path;
270     char *domain = NULL;
271     int32_t interface, protocol;
272     uint32_t flags = 0;
273     AvahiStringList *l;
274
275     assert(client);
276     assert(message);
277     
278     dbus_error_init (&error);
279
280     if (!(path = dbus_message_get_path(message)))
281         goto fail;
282
283     for (db = client->domain_browsers; db; db = db->domain_browsers_next)
284         if (strcmp (db->path, path) == 0)
285             break;
286
287     if (!db)
288         goto fail;
289
290     interface = db->interface;
291     protocol = db->protocol;
292
293     switch (event) {
294         case AVAHI_BROWSER_NEW:
295         case AVAHI_BROWSER_REMOVE:
296             
297             if (!dbus_message_get_args(
298                     message, &error,
299                     DBUS_TYPE_INT32, &interface,
300                     DBUS_TYPE_INT32, &protocol,
301                     DBUS_TYPE_STRING, &domain,
302                     DBUS_TYPE_UINT32, &flags,
303                     DBUS_TYPE_INVALID) ||
304                 dbus_error_is_set (&error)) {
305                 fprintf(stderr, "Failed to parse browser event.\n");
306                 goto fail;
307             }
308
309             break;
310             
311         case AVAHI_BROWSER_CACHE_EXHAUSTED:
312         case AVAHI_BROWSER_ALL_FOR_NOW:
313             break;
314
315         case AVAHI_BROWSER_FAILURE: {
316             char *etxt;
317             
318             if (!dbus_message_get_args(
319                     message, &error,
320                     DBUS_TYPE_STRING, &etxt,
321                     DBUS_TYPE_INVALID) ||
322                 dbus_error_is_set (&error)) {
323                 fprintf(stderr, "Failed to parse browser event.\n");
324                 goto fail;
325             }
326             
327             avahi_client_set_errno(db->client, avahi_error_dbus_to_number(etxt));
328             break;
329         }
330     }
331
332     if (domain)
333         for (l = db->static_browse_domains; l; l = l->next)
334             if (avahi_domain_equal((char*) l->text, domain)) {
335                 /* We had this entry already in the static entries */
336                 return DBUS_HANDLER_RESULT_HANDLED;
337             }
338     
339     db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, (AvahiLookupResultFlags) flags, db->userdata);
340
341     return DBUS_HANDLER_RESULT_HANDLED;
342
343 fail:
344     dbus_error_free (&error);
345     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
346 }
347
348 /* AvahiServiceTypeBrowser */
349 AvahiServiceTypeBrowser* avahi_service_type_browser_new(
350     AvahiClient *client,
351     AvahiIfIndex interface,
352     AvahiProtocol protocol,
353     const char *domain,
354     AvahiLookupFlags flags, 
355     AvahiServiceTypeBrowserCallback callback,
356     void *userdata) {
357         
358     AvahiServiceTypeBrowser *b = NULL;
359     DBusMessage *message = NULL, *reply = NULL;
360     DBusError error;
361     char *path;
362     int32_t i_interface, i_protocol;
363     uint32_t u_flags;
364
365     assert(client);
366     assert(callback);
367
368     dbus_error_init(&error);
369
370     if (client->state == AVAHI_CLIENT_FAILURE) {
371         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
372         goto fail;
373     }
374
375     if (!domain)
376         domain = "";
377
378     if (!(b = avahi_new(AvahiServiceTypeBrowser, 1))) {
379         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
380         goto fail;
381     }
382
383     b->client = client;
384     b->callback = callback;
385     b->userdata = userdata;
386     b->path = NULL;
387     b->domain = NULL;
388     b->interface = interface;
389     b->protocol = protocol;
390
391     AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, service_type_browsers, client->service_type_browsers, b);
392
393     if (domain[0])
394         if (!(b->domain = avahi_strdup(domain))) {
395             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
396             goto fail;
397         }
398           
399     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew"))) {
400         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
401         goto fail;
402     }
403     
404     i_interface = (int32_t) interface;
405     i_protocol = (int32_t) protocol;
406     u_flags = (uint32_t) flags;
407
408     if (!dbus_message_append_args(
409             message,
410             DBUS_TYPE_INT32, &i_interface,
411             DBUS_TYPE_INT32, &i_protocol,
412             DBUS_TYPE_STRING, &domain,
413             DBUS_TYPE_UINT32, &u_flags,
414             DBUS_TYPE_INVALID)) {
415         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
416         goto fail;
417     }
418
419     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
420         dbus_error_is_set(&error)) {
421         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
422         goto fail;
423     }
424
425     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
426         dbus_error_is_set(&error) ||
427         !path) {
428         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
429         goto fail;
430     }
431
432     if (!(b->path = avahi_strdup(path))) {
433
434         /* FIXME: We don't remove the object on the server side */
435
436         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
437         goto fail;
438     }
439
440     dbus_message_unref(message);
441     dbus_message_unref(reply);
442
443     return b;
444
445 fail:
446     
447     if (dbus_error_is_set(&error)) {
448         avahi_client_set_dbus_error(client, &error);
449         dbus_error_free(&error);
450     }
451
452     if (b)
453         avahi_service_type_browser_free(b);
454     
455     if (message)
456         dbus_message_unref(message);
457
458     if (reply)
459         dbus_message_unref(reply);
460
461     return NULL;
462 }
463
464 AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *b) {
465     assert(b);
466     return b->client;
467 }
468
469 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
470     AvahiClient *client;
471     int r = AVAHI_OK;
472
473     assert(b);
474     client = b->client;
475
476     if (b->path && client->state != AVAHI_CLIENT_FAILURE)
477         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
478
479     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
480
481     avahi_free(b->path);
482     avahi_free(b->domain);
483     avahi_free(b);
484     return r;
485 }
486
487 DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
488     AvahiServiceTypeBrowser *b = NULL;
489     DBusError error;
490     const char *path;
491     char *domain, *type = NULL;
492     int32_t interface, protocol;
493     uint32_t flags = 0;
494
495     assert(client);
496     assert(message);
497     
498     dbus_error_init (&error);
499
500     if (!(path = dbus_message_get_path(message)))
501         goto fail;
502
503     for (b = client->service_type_browsers; b; b = b->service_type_browsers_next)
504         if (strcmp (b->path, path) == 0)
505             break;
506
507     if (!b)
508         goto fail;
509
510     domain = b->domain;
511     interface = b->interface;
512     protocol = b->protocol;
513     
514     switch (event) {
515         case AVAHI_BROWSER_NEW:
516         case AVAHI_BROWSER_REMOVE:
517             if (!dbus_message_get_args(
518                     message, &error,
519                     DBUS_TYPE_INT32, &interface,
520                     DBUS_TYPE_INT32, &protocol,
521                     DBUS_TYPE_STRING, &type,
522                     DBUS_TYPE_STRING, &domain,
523                     DBUS_TYPE_UINT32, &flags,
524                     DBUS_TYPE_INVALID) ||
525                 dbus_error_is_set(&error)) {
526                 fprintf(stderr, "Failed to parse browser event.\n");
527                 goto fail;
528             }
529             break;
530             
531         case AVAHI_BROWSER_CACHE_EXHAUSTED:
532         case AVAHI_BROWSER_ALL_FOR_NOW:
533             break;
534
535         case AVAHI_BROWSER_FAILURE: {
536             char *etxt;
537             
538             if (!dbus_message_get_args(
539                     message, &error,
540                     DBUS_TYPE_STRING, &etxt,
541                     DBUS_TYPE_INVALID) ||
542                 dbus_error_is_set (&error)) {
543                 fprintf(stderr, "Failed to parse browser event.\n");
544                 goto fail;
545             }
546             
547             avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
548             break;
549         }
550     }
551
552     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
553
554     return DBUS_HANDLER_RESULT_HANDLED;
555
556 fail:
557     dbus_error_free (&error);
558     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
559 }
560
561 /* AvahiServiceBrowser */
562
563 AvahiServiceBrowser* avahi_service_browser_new(
564     AvahiClient *client,
565     AvahiIfIndex interface,
566     AvahiProtocol protocol,
567     const char *type,
568     const char *domain,
569     AvahiLookupFlags flags, 
570     AvahiServiceBrowserCallback callback,
571     void *userdata) {
572     
573     AvahiServiceBrowser *b = NULL;
574     DBusMessage *message = NULL, *reply = NULL;
575     DBusError error;
576     char *path;
577     int32_t i_protocol, i_interface;
578     uint32_t u_flags;
579
580     assert(client);
581     assert(type);
582     assert(callback);
583
584     dbus_error_init(&error);
585
586     if (client->state == AVAHI_CLIENT_FAILURE) {
587         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
588         goto fail;
589     }
590
591     if (!domain)
592         domain = "";
593
594     if (!(b = avahi_new(AvahiServiceBrowser, 1))) {
595         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
596         goto fail;
597     }
598     
599     b->client = client;
600     b->callback = callback;
601     b->userdata = userdata;
602     b->path = NULL;
603     b->type = b->domain = NULL;
604     b->interface = interface;
605     b->protocol = protocol;
606
607     AVAHI_LLIST_PREPEND(AvahiServiceBrowser, service_browsers, client->service_browsers, b);
608
609     if (!(b->type = avahi_strdup(type))) {
610         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
611         goto fail;
612     }
613     
614     if (domain && domain[0])
615         if (!(b->domain = avahi_strdup(domain))) {
616             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
617             goto fail;
618         }
619     
620     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew"))) {
621         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
622         goto fail;
623     }
624
625     i_interface = (int32_t) interface;
626     i_protocol = (int32_t) protocol;
627     u_flags = (uint32_t) flags;
628
629     if (!dbus_message_append_args(
630             message,
631             DBUS_TYPE_INT32, &i_interface,
632             DBUS_TYPE_INT32, &i_protocol,
633             DBUS_TYPE_STRING, &type,
634             DBUS_TYPE_STRING, &domain,
635             DBUS_TYPE_UINT32, &u_flags,
636             DBUS_TYPE_INVALID)) {
637         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
638         goto fail;
639     }
640
641     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
642         dbus_error_is_set(&error)) {
643         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
644         goto fail;
645     }
646
647     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
648         dbus_error_is_set(&error) ||
649         !path) {
650         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
651         goto fail;
652     }
653
654     if (!(b->path = avahi_strdup(path))) {
655
656         /* FIXME: We don't remove the object on the server side */
657
658         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
659         goto fail;
660     }
661
662     dbus_message_unref(message);
663     dbus_message_unref(reply);
664     
665     return b;
666
667 fail:
668     if (dbus_error_is_set(&error)) {
669         avahi_client_set_dbus_error(client, &error);
670         dbus_error_free(&error);
671     }
672
673     if (b)
674         avahi_service_browser_free(b);
675     
676     if (message)
677         dbus_message_unref(message);
678
679     if (reply)
680         dbus_message_unref(reply);
681
682     return NULL;
683 }
684
685 AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *b) {
686     assert(b);
687     return b->client;
688 }
689
690 int avahi_service_browser_free (AvahiServiceBrowser *b) {
691     AvahiClient *client;
692     int r = AVAHI_OK;
693
694     assert(b);
695     client = b->client;
696
697     if (b->path && client->state != AVAHI_CLIENT_FAILURE)
698         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
699
700     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
701
702     avahi_free(b->path);
703     avahi_free(b->type);
704     avahi_free(b->domain);
705     avahi_free(b);
706     return r;
707 }
708
709 DBusHandlerResult avahi_service_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
710     AvahiServiceBrowser *b = NULL;
711     DBusError error;
712     const char *path;
713     char *name = NULL, *type, *domain;
714     int32_t interface, protocol;
715     uint32_t flags = 0;
716
717     dbus_error_init (&error);
718
719     if (!(path = dbus_message_get_path(message)))
720         goto fail;
721
722     for (b = client->service_browsers; b; b = b->service_browsers_next)
723         if (strcmp (b->path, path) == 0)
724             break;
725
726     if (!b)
727         goto fail;
728
729     type = b->type;
730     domain = b->domain;
731     interface = b->interface;
732     protocol = b->protocol;
733
734     switch (event) {
735         case AVAHI_BROWSER_NEW:
736         case AVAHI_BROWSER_REMOVE:
737             
738             if (!dbus_message_get_args (
739                     message, &error,
740                     DBUS_TYPE_INT32, &interface,
741                     DBUS_TYPE_INT32, &protocol,
742                     DBUS_TYPE_STRING, &name,
743                     DBUS_TYPE_STRING, &type,
744                     DBUS_TYPE_STRING, &domain,
745                     DBUS_TYPE_UINT32, &flags,
746                     DBUS_TYPE_INVALID) ||
747                 dbus_error_is_set(&error)) {
748                 fprintf(stderr, "Failed to parse browser event.\n");
749                 goto fail;
750             }
751             break;
752
753         case AVAHI_BROWSER_CACHE_EXHAUSTED:
754         case AVAHI_BROWSER_ALL_FOR_NOW:
755             break;
756
757         case AVAHI_BROWSER_FAILURE: {
758             char *etxt;
759             
760             if (!dbus_message_get_args(
761                     message, &error,
762                     DBUS_TYPE_STRING, &etxt,
763                     DBUS_TYPE_INVALID) ||
764                 dbus_error_is_set (&error)) {
765                 fprintf(stderr, "Failed to parse browser event.\n");
766                 goto fail;
767             }
768             
769             avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
770             break;
771         }
772     }
773
774     b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, type, domain, (AvahiLookupResultFlags) flags, b->userdata);
775
776     return DBUS_HANDLER_RESULT_HANDLED;
777
778 fail:
779     dbus_error_free (&error);
780     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
781 }
782
783