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