• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
avahi_service_resolver_event(AvahiClient * client,AvahiResolverEvent event,DBusMessage * message)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 
avahi_service_resolver_new(AvahiClient * client,AvahiIfIndex interface,AvahiProtocol protocol,const char * name,const char * type,const char * domain,AvahiProtocol aprotocol,AvahiLookupFlags flags,AvahiServiceResolverCallback callback,void * userdata)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 
avahi_service_resolver_get_client(AvahiServiceResolver * r)318 AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *r) {
319     assert (r);
320 
321     return r->client;
322 }
323 
avahi_service_resolver_free(AvahiServiceResolver * r)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 
avahi_host_name_resolver_event(AvahiClient * client,AvahiResolverEvent event,DBusMessage * message)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 
avahi_host_name_resolver_new(AvahiClient * client,AvahiIfIndex interface,AvahiProtocol protocol,const char * name,AvahiProtocol aprotocol,AvahiLookupFlags flags,AvahiHostNameResolverCallback callback,void * userdata)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 
avahi_host_name_resolver_free(AvahiHostNameResolver * r)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 
avahi_host_name_resolver_get_client(AvahiHostNameResolver * r)558 AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *r) {
559     assert (r);
560 
561     return r->client;
562 }
563 
564 /* AvahiAddressResolver implementation */
565 
avahi_address_resolver_event(AvahiClient * client,AvahiResolverEvent event,DBusMessage * message)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 
avahi_address_resolver_new(AvahiClient * client,AvahiIfIndex interface,AvahiProtocol protocol,const AvahiAddress * a,AvahiLookupFlags flags,AvahiAddressResolverCallback callback,void * userdata)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 
avahi_address_resolver_get_client(AvahiAddressResolver * r)755 AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *r) {
756     assert (r);
757 
758     return r->client;
759 }
760 
avahi_address_resolver_free(AvahiAddressResolver * r)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 
779