X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-client%2Fclient.c;h=f665613c0598e09dc3199620a38bbab0bcdc92b3;hb=a66c19d9111dc950aac47b7becaddf1b0814f251;hp=1067456ed81104fb7f3d66f3d9aa80ee9ceb9ced;hpb=6ecd227ceadc32ed229246aa61df6361c7b58a95;p=catta diff --git a/avahi-client/client.c b/avahi-client/client.c index 1067456..f665613 100644 --- a/avahi-client/client.c +++ b/avahi-client/client.c @@ -39,6 +39,8 @@ #include "client.h" #include "internal.h" +#define AVAHI_CLIENT_DBUS_API_SUPPORTED ((uint32_t) 0x0201) + static int init_server(AvahiClient *client, int *ret_error); int avahi_client_set_errno (AvahiClient *client, int error) { @@ -65,7 +67,11 @@ static void client_set_state (AvahiClient *client, AvahiServerState state) { switch (client->state) { case AVAHI_CLIENT_FAILURE: if (client->bus) { +#ifdef HAVE_DBUS_CONNECTION_CLOSE + dbus_connection_close(client->bus); +#else dbus_connection_disconnect(client->bus); +#endif dbus_connection_unref(client->bus); client->bus = NULL; } @@ -115,7 +121,11 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message, avahi_client_set_errno(client, AVAHI_ERR_DISCONNECTED); goto fail; - } if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { + } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameAcquired")) { + + /* Ignore this message */ + + } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { char *name, *old, *new; if (!dbus_message_get_args( @@ -154,7 +164,7 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message, } else if (!avahi_client_is_connected(client)) { - /* Ignore messages, we get in unconnected state */ + /* Ignore messages we get in unconnected state */ } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged")) { int32_t state; @@ -256,6 +266,18 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message, return avahi_address_resolver_event (client, AVAHI_RESOLVER_FOUND, message); else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Failure")) return avahi_address_resolver_event (client, AVAHI_RESOLVER_FAILURE, message); + + else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "ItemNew")) + return avahi_record_browser_event (client, AVAHI_BROWSER_NEW, message); + else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "ItemRemove")) + return avahi_record_browser_event (client, AVAHI_BROWSER_REMOVE, message); + else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "CacheExhausted")) + return avahi_record_browser_event (client, AVAHI_BROWSER_CACHE_EXHAUSTED, message); + else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "AllForNow")) + return avahi_record_browser_event (client, AVAHI_BROWSER_ALL_FOR_NOW, message); + else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "Failure")) + return avahi_record_browser_event (client, AVAHI_BROWSER_FAILURE, message); + else { fprintf(stderr, "WARNING: Unhandled message: interface=%s, path=%s, member=%s\n", @@ -329,26 +351,57 @@ fail: static int check_version(AvahiClient *client, int *ret_error) { DBusMessage *message = NULL, *reply = NULL; DBusError error; - char *version; + uint32_t version; int e = AVAHI_ERR_NO_MEMORY; assert(client); dbus_error_init(&error); - if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString"))) + if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion"))) goto fail; reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error); - if (!reply || dbus_error_is_set (&error)) - goto fail; + if (!reply || dbus_error_is_set (&error)) { + char *version_str; - if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &version, DBUS_TYPE_INVALID) || - dbus_error_is_set (&error)) - goto fail; + if (!dbus_error_is_set(&error) || strcmp(error.name, DBUS_ERROR_UNKNOWN_METHOD)) + goto fail; + + /* If the method GetAPIVersion is not known, we look if + * GetVersionString matches "avahi 0.6" which is the only + * version we support which doesn't have GetAPIVersion() .*/ + + dbus_message_unref(message); + if (reply) dbus_message_unref(reply); + dbus_error_free(&error); + + if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString"))) + goto fail; + + reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error); + + if (!reply || dbus_error_is_set (&error)) + goto fail; + + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &version_str, DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) + goto fail; + + version = strcmp(version_str, "avahi 0.6") == 0 ? 0x0201 : 0x0000; + + } else { + + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_UINT32, &version, DBUS_TYPE_INVALID) || + dbus_error_is_set(&error)) + goto fail; + } - if (strcmp(version, PACKAGE_STRING) != 0) { + /*fprintf(stderr, "API Version 0x%04x\n", version);*/ + + if ((version & 0xFF00) != (AVAHI_CLIENT_DBUS_API_SUPPORTED & 0xFF00) || + (version & 0x00FF) < (AVAHI_CLIENT_DBUS_API_SUPPORTED & 0x00FF)) { e = AVAHI_ERR_VERSION_MISMATCH; goto fail; } @@ -388,11 +441,18 @@ static int init_server(AvahiClient *client, int *ret_error) { } /* This function acts like dbus_bus_get but creates a private - * connection instead */ + * connection instead. */ static DBusConnection* avahi_dbus_bus_get(DBusError *error) { DBusConnection *c; - const char *a; +#ifdef HAVE_DBUS_BUS_GET_PRIVATE + if (!(c = dbus_bus_get_private(DBUS_BUS_SYSTEM, error))) + return NULL; + + dbus_connection_set_exit_on_disconnect(c, FALSE); +#else + const char *a; + if (!(a = getenv("DBUS_SYSTEM_BUS_ADDRESS")) || !*a) a = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS; @@ -402,10 +462,15 @@ static DBusConnection* avahi_dbus_bus_get(DBusError *error) { dbus_connection_set_exit_on_disconnect(c, FALSE); if (!dbus_bus_register(c, error)) { +#ifdef HAVE_DBUS_CONNECTION_CLOSE dbus_connection_close(c); +#else + dbus_connection_disconnect(c); +#endif dbus_connection_unref(c); return NULL; } +#endif return c; } @@ -442,6 +507,7 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientFlags flags, AVAHI_LLIST_HEAD_INIT(AvahiServiceResolver, client->service_resolvers); AVAHI_LLIST_HEAD_INIT(AvahiHostNameResolver, client->host_name_resolvers); AVAHI_LLIST_HEAD_INIT(AvahiAddressResolver, client->address_resolvers); + AVAHI_LLIST_HEAD_INIT(AvahiRecordBrowser, client->record_browsers); if (!(client->bus = avahi_dbus_bus_get(&error)) || dbus_error_is_set(&error)) { if (ret_error) @@ -527,8 +593,13 @@ fail: if (dbus_error_is_set(&error)) { - if (ret_error) - *ret_error = avahi_error_dbus_to_number(error.name); + if (ret_error) { + if (strcmp(error.name, DBUS_ERROR_FILE_NOT_FOUND) == 0) + /* DBUS returns this error when the DBUS daemon is not running */ + *ret_error = AVAHI_ERR_NO_DAEMON; + else + *ret_error = avahi_error_dbus_to_number(error.name); + } dbus_error_free(&error); } @@ -539,6 +610,15 @@ fail: void avahi_client_free(AvahiClient *client) { assert(client); + if (client->bus) + /* Disconnect in advance, so that the free() functions won't + * issue needless server calls */ +#ifdef HAVE_DBUS_CONNECTION_CLOSE + dbus_connection_close(client->bus); +#else + dbus_connection_disconnect(client->bus); +#endif + while (client->groups) avahi_entry_group_free(client->groups); @@ -554,10 +634,17 @@ void avahi_client_free(AvahiClient *client) { while (client->service_resolvers) avahi_service_resolver_free(client->service_resolvers); - if (client->bus) { - dbus_connection_disconnect(client->bus); + while (client->host_name_resolvers) + avahi_host_name_resolver_free(client->host_name_resolvers); + + while (client->address_resolvers) + avahi_address_resolver_free(client->address_resolvers); + + while (client->record_browsers) + avahi_record_browser_free(client->record_browsers); + + if (client->bus) dbus_connection_unref(client->bus); - } avahi_free(client->version_string); avahi_free(client->host_name); @@ -794,5 +881,63 @@ fail: int avahi_client_is_connected(AvahiClient *client) { assert(client); - return client->state == AVAHI_CLIENT_S_RUNNING || client->state == AVAHI_CLIENT_S_REGISTERING || client->state == AVAHI_CLIENT_S_COLLISION; + return + client->bus && + dbus_connection_get_is_connected(client->bus) && + (client->state == AVAHI_CLIENT_S_RUNNING || client->state == AVAHI_CLIENT_S_REGISTERING || client->state == AVAHI_CLIENT_S_COLLISION); +} + +int avahi_client_set_host_name(AvahiClient* client, const char *name) { + DBusMessage *message = NULL, *reply = NULL; + DBusError error; + + assert(client); + + if (!avahi_client_is_connected(client)) + return avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE); + + dbus_error_init (&error); + + if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "SetHostName"))) { + avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { + avahi_client_set_errno (client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error); + + if (!reply || dbus_error_is_set (&error)) + goto fail; + + if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) + goto fail; + + dbus_message_unref(message); + dbus_message_unref(reply); + + avahi_free(client->host_name); + client->host_name = NULL; + avahi_free(client->host_name_fqdn); + client->host_name_fqdn = NULL; + + return 0; + +fail: + + if (message) + dbus_message_unref(message); + if (reply) + dbus_message_unref(reply); + + if (dbus_error_is_set(&error)) { + avahi_client_set_dbus_error(client, &error); + dbus_error_free(&error); + } + + return client->error; }