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