X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-client%2Fresolver.c;h=6ee15e93f2434516734c05a86eab11ec255c62e7;hb=7a5b2f69af7d36d6cd4153142f125fa011784e03;hp=2e443512aa277706aabffdd2ded7bc42cf85e61a;hpb=45bf63f4c05690420fd2d701a6399550160aba02;p=catta diff --git a/avahi-client/resolver.c b/avahi-client/resolver.c index 2e44351..6ee15e9 100644 --- a/avahi-client/resolver.c +++ b/avahi-client/resolver.c @@ -1,18 +1,16 @@ -/* $Id$ */ - /*** This file is part of avahi. - + avahi is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + avahi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with avahi; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -38,169 +36,144 @@ #include "client.h" #include "internal.h" -static void -service_pending_call_callback(DBusPendingCall *pending, void *userdata) { - AvahiServiceResolver *r = userdata; - DBusMessage *message = NULL; - AvahiStringList *strlst = NULL; +/* AvahiServiceResolver implementation */ + +DBusHandlerResult avahi_service_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) { + AvahiServiceResolver *r = NULL; DBusError error; - - assert(pending); - assert(r); + const char *path; + AvahiStringList *strlst = NULL; - dbus_error_init(&error); + assert(client); + assert(message); + + dbus_error_init (&error); - if (!(message = dbus_pending_call_steal_reply(pending))) + if (!(path = dbus_message_get_path(message))) goto fail; - if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) { - int j; - int32_t interface, protocol, aprotocol; - char *name, *type, *domain, *host, *address; - uint16_t port; - DBusMessageIter iter, sub; - AvahiAddress a; - - if (!dbus_message_get_args( - message, &error, - DBUS_TYPE_INT32, &interface, - DBUS_TYPE_INT32, &protocol, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_STRING, &domain, - DBUS_TYPE_STRING, &host, - DBUS_TYPE_INT32, &aprotocol, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_UINT16, &port, - DBUS_TYPE_INVALID) || - dbus_error_is_set (&error)) { - fprintf(stderr, "Failed to parse resolver event.\n"); - goto fail; - } - - dbus_message_iter_init(message, &iter); - - for (j = 0; j < 9; j++) - dbus_message_iter_next(&iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) { - fprintf(stderr, "Error parsing service resolving message"); - goto fail; - } - - strlst = NULL; - dbus_message_iter_recurse(&iter, &sub); - - for (;;) { - DBusMessageIter sub2; - int at; - - if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID) - break; - - assert(at == DBUS_TYPE_ARRAY); - - if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) { - fprintf(stderr, "Error parsing service resolving message"); + for (r = client->service_resolvers; r; r = r->service_resolvers_next) + if (strcmp (r->path, path) == 0) + break; + + if (!r) + goto fail; + + switch (event) { + case AVAHI_RESOLVER_FOUND: { + int j; + int32_t interface, protocol, aprotocol; + uint32_t flags; + char *name, *type, *domain, *host, *address; + uint16_t port; + DBusMessageIter iter, sub; + AvahiAddress a; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_INT32, &interface, + DBUS_TYPE_INT32, &protocol, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &type, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_STRING, &host, + DBUS_TYPE_INT32, &aprotocol, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT16, &port, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + + fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } - - dbus_message_iter_recurse(&sub, &sub2); - if (dbus_message_iter_get_array_len(&sub2) > 0) { - uint8_t *k; - int n; - - dbus_message_iter_get_fixed_array(&sub2, &k, &n); - strlst = avahi_string_list_add_arbitrary(strlst, k, n); + dbus_message_iter_init(message, &iter); + + for (j = 0; j < 9; j++) + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) { + fprintf(stderr, "Error parsing service resolving message\n"); + goto fail; } - - dbus_message_iter_next(&sub); - } - assert(address); - if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) { - fprintf(stderr, "Failed to parse address\n"); - goto fail; - } - - r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, type, domain, host, &a, port, strlst, r->userdata); + strlst = NULL; + dbus_message_iter_recurse(&iter, &sub); - } else { + for (;;) { + DBusMessageIter sub2; + int at; + const uint8_t *k; + int n; - assert(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR); + if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID) + break; - avahi_client_set_errno(r->client, avahi_error_dbus_to_number(dbus_message_get_error_name(message))); + assert(at == DBUS_TYPE_ARRAY); - r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, NULL, NULL, NULL, NULL, NULL, 0, NULL, r->userdata); - } + if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) { + fprintf(stderr, "Error parsing service resolving message\n"); + goto fail; + } -fail: - - if (message) - dbus_message_unref(message); - - avahi_string_list_free(strlst); - - dbus_error_free (&error); -} + dbus_message_iter_recurse(&sub, &sub2); -static void -hostname_pending_call_callback(DBusPendingCall *pending, void *userdata) { - AvahiHostNameResolver *r = userdata; - DBusMessage *message = NULL; - DBusError error; - - assert(pending); - assert(r); + k = NULL; n = 0; + dbus_message_iter_get_fixed_array(&sub2, &k, &n); + if (k && n > 0) + strlst = avahi_string_list_add_arbitrary(strlst, k, n); - dbus_error_init(&error); + dbus_message_iter_next(&sub); + } - if (!(message = dbus_pending_call_steal_reply(pending))) - goto fail; + dbus_message_iter_next(&iter); - if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) { - int32_t interface, protocol, aprotocol; - char *name, *address; - AvahiAddress a; - - if (!dbus_message_get_args( - message, &error, - DBUS_TYPE_INT32, &interface, - DBUS_TYPE_INT32, &protocol, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INT32, &aprotocol, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID) || - dbus_error_is_set (&error)) { - fprintf(stderr, "Failed to parse resolver event.\n"); - goto fail; - } - - assert(address); - if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) { - fprintf(stderr, "Failed to parse address\n"); - goto fail; - } - - r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, &a, r->userdata); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + dbus_message_iter_get_basic(&iter, &flags); - } else { + assert(address); - assert(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR); + if (address[0] == 0) + address = NULL; + else + avahi_address_parse(address, (AvahiProtocol) aprotocol, &a); - avahi_client_set_errno(r->client, avahi_error_dbus_to_number(dbus_message_get_error_name(message))); + r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, type, domain, host, address ? &a : NULL, port, strlst, (AvahiLookupResultFlags) flags, r->userdata); - r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, NULL, NULL, r->userdata); + avahi_string_list_free(strlst); + break; + } + + case AVAHI_RESOLVER_FAILURE: { + char *etxt; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_STRING, &etxt, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt)); + r->callback(r, r->interface, r->protocol, event, r->name, r->type, r->domain, NULL, NULL, 0, NULL, 0, r->userdata); + break; + } } + return DBUS_HANDLER_RESULT_HANDLED; + + fail: - - if (message) - dbus_message_unref(message); - dbus_error_free (&error); + avahi_string_list_free(strlst); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } AvahiServiceResolver * avahi_service_resolver_new( @@ -211,24 +184,29 @@ AvahiServiceResolver * avahi_service_resolver_new( const char *type, const char *domain, AvahiProtocol aprotocol, + AvahiLookupFlags flags, AvahiServiceResolverCallback callback, void *userdata) { DBusError error; - AvahiServiceResolver *r; - DBusMessage *message; + AvahiServiceResolver *r = NULL; + DBusMessage *message = NULL, *reply = NULL; int32_t i_interface, i_protocol, i_aprotocol; - + uint32_t u_flags; + char *path; + assert(client); - assert(name); assert(type); if (!domain) domain = ""; - + + if (!name) + name = ""; + dbus_error_init (&error); - if (client->state == AVAHI_CLIENT_DISCONNECTED) { + if (!avahi_client_is_connected(client)) { avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE); goto fail; } @@ -241,18 +219,40 @@ AvahiServiceResolver * avahi_service_resolver_new( r->client = client; r->callback = callback; r->userdata = userdata; - r->call = NULL; - + r->path = NULL; + r->name = r->type = r->domain = NULL; + r->interface = interface; + r->protocol = protocol; + AVAHI_LLIST_PREPEND(AvahiServiceResolver, service_resolvers, client->service_resolvers, r); - if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService"))) { + if (name && name[0]) + if (!(r->name = avahi_strdup(name))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (!(r->type = avahi_strdup(type))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (domain && domain[0]) + if (!(r->domain = avahi_strdup(domain))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + + if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew"))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } - i_interface = interface; - i_protocol = protocol; - i_aprotocol = aprotocol; + i_interface = (int32_t) interface; + i_protocol = (int32_t) protocol; + i_aprotocol = (int32_t) aprotocol; + u_flags = (uint32_t) flags; if (!(dbus_message_append_args( message, @@ -262,21 +262,39 @@ AvahiServiceResolver * avahi_service_resolver_new( DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_INT32, &i_aprotocol, + DBUS_TYPE_UINT32, &u_flags, DBUS_TYPE_INVALID))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } - if (!dbus_connection_send_with_reply(client->bus, message, &r->call, -1) || - !dbus_pending_call_set_notify(r->call, service_pending_call_callback, r, NULL)) { + if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || + dbus_error_is_set(&error)) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) || + dbus_error_is_set(&error) || + !path) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!(r->path = avahi_strdup(path))) { + + /* FIXME: We don't remove the object on the server side */ + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } + dbus_message_unref(message); + dbus_message_unref(reply); return r; - + fail: if (dbus_error_is_set(&error)) { @@ -286,17 +304,18 @@ fail: if (r) avahi_service_resolver_free(r); - + if (message) dbus_message_unref(message); + if (reply) + dbus_message_unref(reply); + return NULL; } AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *r) { - AvahiClient *client; - assert (r); return r->client; @@ -304,54 +323,127 @@ AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *r) { int avahi_service_resolver_free(AvahiServiceResolver *r) { AvahiClient *client; + int ret = AVAHI_OK; assert(r); client = r->client; - if (r->call) { - dbus_pending_call_cancel(r->call); - dbus_pending_call_unref(r->call); - } + if (r->path && avahi_client_is_connected(client)) + ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free"); AVAHI_LLIST_REMOVE(AvahiServiceResolver, service_resolvers, client->service_resolvers, r); + avahi_free(r->path); + avahi_free(r->name); + avahi_free(r->type); + avahi_free(r->domain); avahi_free(r); - return AVAHI_OK; + return ret; } -int avahi_service_resolver_block(AvahiServiceResolver *r) { - AvahiClient *client; +/* AvahiHostNameResolver implementation */ - assert(r); - client = r->client; +DBusHandlerResult avahi_host_name_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) { + AvahiHostNameResolver *r = NULL; + DBusError error; + const char *path; - if (r->call) - dbus_pending_call_block(r->call); + assert(client); + assert(message); - return AVAHI_OK; + dbus_error_init (&error); + + if (!(path = dbus_message_get_path(message))) + goto fail; + + for (r = client->host_name_resolvers; r; r = r->host_name_resolvers_next) + if (strcmp (r->path, path) == 0) + break; + + if (!r) + goto fail; + + switch (event) { + case AVAHI_RESOLVER_FOUND: { + int32_t interface, protocol, aprotocol; + uint32_t flags; + char *name, *address; + AvahiAddress a; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_INT32, &interface, + DBUS_TYPE_INT32, &protocol, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INT32, &aprotocol, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + assert(address); + if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) { + fprintf(stderr, "Failed to parse address\n"); + goto fail; + } + + r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, &a, (AvahiLookupResultFlags) flags, r->userdata); + break; + } + + case AVAHI_RESOLVER_FAILURE: { + char *etxt; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_STRING, &etxt, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt)); + r->callback(r, r->interface, r->protocol, event, r->host_name, NULL, 0, r->userdata); + break; + } + } + + return DBUS_HANDLER_RESULT_HANDLED; + +fail: + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } + AvahiHostNameResolver * avahi_host_name_resolver_new( AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, AvahiProtocol aprotocol, + AvahiLookupFlags flags, AvahiHostNameResolverCallback callback, void *userdata) { DBusError error; - AvahiHostNameResolver *r; - DBusMessage *message; + AvahiHostNameResolver *r = NULL; + DBusMessage *message = NULL, *reply = NULL; int32_t i_interface, i_protocol, i_aprotocol; - + uint32_t u_flags; + char *path; + assert(client); assert(name); dbus_error_init (&error); - if (client->state == AVAHI_CLIENT_DISCONNECTED) { + if (!avahi_client_is_connected(client)) { avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE); goto fail; } @@ -364,18 +456,27 @@ AvahiHostNameResolver * avahi_host_name_resolver_new( r->client = client; r->callback = callback; r->userdata = userdata; - r->call = NULL; - + r->path = NULL; + r->interface = interface; + r->protocol = protocol; + r->host_name = NULL; + AVAHI_LLIST_PREPEND(AvahiHostNameResolver, host_name_resolvers, client->host_name_resolvers, r); - if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName"))) { + if (!(r->host_name = avahi_strdup(name))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew"))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } - i_interface = interface; - i_protocol = protocol; - i_aprotocol = aprotocol; + i_interface = (int32_t) interface; + i_protocol = (int32_t) protocol; + i_aprotocol = (int32_t) aprotocol; + u_flags = (uint32_t) flags; if (!(dbus_message_append_args( message, @@ -383,21 +484,38 @@ AvahiHostNameResolver * avahi_host_name_resolver_new( DBUS_TYPE_INT32, &i_protocol, DBUS_TYPE_STRING, &name, DBUS_TYPE_INT32, &i_aprotocol, + DBUS_TYPE_UINT32, &u_flags, DBUS_TYPE_INVALID))) { avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } - if (!dbus_connection_send_with_reply(client->bus, message, &r->call, -1) || - !dbus_pending_call_set_notify(r->call, hostname_pending_call_callback, r, NULL)) { + if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || + dbus_error_is_set(&error)) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) || + dbus_error_is_set(&error) || + !path) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!(r->path = avahi_strdup(path))) { + + /* FIXME: We don't remove the object on the server side */ + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); goto fail; } dbus_message_unref(message); + dbus_message_unref(reply); return r; - + fail: if (dbus_error_is_set(&error)) { @@ -407,48 +525,254 @@ fail: if (r) avahi_host_name_resolver_free(r); - + if (message) dbus_message_unref(message); + if (reply) + dbus_message_unref(reply); + return NULL; } int avahi_host_name_resolver_free(AvahiHostNameResolver *r) { + int ret = AVAHI_OK; AvahiClient *client; assert(r); client = r->client; - if (r->call) { - dbus_pending_call_cancel(r->call); - dbus_pending_call_unref(r->call); - } + if (r->path && avahi_client_is_connected(client)) + ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free"); AVAHI_LLIST_REMOVE(AvahiHostNameResolver, host_name_resolvers, client->host_name_resolvers, r); + avahi_free(r->path); + avahi_free(r->host_name); avahi_free(r); - return AVAHI_OK; + return ret; } AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *r) { - AvahiClient *client; + assert (r); + + return r->client; +} + +/* AvahiAddressResolver implementation */ + +DBusHandlerResult avahi_address_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) { + AvahiAddressResolver *r = NULL; + DBusError error; + const char *path; + + assert(client); + assert(message); + + dbus_error_init (&error); + + if (!(path = dbus_message_get_path(message))) + goto fail; + + for (r = client->address_resolvers; r; r = r->address_resolvers_next) + if (strcmp (r->path, path) == 0) + break; + + if (!r) + goto fail; + + switch (event) { + case AVAHI_RESOLVER_FOUND: { + int32_t interface, protocol, aprotocol; + uint32_t flags; + char *name, *address; + AvahiAddress a; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_INT32, &interface, + DBUS_TYPE_INT32, &protocol, + DBUS_TYPE_INT32, &aprotocol, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + assert(address); + if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) { + fprintf(stderr, "Failed to parse address\n"); + goto fail; + } + + r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, &a, name, (AvahiLookupResultFlags) flags, r->userdata); + break; + } + + case AVAHI_RESOLVER_FAILURE: { + char *etxt; + + if (!dbus_message_get_args( + message, &error, + DBUS_TYPE_STRING, &etxt, + DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + fprintf(stderr, "Failed to parse resolver event.\n"); + goto fail; + } + + avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt)); + r->callback(r, r->interface, r->protocol, event, &r->address, NULL, 0, r->userdata); + break; + } + } + + return DBUS_HANDLER_RESULT_HANDLED; + +fail: + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +AvahiAddressResolver * avahi_address_resolver_new( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const AvahiAddress *a, + AvahiLookupFlags flags, + AvahiAddressResolverCallback callback, + void *userdata) { + + DBusError error; + AvahiAddressResolver *r = NULL; + DBusMessage *message = NULL, *reply = NULL; + int32_t i_interface, i_protocol; + uint32_t u_flags; + char *path; + char addr[AVAHI_ADDRESS_STR_MAX], *address = addr; + + assert(client); + assert(a); + + dbus_error_init (&error); + + if (!avahi_address_snprint (addr, sizeof(addr), a)) { + avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS); + return NULL; + } + if (!avahi_client_is_connected(client)) { + avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE); + goto fail; + } + + if (!(r = avahi_new(AvahiAddressResolver, 1))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + r->client = client; + r->callback = callback; + r->userdata = userdata; + r->path = NULL; + r->interface = interface; + r->protocol = protocol; + r->address = *a; + + AVAHI_LLIST_PREPEND(AvahiAddressResolver, address_resolvers, client->address_resolvers, r); + + if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew"))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + i_interface = (int32_t) interface; + i_protocol = (int32_t) protocol; + u_flags = (uint32_t) flags; + + if (!(dbus_message_append_args( + message, + DBUS_TYPE_INT32, &i_interface, + DBUS_TYPE_INT32, &i_protocol, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT32, &u_flags, + DBUS_TYPE_INVALID))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || + dbus_error_is_set(&error)) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) || + dbus_error_is_set(&error) || + !path) { + avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!(r->path = avahi_strdup(path))) { + + /* FIXME: We don't remove the object on the server side */ + + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + dbus_message_unref(message); + dbus_message_unref(reply); + + return r; + +fail: + + if (dbus_error_is_set(&error)) { + avahi_client_set_dbus_error(client, &error); + dbus_error_free(&error); + } + + if (r) + avahi_address_resolver_free(r); + + if (message) + dbus_message_unref(message); + + if (reply) + dbus_message_unref(reply); + + return NULL; + +} + +AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *r) { assert (r); return r->client; } -int avahi_host_name_resolver_block(AvahiHostNameResolver *r) { +int avahi_address_resolver_free(AvahiAddressResolver *r) { AvahiClient *client; + int ret = AVAHI_OK; assert(r); client = r->client; - if (r->call) - dbus_pending_call_block(r->call); + if (r->path && avahi_client_is_connected(client)) + ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free"); + + AVAHI_LLIST_REMOVE(AvahiAddressResolver, address_resolvers, client->address_resolvers, r); - return AVAHI_OK; + avahi_free(r->path); + avahi_free(r); + + return ret; } +