]> git.meshlink.io Git - catta/blob - avahi-client/resolver.c
d06c43c7ba3cd808a0a4addcfda19974a3f455f8
[catta] / avahi-client / resolver.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <dbus/dbus.h>
31
32 #include <avahi-client/client.h>
33 #include <avahi-common/dbus.h>
34 #include <avahi-common/llist.h>
35 #include <avahi-common/error.h>
36 #include <avahi-common/malloc.h>
37
38 #include "client.h"
39 #include "internal.h"
40
41 /* AvahiServiceResolver implementation */
42
43 DBusHandlerResult avahi_service_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) {
44     AvahiServiceResolver *r = NULL;
45     DBusError error;
46     const char *path;
47     AvahiStringList *strlst = NULL;
48
49     assert(client);
50     assert(message);
51     
52     dbus_error_init (&error);
53
54     if (!(path = dbus_message_get_path(message)))
55         goto fail;
56
57     for (r = client->service_resolvers; r; r = r->service_resolvers_next)
58         if (strcmp (r->path, path) == 0)
59             break;
60
61     if (!r)
62         goto fail;
63
64     switch (event) {
65         case AVAHI_RESOLVER_FOUND: {
66             int j;
67             int32_t interface, protocol, aprotocol;
68             uint32_t flags;
69             char *name, *type, *domain, *host, *address;
70             uint16_t port;
71             DBusMessageIter iter, sub;
72             AvahiAddress a;
73             
74             if (!dbus_message_get_args(
75                     message, &error,
76                     DBUS_TYPE_INT32, &interface,
77                     DBUS_TYPE_INT32, &protocol,
78                     DBUS_TYPE_STRING, &name,
79                     DBUS_TYPE_STRING, &type,
80                     DBUS_TYPE_STRING, &domain,
81                     DBUS_TYPE_STRING, &host,
82                     DBUS_TYPE_INT32, &aprotocol,
83                     DBUS_TYPE_STRING, &address,
84                     DBUS_TYPE_UINT16, &port,
85                     DBUS_TYPE_INVALID) ||
86                 dbus_error_is_set (&error)) {
87             
88                 fprintf(stderr, "Failed to parse resolver event.\n");
89                 goto fail;
90             }
91         
92             dbus_message_iter_init(message, &iter);
93         
94             for (j = 0; j < 9; j++)
95                 dbus_message_iter_next(&iter);
96         
97             if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
98                 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
99                 fprintf(stderr, "Error parsing service resolving message\n");
100                 goto fail;
101             }
102         
103             strlst = NULL;
104             dbus_message_iter_recurse(&iter, &sub);
105         
106             for (;;) {
107                 DBusMessageIter sub2;
108                 int at;
109             
110                 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
111                     break;
112             
113                 assert(at == DBUS_TYPE_ARRAY);
114             
115                 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
116                     fprintf(stderr, "Error parsing service resolving message\n");
117                     goto fail;
118                 }
119             
120                 dbus_message_iter_recurse(&sub, &sub2);
121
122                 if (dbus_message_iter_get_array_len(&sub2) > 0) {
123                     uint8_t *k;
124                     int n;
125                 
126                     dbus_message_iter_get_fixed_array(&sub2, &k, &n);
127                     strlst = avahi_string_list_add_arbitrary(strlst, k, n);
128                 }
129             
130                 dbus_message_iter_next(&sub);
131             }
132
133             dbus_message_iter_next(&iter);
134
135             if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
136                 fprintf(stderr, "Failed to parse resolver event.\n");
137                 goto fail;
138             }
139
140             dbus_message_iter_get_basic(&iter, &flags);
141                                     
142             assert(address);
143
144             if (address[0] == 0)
145                 address = NULL;
146             else
147                 avahi_address_parse(address, (AvahiProtocol) aprotocol, &a);
148     
149             r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, type, domain, host, address ? &a : NULL, port, strlst, (AvahiLookupResultFlags) flags, r->userdata);
150         
151             avahi_string_list_free(strlst);
152             break;
153         }
154             
155         case AVAHI_RESOLVER_FAILURE: {
156             char *etxt;
157             
158             if (!dbus_message_get_args(
159                     message, &error,
160                     DBUS_TYPE_STRING, &etxt,
161                     DBUS_TYPE_INVALID) ||
162                 dbus_error_is_set (&error)) {
163                 fprintf(stderr, "Failed to parse resolver event.\n");
164                 goto fail;
165             }
166             
167             avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt));
168             r->callback(r, r->interface, r->protocol, event, r->name, r->type, r->domain, NULL, NULL, 0, NULL, 0, r->userdata);
169             break;
170         }
171     }
172
173     return DBUS_HANDLER_RESULT_HANDLED;
174
175     
176 fail:
177     dbus_error_free (&error);
178     avahi_string_list_free(strlst);
179     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
180 }
181
182 AvahiServiceResolver * avahi_service_resolver_new(
183     AvahiClient *client,
184     AvahiIfIndex interface,
185     AvahiProtocol protocol,
186     const char *name,
187     const char *type,
188     const char *domain,
189     AvahiProtocol aprotocol,
190     AvahiLookupFlags flags,
191     AvahiServiceResolverCallback callback,
192     void *userdata) {
193
194     DBusError error;
195     AvahiServiceResolver *r = NULL;
196     DBusMessage *message = NULL, *reply = NULL;
197     int32_t i_interface, i_protocol, i_aprotocol;
198     uint32_t u_flags;
199     char *path;
200     
201     assert(client);
202     assert(type);
203
204     if (!domain)
205         domain = "";
206
207     if (!name)
208         name = "";
209     
210     dbus_error_init (&error);
211
212     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
213         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
214         goto fail;
215     }
216
217     if (!(r = avahi_new(AvahiServiceResolver, 1))) {
218         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
219         goto fail;
220     }
221
222     r->client = client;
223     r->callback = callback;
224     r->userdata = userdata;
225     r->path = NULL;
226     r->name = r->type = r->domain = NULL;
227     r->interface = interface;
228     r->protocol = protocol;
229     
230     AVAHI_LLIST_PREPEND(AvahiServiceResolver, service_resolvers, client->service_resolvers, r);
231
232     if (name && name[0])
233         if (!(r->name = avahi_strdup(name))) {
234             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
235             goto fail;
236         }
237
238     if (!(r->type = avahi_strdup(type))) {
239         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
240         goto fail;
241     }
242
243     if (domain && domain[0])
244         if (!(r->domain = avahi_strdup(domain))) {
245             avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
246             goto fail;
247         }
248     
249     
250     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew"))) {
251         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
252         goto fail;
253     }
254
255     i_interface = (int32_t) interface;
256     i_protocol = (int32_t) protocol;
257     i_aprotocol = (int32_t) aprotocol;
258     u_flags = (uint32_t) flags;
259
260     if (!(dbus_message_append_args(
261               message,
262               DBUS_TYPE_INT32, &i_interface,
263               DBUS_TYPE_INT32, &i_protocol,
264               DBUS_TYPE_STRING, &name,
265               DBUS_TYPE_STRING, &type,
266               DBUS_TYPE_STRING, &domain,
267               DBUS_TYPE_INT32, &i_aprotocol,
268               DBUS_TYPE_UINT32, &u_flags,
269               DBUS_TYPE_INVALID))) {
270         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
271         goto fail;
272     }
273
274     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
275         dbus_error_is_set(&error)) {
276         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
277         goto fail;
278     }
279
280     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
281         dbus_error_is_set(&error) ||
282         !path) {
283         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
284         goto fail;
285     }
286
287     if (!(r->path = avahi_strdup(path))) {
288
289         /* FIXME: We don't remove the object on the server side */
290
291         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
292         goto fail;
293     }
294         
295
296     dbus_message_unref(message);
297     dbus_message_unref(reply);
298
299     return r;
300     
301 fail:
302
303     if (dbus_error_is_set(&error)) {
304         avahi_client_set_dbus_error(client, &error);
305         dbus_error_free(&error);
306     }
307
308     if (r)
309         avahi_service_resolver_free(r);
310     
311     if (message)
312         dbus_message_unref(message);
313
314     if (reply)
315         dbus_message_unref(reply);
316     
317     return NULL;
318
319 }
320
321 AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *r) {
322     assert (r);
323
324     return r->client;
325 }
326
327 int avahi_service_resolver_free(AvahiServiceResolver *r) {
328     AvahiClient *client;
329     int ret = AVAHI_OK;
330
331     assert(r);
332     client = r->client;
333
334     if (r->path && client->state != AVAHI_CLIENT_DISCONNECTED)
335         ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free");
336
337     AVAHI_LLIST_REMOVE(AvahiServiceResolver, service_resolvers, client->service_resolvers, r);
338
339     avahi_free(r->path);
340     avahi_free(r->name);
341     avahi_free(r->type);
342     avahi_free(r->domain);
343     avahi_free(r);
344
345     return ret;
346 }
347
348 /* AvahiHostNameResolver implementation */
349
350 DBusHandlerResult avahi_host_name_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) {
351     AvahiHostNameResolver *r = NULL;
352     DBusError error;
353     const char *path;
354
355     assert(client);
356     assert(message);
357     
358     dbus_error_init (&error);
359
360     if (!(path = dbus_message_get_path(message)))
361         goto fail;
362
363     for (r = client->host_name_resolvers; r; r = r->host_name_resolvers_next)
364         if (strcmp (r->path, path) == 0)
365             break;
366
367     if (!r)
368         goto fail;
369
370     switch (event) {
371         case AVAHI_RESOLVER_FOUND: {
372             int32_t interface, protocol, aprotocol;
373             uint32_t flags;
374             char *name, *address;
375             AvahiAddress a;
376             
377             if (!dbus_message_get_args(
378                     message, &error,
379                     DBUS_TYPE_INT32, &interface,
380                     DBUS_TYPE_INT32, &protocol,
381                     DBUS_TYPE_STRING, &name,
382                     DBUS_TYPE_INT32, &aprotocol,
383                     DBUS_TYPE_STRING, &address,
384                     DBUS_TYPE_UINT32, &flags,
385                     DBUS_TYPE_INVALID) ||
386                 dbus_error_is_set (&error)) {
387                 fprintf(stderr, "Failed to parse resolver event.\n");
388                 goto fail;
389             }
390             
391             assert(address);
392             if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) {
393                 fprintf(stderr, "Failed to parse address\n");
394                 goto fail;
395             }
396             
397             r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, &a, (AvahiLookupResultFlags) flags, r->userdata);
398             break;
399         }
400             
401         case AVAHI_RESOLVER_FAILURE: {
402             char *etxt;
403             
404             if (!dbus_message_get_args(
405                     message, &error,
406                     DBUS_TYPE_STRING, &etxt,
407                     DBUS_TYPE_INVALID) ||
408                 dbus_error_is_set (&error)) {
409                 fprintf(stderr, "Failed to parse resolver event.\n");
410                 goto fail;
411             }
412             
413             avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt));
414             r->callback(r, r->interface, r->protocol, event, r->host_name, NULL, 0, r->userdata);
415             break;
416         }
417     }
418
419     return DBUS_HANDLER_RESULT_HANDLED;
420     
421 fail:
422     dbus_error_free (&error);
423     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
424 }
425
426
427 AvahiHostNameResolver * avahi_host_name_resolver_new(
428     AvahiClient *client,
429     AvahiIfIndex interface,
430     AvahiProtocol protocol,
431     const char *name,
432     AvahiProtocol aprotocol,
433     AvahiLookupFlags flags,
434     AvahiHostNameResolverCallback callback,
435     void *userdata) {
436
437     DBusError error;
438     AvahiHostNameResolver *r = NULL;
439     DBusMessage *message = NULL, *reply = NULL;
440     int32_t i_interface, i_protocol, i_aprotocol;
441     uint32_t u_flags;
442     char *path;
443     
444     assert(client);
445     assert(name);
446
447     dbus_error_init (&error);
448
449     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
450         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
451         goto fail;
452     }
453
454     if (!(r = avahi_new(AvahiHostNameResolver, 1))) {
455         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
456         goto fail;
457     }
458
459     r->client = client;
460     r->callback = callback;
461     r->userdata = userdata;
462     r->path = NULL;
463     r->interface = interface;
464     r->protocol = protocol;
465     r->host_name = NULL;
466     
467     AVAHI_LLIST_PREPEND(AvahiHostNameResolver, host_name_resolvers, client->host_name_resolvers, r);
468
469     if (!(r->host_name = avahi_strdup(name))) {
470         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
471         goto fail;
472     }
473
474     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew"))) {
475         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
476         goto fail;
477     }
478
479     i_interface = (int32_t) interface;
480     i_protocol = (int32_t) protocol;
481     i_aprotocol = (int32_t) aprotocol;
482     u_flags = (uint32_t) flags;
483
484     if (!(dbus_message_append_args(
485               message,
486               DBUS_TYPE_INT32, &i_interface,
487               DBUS_TYPE_INT32, &i_protocol,
488               DBUS_TYPE_STRING, &name,
489               DBUS_TYPE_INT32, &i_aprotocol,
490               DBUS_TYPE_UINT32, &u_flags,
491               DBUS_TYPE_INVALID))) {
492         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
493         goto fail;
494     }
495
496     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
497         dbus_error_is_set(&error)) {
498         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
499         goto fail;
500     }
501
502     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
503         dbus_error_is_set(&error) ||
504         !path) {
505         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
506         goto fail;
507     }
508
509     if (!(r->path = avahi_strdup(path))) {
510
511         /* FIXME: We don't remove the object on the server side */
512
513         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
514         goto fail;
515     }
516
517     dbus_message_unref(message);
518     dbus_message_unref(reply);
519
520     return r;
521     
522 fail:
523
524     if (dbus_error_is_set(&error)) {
525         avahi_client_set_dbus_error(client, &error);
526         dbus_error_free(&error);
527     }
528
529     if (r)
530         avahi_host_name_resolver_free(r);
531     
532     if (message)
533         dbus_message_unref(message);
534
535     if (reply)
536         dbus_message_unref(reply);
537
538     return NULL;
539
540 }
541
542 int avahi_host_name_resolver_free(AvahiHostNameResolver *r) {
543     int ret = AVAHI_OK;
544     AvahiClient *client;
545
546     assert(r);
547     client = r->client;
548
549     if (r->path && client->state != AVAHI_CLIENT_DISCONNECTED)
550         ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free");
551
552     AVAHI_LLIST_REMOVE(AvahiHostNameResolver, host_name_resolvers, client->host_name_resolvers, r);
553
554     avahi_free(r->path);
555     avahi_free(r->host_name);
556     avahi_free(r);
557
558     return ret;
559 }
560
561 AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *r) {
562     assert (r);
563
564     return r->client;
565 }
566
567 /* AvahiAddressResolver implementation */
568
569 DBusHandlerResult avahi_address_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) {
570     AvahiAddressResolver *r = NULL;
571     DBusError error;
572     const char *path;
573
574     assert(client);
575     assert(message);
576     
577     dbus_error_init (&error);
578
579     if (!(path = dbus_message_get_path(message)))
580         goto fail;
581
582     for (r = client->address_resolvers; r; r = r->address_resolvers_next)
583         if (strcmp (r->path, path) == 0)
584             break;
585
586     if (!r)
587         goto fail;
588
589     switch (event) {
590         case AVAHI_RESOLVER_FOUND: {
591             int32_t interface, protocol, aprotocol;
592             uint32_t flags;
593             char *name, *address;
594             AvahiAddress a;
595             
596             if (!dbus_message_get_args(
597                     message, &error,
598                     DBUS_TYPE_INT32, &interface,
599                     DBUS_TYPE_INT32, &protocol,
600                     DBUS_TYPE_INT32, &aprotocol,
601                     DBUS_TYPE_STRING, &address,
602                     DBUS_TYPE_STRING, &name,
603                     DBUS_TYPE_UINT32, &flags,
604                     DBUS_TYPE_INVALID) ||
605                 dbus_error_is_set (&error)) {
606                 fprintf(stderr, "Failed to parse resolver event.\n");
607                 goto fail;
608             }
609             
610             assert(address);
611             if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) {
612                 fprintf(stderr, "Failed to parse address\n");
613                 goto fail;
614             }
615             
616             r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, &a, name, (AvahiLookupResultFlags) flags, r->userdata);
617             break;
618         }
619
620         case AVAHI_RESOLVER_FAILURE: {
621             char *etxt;
622             
623             if (!dbus_message_get_args(
624                     message, &error,
625                     DBUS_TYPE_STRING, &etxt,
626                     DBUS_TYPE_INVALID) ||
627                 dbus_error_is_set (&error)) {
628                 fprintf(stderr, "Failed to parse resolver event.\n");
629                 goto fail;
630             }
631             
632             avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt));
633             r->callback(r, r->interface, r->protocol, event, &r->address, NULL, 0, r->userdata);
634             break;
635         }
636     }
637
638     return DBUS_HANDLER_RESULT_HANDLED;
639     
640 fail:
641     dbus_error_free (&error);
642     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
643 }
644
645 AvahiAddressResolver * avahi_address_resolver_new(
646     AvahiClient *client,
647     AvahiIfIndex interface,
648     AvahiProtocol protocol,
649     const AvahiAddress *a,
650     AvahiLookupFlags flags, 
651     AvahiAddressResolverCallback callback,
652     void *userdata) {
653
654     DBusError error;
655     AvahiAddressResolver *r = NULL;
656     DBusMessage *message = NULL, *reply = NULL;
657     int32_t i_interface, i_protocol;
658     uint32_t u_flags;
659     char *path;
660     char addr[AVAHI_ADDRESS_STR_MAX], *address = addr;
661
662     assert(client);
663     assert(a);
664
665     dbus_error_init (&error);
666
667     if (!avahi_address_snprint (addr, sizeof(addr), a)) {
668         avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS);
669         return NULL;
670     }
671
672     if (client->state == AVAHI_CLIENT_DISCONNECTED) {
673         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
674         goto fail;
675     }
676
677     if (!(r = avahi_new(AvahiAddressResolver, 1))) {
678         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
679         goto fail;
680     }
681
682     r->client = client;
683     r->callback = callback;
684     r->userdata = userdata;
685     r->path = NULL;
686     r->interface = interface;
687     r->protocol = protocol;
688     r->address = *a;
689     
690     AVAHI_LLIST_PREPEND(AvahiAddressResolver, address_resolvers, client->address_resolvers, r);
691
692     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew"))) {
693         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
694         goto fail;
695     }
696
697     i_interface = (int32_t) interface;
698     i_protocol = (int32_t) protocol;
699     u_flags = (uint32_t) flags;
700
701     if (!(dbus_message_append_args(
702               message,
703               DBUS_TYPE_INT32, &i_interface,
704               DBUS_TYPE_INT32, &i_protocol,
705               DBUS_TYPE_STRING, &address,
706               DBUS_TYPE_UINT32, &u_flags,
707               DBUS_TYPE_INVALID))) {
708         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
709         goto fail;
710     }
711
712     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
713         dbus_error_is_set(&error)) {
714         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
715         goto fail;
716     }
717
718     if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
719         dbus_error_is_set(&error) ||
720         !path) {
721         avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
722         goto fail;
723     }
724     
725     if (!(r->path = avahi_strdup(path))) {
726
727         /* FIXME: We don't remove the object on the server side */
728
729         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
730         goto fail;
731     }
732
733     dbus_message_unref(message);
734     dbus_message_unref(reply);
735
736     return r;
737     
738 fail:
739
740     if (dbus_error_is_set(&error)) {
741         avahi_client_set_dbus_error(client, &error);
742         dbus_error_free(&error);
743     }
744
745     if (r)
746         avahi_address_resolver_free(r);
747     
748     if (message)
749         dbus_message_unref(message);
750
751     if (reply)
752         dbus_message_unref(reply);
753
754     return NULL;
755
756 }
757
758 AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *r) {
759     assert (r);
760
761     return r->client;
762 }
763
764 int avahi_address_resolver_free(AvahiAddressResolver *r) {
765     AvahiClient *client;
766     int ret = AVAHI_OK;
767
768     assert(r);
769     client = r->client;
770
771     if (r->path && client->state != AVAHI_CLIENT_DISCONNECTED)
772         ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free");
773
774     AVAHI_LLIST_REMOVE(AvahiAddressResolver, address_resolvers, client->address_resolvers, r);
775
776     avahi_free(r->path);
777     avahi_free(r);
778
779     return ret;
780 }
781