+static int check_version(AvahiClient *client, int *ret_error) {
+ DBusMessage *message = NULL, *reply = NULL;
+ DBusError error;
+ 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, "GetAPIVersion")))
+ goto fail;
+
+ reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error);
+
+ if (!reply || dbus_error_is_set (&error)) {
+ char *version_str;
+
+ 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;
+ }
+
+ /*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;
+ }
+
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+
+ return AVAHI_OK;
+
+fail:
+ if (dbus_error_is_set(&error)) {
+ e = avahi_error_dbus_to_number (error.name);
+ dbus_error_free(&error);
+ }
+
+ if (ret_error)
+ *ret_error = e;
+
+ if (message)
+ dbus_message_unref(message);
+ if (reply)
+ dbus_message_unref(reply);
+
+ return e;
+}
+
+static int init_server(AvahiClient *client, int *ret_error) {
+ int r;
+
+ if ((r = check_version(client, ret_error)) < 0)
+ return r;
+
+ if ((r = get_server_state(client, ret_error)) < 0)
+ return r;
+
+ return AVAHI_OK;
+}
+
+/* This function acts like dbus_bus_get but creates a private
+ * connection instead. */
+static DBusConnection* avahi_dbus_bus_get(DBusError *error) {
+ DBusConnection *c;
+
+#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;
+
+ if (!(c = dbus_connection_open_private(a, error)))
+ return NULL;
+
+ 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;
+}
+
+AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientFlags flags, AvahiClientCallback callback, void *userdata, int *ret_error) {