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