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/avahi-malloc.h"
35
36#include "client.h"
37#include "internal.h"
38
39/* AvahiServiceResolver implementation */
40
41DBusHandlerResult 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
173fail:
174    dbus_error_free (&error);
175    avahi_string_list_free(strlst);
176    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
177}
178
179AvahiServiceResolver * 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
298fail:
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
318AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *r) {
319    assert (r);
320
321    return r->client;
322}
323
324int 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
347DBusHandlerResult 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
418fail:
419    dbus_error_free (&error);
420    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
421}
422
423
424AvahiHostNameResolver * 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
519fail:
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
539int 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
558AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *r) {
559    assert (r);
560
561    return r->client;
562}
563
564/* AvahiAddressResolver implementation */
565
566DBusHandlerResult 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
637fail:
638    dbus_error_free (&error);
639    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
640}
641
642AvahiAddressResolver * 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
735fail:
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
755AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *r) {
756    assert (r);
757
758    return r->client;
759}
760
761int 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
779