X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-client%2Fresolver.c;h=ddea755dc7409bbf91365a075105b3ace9793d1f;hb=5af9f469d85a9281bc5484e9f5a8740751591dfe;hp=2e443512aa277706aabffdd2ded7bc42cf85e61a;hpb=45bf63f4c05690420fd2d701a6399550160aba02;p=catta diff --git a/avahi-client/resolver.c b/avahi-client/resolver.c index 2e44351..ddea755 100644 --- a/avahi-client/resolver.c +++ b/avahi-client/resolver.c @@ -38,24 +38,33 @@ #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; + const char *path; + AvahiStringList *strlst = NULL; + + assert(client); + assert(message); - assert(pending); - assert(r); + dbus_error_init (&error); + + if (!(path = dbus_message_get_path(message))) + goto fail; - dbus_error_init(&error); + for (r = client->service_resolvers; r; r = r->service_resolvers_next) + if (strcmp (r->path, path) == 0) + break; - if (!(message = dbus_pending_call_steal_reply(pending))) + if (!r) goto fail; - if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) { + if (event == AVAHI_RESOLVER_FOUND) { int j; - int32_t interface, protocol, aprotocol; + int32_t interface; + AvahiProtocol protocol, aprotocol; char *name, *type, *domain, *host, *address; uint16_t port; DBusMessageIter iter, sub; @@ -126,83 +135,25 @@ service_pending_call_callback(DBusPendingCall *pending, void *userdata) { } r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, type, domain, host, &a, port, strlst, r->userdata); + + avahi_string_list_free(strlst); } else { - - assert(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR); - - avahi_client_set_errno(r->client, avahi_error_dbus_to_number(dbus_message_get_error_name(message))); - + assert(event == AVAHI_RESOLVER_TIMEOUT); + r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, NULL, NULL, NULL, NULL, NULL, 0, NULL, r->userdata); } -fail: - - if (message) - dbus_message_unref(message); - - avahi_string_list_free(strlst); - - dbus_error_free (&error); -} + return DBUS_HANDLER_RESULT_HANDLED; -static void -hostname_pending_call_callback(DBusPendingCall *pending, void *userdata) { - AvahiHostNameResolver *r = userdata; - DBusMessage *message = NULL; - DBusError error; - assert(pending); - assert(r); - - dbus_error_init(&error); - - if (!(message = dbus_pending_call_steal_reply(pending))) - goto fail; - - 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); - - } else { - - assert(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR); - - avahi_client_set_errno(r->client, avahi_error_dbus_to_number(dbus_message_get_error_name(message))); - - r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, NULL, NULL, r->userdata); - } - 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( AvahiClient *client, AvahiIfIndex interface, @@ -216,8 +167,9 @@ AvahiServiceResolver * avahi_service_resolver_new( DBusError error; AvahiServiceResolver *r; - DBusMessage *message; + DBusMessage *message = NULL, *reply = NULL; int32_t i_interface, i_protocol, i_aprotocol; + char *path; assert(client); assert(name); @@ -241,11 +193,11 @@ AvahiServiceResolver * avahi_service_resolver_new( r->client = client; r->callback = callback; r->userdata = userdata; - r->call = NULL; + r->path = NULL; 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 (!(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; } @@ -267,13 +219,30 @@ AvahiServiceResolver * avahi_service_resolver_new( 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; @@ -290,13 +259,14 @@ fail: 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,34 +274,86 @@ 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 && client->state != AVAHI_CLIENT_DISCONNECTED) + 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); - 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; + + assert(client); + assert(message); + + 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; + + if (event == AVAHI_RESOLVER_FOUND) { + int32_t interface; + AvahiProtocol 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 (r->call) - dbus_pending_call_block(r->call); + } else { + + assert(event == AVAHI_RESOLVER_TIMEOUT); + + r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, NULL, NULL, r->userdata); + } - return AVAHI_OK; + 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, @@ -343,8 +365,9 @@ AvahiHostNameResolver * avahi_host_name_resolver_new( DBusError error; AvahiHostNameResolver *r; - DBusMessage *message; + DBusMessage *message = NULL, *reply = NULL; int32_t i_interface, i_protocol, i_aprotocol; + char *path; assert(client); assert(name); @@ -364,11 +387,11 @@ AvahiHostNameResolver * avahi_host_name_resolver_new( r->client = client; r->callback = callback; r->userdata = userdata; - r->call = NULL; + r->path = 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 (!(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; } @@ -388,13 +411,29 @@ AvahiHostNameResolver * avahi_host_name_resolver_new( 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; @@ -411,44 +450,243 @@ fail: 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 && client->state != AVAHI_CLIENT_DISCONNECTED) + 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); - 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; + + if (event == AVAHI_RESOLVER_FOUND) { + int32_t interface; + AvahiProtocol protocol, aprotocol; + 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_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, (AvahiProtocol) aprotocol, &a, name, r->userdata); + } else { + + assert(event == AVAHI_RESOLVER_TIMEOUT); + + r->callback(r, (AvahiIfIndex) 0, (AvahiProtocol) 0, AVAHI_RESOLVER_TIMEOUT, (AvahiProtocol) 0, NULL, NULL, r->userdata); + } + + return DBUS_HANDLER_RESULT_HANDLED; + +fail: + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +AvahiAddressResolver * avahi_address_resolver_new_a( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const AvahiAddress *a, + AvahiAddressResolverCallback callback, + void *userdata) { + + char addr[64]; + + assert (a); + + if (!avahi_address_snprint (addr, sizeof (addr), a)) { + avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS); + return NULL; + } + + return avahi_address_resolver_new ( + client, interface, protocol, + addr, + callback, userdata); +} + +AvahiAddressResolver * avahi_address_resolver_new( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *address, + AvahiAddressResolverCallback callback, + void *userdata) { + + DBusError error; + AvahiAddressResolver *r; + DBusMessage *message = NULL, *reply = NULL; + int32_t i_interface; + AvahiProtocol i_protocol; + char *path; + + assert(client); + + dbus_error_init (&error); + + if (client->state == AVAHI_CLIENT_DISCONNECTED) { + 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; + + 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 = interface; + i_protocol = protocol; + + if (!(dbus_message_append_args( + message, + DBUS_TYPE_INT32, &i_interface, + DBUS_TYPE_INT32, &i_protocol, + DBUS_TYPE_STRING, &address, + 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 && client->state != AVAHI_CLIENT_DISCONNECTED) + ret = avahi_client_simple_method_call(client, r->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free"); - return AVAHI_OK; + AVAHI_LLIST_REMOVE(AvahiAddressResolver, address_resolvers, client->address_resolvers, r); + + avahi_free(r->path); + avahi_free(r); + + return ret; } +