diff options
Diffstat (limited to 'avahi-client/client.c')
| -rw-r--r-- | avahi-client/client.c | 175 | 
1 files changed, 114 insertions, 61 deletions
diff --git a/avahi-client/client.c b/avahi-client/client.c index ef77366..1067456 100644 --- a/avahi-client/client.c +++ b/avahi-client/client.c @@ -39,6 +39,8 @@  #include "client.h"  #include "internal.h" +static int init_server(AvahiClient *client, int *ret_error); +  int avahi_client_set_errno (AvahiClient *client, int error) {      assert(client); @@ -84,6 +86,7 @@ static void client_set_state (AvahiClient *client, AvahiServerState state) {              break;          case AVAHI_CLIENT_S_RUNNING: +        case AVAHI_CLIENT_CONNECTING:              break;      } @@ -99,21 +102,18 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message,      assert(bus);      assert(message); -    dbus_error_init (&error); +    dbus_error_init(&error);  /*     fprintf(stderr, "dbus: interface=%s, path=%s, member=%s\n", */  /*             dbus_message_get_interface (message), */  /*             dbus_message_get_path (message), */  /*             dbus_message_get_member (message)); */ -    if (client->state == AVAHI_CLIENT_FAILURE) -        goto fail; -      if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {          /* The DBUS server died or kicked us */          avahi_client_set_errno(client, AVAHI_ERR_DISCONNECTED); -        client_set_state(client, AVAHI_CLIENT_FAILURE); +        goto fail;      } if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {          char *name, *old, *new; @@ -123,22 +123,39 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message,                    DBUS_TYPE_STRING, &name,                    DBUS_TYPE_STRING, &old,                    DBUS_TYPE_STRING, &new, -                  DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { +                  DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) {              fprintf(stderr, "WARNING: Failed to parse NameOwnerChanged signal: %s\n", error.message); +            avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);              goto fail;          }          if (strcmp(name, AVAHI_DBUS_NAME) == 0) { -            /* Regardless if the server lost or acquired its name or -             * if the name was transfered: our services are no longer -             * available, so we disconnect ourselves */ +            if (avahi_client_is_connected(client)) { -            avahi_client_set_errno(client, AVAHI_ERR_DISCONNECTED); -            client_set_state(client, AVAHI_CLIENT_FAILURE); +                /* Regardless if the server lost or acquired its name or +                 * if the name was transfered: our services are no longer +                 * available, so we disconnect ourselves */ +                avahi_client_set_errno(client, AVAHI_ERR_DISCONNECTED); +                goto fail; +                 +            } else if (client->state == AVAHI_CLIENT_CONNECTING && (!old || *old == 0)) { +                int ret; +                 +                /* Server appeared */ +                 +                if ((ret = init_server(client, NULL)) < 0) { +                    avahi_client_set_errno(client, ret); +                    goto fail; +                } +            }          } +    } else if (!avahi_client_is_connected(client)) { +         +        /* Ignore messages, we get in unconnected state */ +              } else if (dbus_message_is_signal (message, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged")) {          int32_t state;          char *e = NULL; @@ -149,7 +166,9 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message,                    DBUS_TYPE_INT32, &state,                    DBUS_TYPE_STRING, &e,                    DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { +              fprintf(stderr, "WARNING: Failed to parse Server.StateChanged signal: %s\n", error.message); +            avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);              goto fail;          } @@ -178,7 +197,9 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message,                        DBUS_TYPE_STRING, &e,                        DBUS_TYPE_INVALID) ||                  dbus_error_is_set(&error)) { +                  fprintf(stderr, "WARNING: Failed to parse EntryGroup.StateChanged signal: %s\n", error.message); +                avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);                  goto fail;              } @@ -235,12 +256,27 @@ 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 { + +        fprintf(stderr, "WARNING: Unhandled message: interface=%s, path=%s, member=%s\n", +               dbus_message_get_interface(message),  +               dbus_message_get_path(message), +               dbus_message_get_member(message)); +         +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +    }      return DBUS_HANDLER_RESULT_HANDLED;  fail: -    dbus_error_free (&error); +    if (dbus_error_is_set(&error)) { +        avahi_client_set_errno(client, avahi_error_dbus_to_number(error.name)); +        dbus_error_free(&error); +    } + +    client_set_state(client, AVAHI_CLIENT_FAILURE); +          return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;  } @@ -339,45 +375,46 @@ fail:      return e;  } +static int init_server(AvahiClient *client, int *ret_error) { +    int r; +     +    if ((r = check_version(client, ret_error)) < 0) +        return r; -/* This function acts like dbus_bus_get but creates a private - * connection instead */ -static DBusConnection* -avahi_dbus_bus_get (DBusError *error) -{ -    DBusConnection *conn; -    const char *env_addr; - -    env_addr = getenv ("DBUS_SYSTEM_BUS_ADDRESS"); +    if ((r = get_server_state(client, ret_error)) < 0) +        return r; -    if (env_addr == NULL || (*env_addr == 0)) -    { -        env_addr = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS; -    } +    return AVAHI_OK; +} -    conn = dbus_connection_open_private (env_addr, error); +/* This function acts like dbus_bus_get but creates a private + * connection instead */ +static DBusConnection* avahi_dbus_bus_get(DBusError *error) { +    DBusConnection *c; +    const char *a; -    if (!conn) +    if (!(a = getenv("DBUS_SYSTEM_BUS_ADDRESS")) || !*a) +        a = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS; +     +    if (!(c = dbus_connection_open_private(a, error)))          return NULL; -    dbus_connection_set_exit_on_disconnect (conn, FALSE); - -    if (!dbus_bus_register (conn, error)) -    { -        dbus_connection_close (conn); -        dbus_connection_unref (conn); +    dbus_connection_set_exit_on_disconnect(c, FALSE); +    if (!dbus_bus_register(c, error)) { +        dbus_connection_close(c); +        dbus_connection_unref(c);          return NULL;      } -    return conn; +    return c;  } -AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientCallback callback, void *userdata, int *ret_error) { +AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientFlags flags, AvahiClientCallback callback, void *userdata, int *ret_error) {      AvahiClient *client = NULL;      DBusError error; -    dbus_error_init (&error); +    dbus_error_init(&error);      if (!(client = avahi_new(AvahiClient, 1))) {          if (ret_error) @@ -389,8 +426,9 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientCallback cal      client->error = AVAHI_OK;      client->callback = callback;      client->userdata = userdata; -    client->state = AVAHI_CLIENT_FAILURE; - +    client->state = (AvahiClientState) -1; +    client->flags = flags; +          client->host_name = NULL;      client->host_name_fqdn = NULL;      client->domain_name = NULL; @@ -405,9 +443,11 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientCallback cal      AVAHI_LLIST_HEAD_INIT(AvahiHostNameResolver, client->host_name_resolvers);      AVAHI_LLIST_HEAD_INIT(AvahiAddressResolver, client->address_resolvers); -    if (!(client->bus = avahi_dbus_bus_get(&error)) || -        dbus_error_is_set (&error)) +    if (!(client->bus = avahi_dbus_bus_get(&error)) || dbus_error_is_set(&error)) { +        if (ret_error) +            *ret_error = AVAHI_ERR_DBUS_ERROR;          goto fail; +    }      if (avahi_dbus_connection_glue(client->bus, poll_api) < 0) {          if (ret_error) @@ -429,7 +469,7 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientCallback cal          "path='" AVAHI_DBUS_PATH_SERVER "'",          &error); -    if (dbus_error_is_set (&error)) +    if (dbus_error_is_set(&error))          goto fail;      dbus_bus_add_match ( @@ -440,36 +480,43 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientCallback cal          "path='" DBUS_PATH_DBUS "'",          &error); -    if (dbus_error_is_set (&error)) +    if (dbus_error_is_set(&error))          goto fail; -        dbus_bus_add_match ( +    dbus_bus_add_match (          client->bus,          "type='signal', "          "interface='" DBUS_INTERFACE_LOCAL "'",          &error); -    if (dbus_error_is_set (&error)) +    if (dbus_error_is_set(&error))          goto fail; +      if (!(dbus_bus_name_has_owner(client->bus, AVAHI_DBUS_NAME, &error)) ||          dbus_error_is_set(&error)) {          /* We free the error so its not set, that way the fail target           * will return the NO_DAEMON error rather than a DBUS error */ -        dbus_error_free (&error); +        dbus_error_free(&error); -        if (ret_error) -            *ret_error = AVAHI_ERR_NO_DAEMON; +        if (!(flags & AVAHI_CLIENT_NO_FAIL)) { +             +            if (ret_error) +                *ret_error = AVAHI_ERR_NO_DAEMON; -        goto fail; -    } +            goto fail; +        } -    if (check_version(client, ret_error) < 0) -        goto fail; +        /* The user doesn't want this call to fail if the daemon is not +         * available, so let's return succesfully */ +        client_set_state(client, AVAHI_CLIENT_CONNECTING); +         +    } else { -    if (get_server_state(client, ret_error) < 0) -        goto fail; +        if (init_server(client, ret_error) < 0) +            goto fail; +    }      return client; @@ -576,10 +623,10 @@ fail:      return NULL;  } -const char* avahi_client_get_version_string (AvahiClient *client) { +const char* avahi_client_get_version_string(AvahiClient *client) {      assert(client); -    if (client->state == AVAHI_CLIENT_FAILURE) { +    if (!avahi_client_is_connected(client)) {          avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);          return NULL;      } @@ -590,10 +637,10 @@ const char* avahi_client_get_version_string (AvahiClient *client) {      return client->version_string;  } -const char* avahi_client_get_domain_name (AvahiClient *client) { +const char* avahi_client_get_domain_name(AvahiClient *client) {      assert(client); -    if (client->state == AVAHI_CLIENT_FAILURE) { +    if (!avahi_client_is_connected(client)) {          avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);          return NULL;      } @@ -604,10 +651,10 @@ const char* avahi_client_get_domain_name (AvahiClient *client) {      return client->domain_name;  } -const char* avahi_client_get_host_name (AvahiClient *client) { +const char* avahi_client_get_host_name(AvahiClient *client) {      assert(client); -    if (client->state == AVAHI_CLIENT_FAILURE) { +    if (!avahi_client_is_connected(client)) {          avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);          return NULL;      } @@ -621,7 +668,7 @@ const char* avahi_client_get_host_name (AvahiClient *client) {  const char* avahi_client_get_host_name_fqdn (AvahiClient *client) {      assert(client); -    if (client->state == AVAHI_CLIENT_FAILURE) { +    if (!avahi_client_is_connected(client)) {          avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);          return NULL;      } @@ -699,7 +746,7 @@ uint32_t avahi_client_get_local_service_cookie(AvahiClient *client) {      DBusError error;      assert(client); -    if (client->state == AVAHI_CLIENT_FAILURE) { +    if (!avahi_client_is_connected(client)) {          avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);          return AVAHI_SERVICE_COOKIE_INVALID;      } @@ -743,3 +790,9 @@ fail:      return AVAHI_SERVICE_COOKIE_INVALID;  } + +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; +}  | 
