Home | History | Annotate | Download | only in avahi-client
      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 
     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 
    779