From: Matthew Barnes Date: Sat, 28 Jul 2012 16:04:27 +0000 (-0400) Subject: Replace e_source_registry_server_queue_auth_session(). X-Git-Tag: upstream/3.7.4~624 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56636b1bdf616e5d3581a050f827bfbd7ce3f1dc;p=platform%2Fupstream%2Fevolution-data-server.git Replace e_source_registry_server_queue_auth_session(). I realized ECollectionBackends are going to need a proper asynchronous authentication function so they know when authentication is achieved. e_source_registry_server_queue_auth_session() is a "fire-and-forget" function with no way for the caller to know if and when authentication is achieved. The replacement function, e_source_registry_server_authenticate_sync(), is a variation of e_source_registry_authenticate_sync() for use in the registry service itself. It takes an EAuthenticationSession instead of an ESource. Since this API has not yet seen a stable release, I'm going to forego deprecating the old function and just remove it. This is an API break, and the libebackend soname has been bumped accordingly. --- diff --git a/configure.ac b/configure.ac index a55a5d0..107f9b8 100644 --- a/configure.ac +++ b/configure.ac @@ -116,7 +116,7 @@ LIBCAMEL_CURRENT=39 LIBCAMEL_REVISION=0 LIBCAMEL_AGE=0 -LIBEBACKEND_CURRENT=4 +LIBEBACKEND_CURRENT=5 LIBEBACKEND_REVISION=0 LIBEBACKEND_AGE=0 diff --git a/docs/reference/libebackend/libebackend-sections.txt b/docs/reference/libebackend/libebackend-sections.txt index fb9752b..b9a34b7 100644 --- a/docs/reference/libebackend/libebackend-sections.txt +++ b/docs/reference/libebackend/libebackend-sections.txt @@ -361,7 +361,6 @@ ESourceRegistryServer e_source_registry_server_new e_source_registry_server_add_source e_source_registry_server_remove_source -e_source_registry_server_queue_auth_session e_source_registry_server_load_all ESourcePermissionFlags e_source_registry_server_load_directory @@ -370,6 +369,9 @@ e_source_registry_server_load_error e_source_registry_server_ref_source e_source_registry_server_list_sources e_source_registry_server_ref_backend_factory +e_source_registry_server_authenticate_sync +e_source_registry_server_authenticate +e_source_registry_server_authenticate_finish E_SOURCE_REGISTRY_SERVER E_IS_SOURCE_REGISTRY_SERVER diff --git a/libebackend/e-authentication-session.c b/libebackend/e-authentication-session.c index 138b024..470e75f 100644 --- a/libebackend/e-authentication-session.c +++ b/libebackend/e-authentication-session.c @@ -38,10 +38,10 @@ * interface themselves. * * The #EAuthenticationSession is then handed to #ESourceRegistryServer - * through e_source_registry_server_queue_auth_session() where it waits - * in line behind other previously added authentication sessions. When - * its turn comes, the server calls e_authentication_session_execute() - * to begin the interactive authentication session. + * through e_source_registry_server_authenticate() where it waits in line + * behind other previously added authentication sessions. When its turn + * comes, the server calls e_authentication_session_execute() to begin + * the interactive authentication session. **/ #include "e-authentication-session.h" diff --git a/libebackend/e-source-registry-server.c b/libebackend/e-source-registry-server.c index 07fd050..2bf10a0 100644 --- a/libebackend/e-source-registry-server.c +++ b/libebackend/e-source-registry-server.c @@ -57,6 +57,8 @@ * sources with a [Collection] extension. */ #define BACKEND_DATA_KEY "__e_collection_backend__" +typedef struct _AuthRequest AuthRequest; + struct _ESourceRegistryServerPrivate { GDBusObjectManagerServer *object_manager; EDBusSourceManager *source_manager; @@ -70,8 +72,8 @@ struct _ESourceRegistryServerPrivate { /* In pseudo-Python notation: * - * auth_table = { UID : [ EAuthenticationSession, ... ] } - * active_auths = { UID : EAuthenticationSession } + * running_auths = { UID : AuthRequest } + * waiting_auths = { UID : [ AuthRequest, ... ] } * * We process all authenticators for a given source UID at once. * The thought being after the first authenticator for a given UID @@ -82,13 +84,20 @@ struct _ESourceRegistryServerPrivate { * he gets what he asked for: lots of annoying prompts. */ GMutex *auth_lock; - GHashTable *auth_table; - GHashTable *active_auths; - GCancellable *auth_cancellable; + GHashTable *running_auths; + GHashTable *waiting_auths; guint authentication_count; }; +struct _AuthRequest { + volatile gint ref_count; + EAuthenticationSession *session; + GSimpleAsyncResult *simple; + ESource *source; /* may be NULL */ + GCancellable *cancellable; +}; + enum { LOAD_ERROR, FILES_LOADED, @@ -109,6 +118,65 @@ G_DEFINE_TYPE ( e_source_registry_server, E_TYPE_DATA_FACTORY) +static AuthRequest * +auth_request_new (EAuthenticationSession *session, + GSimpleAsyncResult *simple, + GCancellable *cancellable) +{ + ESourceRegistryServer *server; + AuthRequest *request; + const gchar *uid; + + server = e_authentication_session_get_server (session); + uid = e_authentication_session_get_source_uid (session); + + request = g_slice_new0 (AuthRequest); + request->ref_count = 1; + request->session = g_object_ref (session); + request->simple = g_object_ref (simple); + + /* This will return NULL if the authenticating data source + * has not yet been submitted to the D-Bus registry server. */ + request->source = e_source_registry_server_ref_source (server, uid); + + if (G_IS_CANCELLABLE (cancellable)) + request->cancellable = g_object_ref (cancellable); + + return request; +} + +static AuthRequest * +auth_request_ref (AuthRequest *request) +{ + g_return_val_if_fail (request != NULL, NULL); + g_return_val_if_fail (request->ref_count > 0, NULL); + + g_atomic_int_inc (&request->ref_count); + + return request; +} + +static void +auth_request_unref (AuthRequest *request) +{ + g_return_if_fail (request != NULL); + g_return_if_fail (request->ref_count > 0); + + if (g_atomic_int_dec_and_test (&request->ref_count)) { + + g_object_unref (request->session); + g_object_unref (request->simple); + + if (request->source != NULL) + g_object_unref (request->source); + + if (request->cancellable != NULL) + g_object_unref (request->cancellable); + + g_slice_free (AuthRequest, request); + } +} + /* GDestroyNotify callback for 'sources' values */ static void unref_data_source (ESource *source) @@ -118,7 +186,7 @@ unref_data_source (ESource *source) g_object_unref (source); } -/* GDestroyNotify callback for 'auth_table' values */ +/* GDestroyNotify callback for 'waiting_auths' values */ static void free_auth_queue (GQueue *queue) { @@ -301,24 +369,107 @@ source_registry_server_orphans_steal (ESourceRegistryServer *server, return array; } -static GQueue * -source_registry_server_auth_table_lookup (ESourceRegistryServer *server, - const gchar *uid) +static void +source_request_server_auth_request_cancel_all (ESourceRegistryServer *server) +{ + GHashTableIter iter; + gpointer value; + + g_mutex_lock (server->priv->auth_lock); + + g_hash_table_iter_init (&iter, server->priv->waiting_auths); + + while (g_hash_table_iter_next (&iter, NULL, &value)) { + GQueue *queue = value; + GList *list, *link; + + list = g_queue_peek_head_link (queue); + + for (link = list; link != NULL; link = g_list_next (link)) { + AuthRequest *request = link->data; + g_cancellable_cancel (request->cancellable); + } + } + + g_hash_table_iter_init (&iter, server->priv->running_auths); + + while (g_hash_table_iter_next (&iter, NULL, &value)) { + AuthRequest *request = value; + g_cancellable_cancel (request->cancellable); + } + + g_mutex_unlock (server->priv->auth_lock); +} + +static void +source_registry_server_auth_request_push (ESourceRegistryServer *server, + const gchar *uid, + AuthRequest *request) { - GHashTable *hash_table; GQueue *queue; - /* This MUST be called with the auth_lock acquired. */ + g_return_if_fail (uid != NULL); + + g_mutex_lock (server->priv->auth_lock); - hash_table = server->priv->auth_table; - queue = g_hash_table_lookup (hash_table, uid); + queue = g_hash_table_lookup (server->priv->waiting_auths, uid); if (queue == NULL) { queue = g_queue_new (); - g_hash_table_insert (hash_table, g_strdup (uid), queue); + g_hash_table_insert ( + server->priv->waiting_auths, + g_strdup (uid), queue); } - return queue; + g_queue_push_tail (queue, auth_request_ref (request)); + + g_mutex_unlock (server->priv->auth_lock); +} + +static AuthRequest * +source_registry_server_auth_request_next (ESourceRegistryServer *server, + const gchar *uid) +{ + AuthRequest *request = NULL; + + g_return_val_if_fail (uid != NULL, NULL); + + g_mutex_lock (server->priv->auth_lock); + + /* If we're already busy processing an authentication request + * for this UID, the next request will have to wait in line. */ + if (!g_hash_table_contains (server->priv->running_auths, uid)) { + GQueue *queue; + + queue = g_hash_table_lookup ( + server->priv->waiting_auths, uid); + + if (queue != NULL) + request = g_queue_pop_head (queue); + + if (request != NULL) + g_hash_table_insert ( + server->priv->running_auths, + g_strdup (uid), + auth_request_ref (request)); + } + + g_mutex_unlock (server->priv->auth_lock); + + return request; +} + +static void +source_registry_server_auth_request_done (ESourceRegistryServer *server, + const gchar *uid) +{ + g_return_if_fail (uid != NULL); + + g_mutex_lock (server->priv->auth_lock); + + g_hash_table_remove (server->priv->running_auths, uid); + + g_mutex_unlock (server->priv->auth_lock); } static void @@ -326,30 +477,27 @@ source_registry_server_auth_session_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { - EAuthenticationSession *session; ESourceRegistryServer *server; + EAuthenticationSession *session; EAuthenticationSessionResult auth_result; + AuthRequest *request; const gchar *uid; GError *error = NULL; session = E_AUTHENTICATION_SESSION (source_object); - server = E_SOURCE_REGISTRY_SERVER (user_data); + request = (AuthRequest *) user_data; auth_result = e_authentication_session_execute_finish ( session, result, &error); if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); + g_warn_if_fail (auth_result == E_AUTHENTICATION_SESSION_ERROR); + g_simple_async_result_take_error (request->simple, error); } - uid = e_authentication_session_get_source_uid (session); - g_return_if_fail (uid != NULL); - - /* Authentication dismissals may require additional handling. */ + /* Authentication dismissals require additional handling. */ if (auth_result == E_AUTHENTICATION_SESSION_DISMISSED) { ESourceAuthenticator *authenticator; - ESource *source; /* If the authenticator is an EAuthenticationMediator, * have it emit a "dismissed" signal to the client. */ @@ -359,63 +507,70 @@ source_registry_server_auth_session_cb (GObject *source_object, e_authentication_mediator_dismiss ( E_AUTHENTICATION_MEDIATOR (authenticator)); - /* This will return NULL if the authenticating data source - * has not yet been submitted to the D-Bus registry service. */ - source = e_source_registry_server_ref_source (server, uid); - if (source != NULL) { - /* Prevent further user interruptions. */ + /* Prevent further user interruptions. */ + if (request->source != NULL) e_server_side_source_set_allow_auth_prompt ( - E_SERVER_SIDE_SOURCE (source), FALSE); - g_object_unref (source); - } + E_SERVER_SIDE_SOURCE (request->source), FALSE); + + /* e_source_registry_server_authenticate_finish() should + * return an error since authentication did not complete. */ + g_simple_async_result_set_error ( + request->simple, + G_IO_ERROR, G_IO_ERROR_CANCELLED, + _("The user declined to authenticate")); } - /* Remove the UID from the active authentication set. */ - g_mutex_lock (server->priv->auth_lock); - g_hash_table_remove (server->priv->active_auths, uid); - g_mutex_unlock (server->priv->auth_lock); + g_simple_async_result_complete_in_idle (request->simple); + + server = e_authentication_session_get_server (session); + uid = e_authentication_session_get_source_uid (session); + source_registry_server_auth_request_done (server, uid); source_registry_server_maybe_start_auth_session (server, uid); - g_object_unref (server); + auth_request_unref (request); } static void source_registry_server_maybe_start_auth_session (ESourceRegistryServer *server, const gchar *uid) { - EAuthenticationSession *session; - GQueue *queue; + AuthRequest *request; - if (g_cancellable_is_cancelled (server->priv->auth_cancellable)) - return; - - g_mutex_lock (server->priv->auth_lock); - - /* If we're already busy processing an authentication request - * for this UID, the new request will have to wait in the queue. */ - if (g_hash_table_contains (server->priv->active_auths, uid)) - goto exit; - - queue = source_registry_server_auth_table_lookup (server, uid); - session = g_queue_pop_head (queue); + /* We own the returned reference, unless we get NULL. */ + request = source_registry_server_auth_request_next (server, uid); /* Execute the new active auth session. This signals it to * respond with a cached secret in the keyring if it can, or * else show an authentication prompt and wait for input. */ - if (session != NULL) { - g_hash_table_insert ( - server->priv->active_auths, - g_strdup (uid), g_object_ref (session)); + if (request != NULL) { e_authentication_session_execute ( - session, G_PRIORITY_DEFAULT, - server->priv->auth_cancellable, + request->session, + G_PRIORITY_DEFAULT, + request->cancellable, source_registry_server_auth_session_cb, - g_object_ref (server)); + request); /* takes ownership */ } +} -exit: - g_mutex_unlock (server->priv->auth_lock); +static void +source_registry_server_authenticate_done_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + + e_source_registry_server_authenticate_finish ( + E_SOURCE_REGISTRY_SERVER (source_object), result, &error); + + /* Ignore cancellations. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + + } else if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } } static void @@ -436,9 +591,18 @@ source_registry_server_wait_for_client_cb (GObject *source_object, if (error == NULL) { ESourceRegistryServer *server; - /* This references the session and adds it to a queue. */ server = e_authentication_session_get_server (session); - e_source_registry_server_queue_auth_session (server, session); + + /* Client is ready and waiting to test passwords, so + * execute the authentication session as soon as all + * other authentication sessions for this same data + * source are finished. + * + * XXX Note this asynchronous operation is not cancellable + * but it does time out on its own after a few minutes. */ + e_source_registry_server_authenticate ( + server, session, NULL, + source_registry_server_authenticate_done_cb, NULL); } else { /* Most likely the client went dark and the operation @@ -820,13 +984,8 @@ source_registry_server_dispose (GObject *object) g_hash_table_remove_all (priv->orphans); g_hash_table_remove_all (priv->monitors); - g_hash_table_remove_all (priv->auth_table); - g_hash_table_remove_all (priv->active_auths); - - if (priv->auth_cancellable != NULL) { - g_object_unref (priv->auth_cancellable); - priv->auth_cancellable = NULL; - } + g_hash_table_remove_all (priv->running_auths); + g_hash_table_remove_all (priv->waiting_auths); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_source_registry_server_parent_class)-> @@ -848,8 +1007,8 @@ source_registry_server_finalize (GObject *object) g_mutex_free (priv->orphans_lock); g_mutex_free (priv->auth_lock); - g_hash_table_destroy (priv->auth_table); - g_hash_table_destroy (priv->active_auths); + g_hash_table_destroy (priv->running_auths); + g_hash_table_destroy (priv->waiting_auths); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_source_registry_server_parent_class)-> @@ -892,8 +1051,8 @@ source_registry_server_quit_server (EDBusServer *server, priv = E_SOURCE_REGISTRY_SERVER_GET_PRIVATE (server); - /* Cancel any active authentication session. */ - g_cancellable_cancel (priv->auth_cancellable); + source_request_server_auth_request_cancel_all ( + E_SOURCE_REGISTRY_SERVER (server)); /* This makes the object manager unexport all objects. */ g_dbus_object_manager_server_set_connection ( @@ -1104,8 +1263,8 @@ e_source_registry_server_init (ESourceRegistryServer *server) GHashTable *sources; GHashTable *orphans; GHashTable *monitors; - GHashTable *auth_table; - GHashTable *active_auths; + GHashTable *running_auths; + GHashTable *waiting_auths; const gchar *object_path; object_path = E_SOURCE_REGISTRY_SERVER_OBJECT_PATH; @@ -1133,17 +1292,17 @@ e_source_registry_server_init (ESourceRegistryServer *server) (GDestroyNotify) g_object_unref, (GDestroyNotify) g_object_unref); - auth_table = g_hash_table_new_full ( + running_auths = g_hash_table_new_full ( (GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, (GDestroyNotify) g_free, - (GDestroyNotify) free_auth_queue); + (GDestroyNotify) auth_request_unref); - active_auths = g_hash_table_new_full ( + waiting_auths = g_hash_table_new_full ( (GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); + (GDestroyNotify) free_auth_queue); server->priv = E_SOURCE_REGISTRY_SERVER_GET_PRIVATE (server); server->priv->object_manager = object_manager; @@ -1154,9 +1313,8 @@ e_source_registry_server_init (ESourceRegistryServer *server) server->priv->sources_lock = g_mutex_new (); server->priv->orphans_lock = g_mutex_new (); server->priv->auth_lock = g_mutex_new (); - server->priv->auth_table = auth_table; - server->priv->active_auths = active_auths; - server->priv->auth_cancellable = g_cancellable_new (); + server->priv->waiting_auths = waiting_auths; + server->priv->running_auths = running_auths; g_signal_connect ( source_manager, "handle-authenticate", @@ -1342,41 +1500,6 @@ e_source_registry_server_remove_source (ESourceRegistryServer *server, } /** - * e_source_registry_server_queue_auth_session: - * @server: an #ESourceRegistryServer - * @session: an #EDBusSourceAuthenticator - * - * Queues an authentication session. When its turn comes, and if necessary, - * the user will be prompted for a secret. Sessions are queued this way to - * prevent user prompts from piling up on the screen. - * - * Since: 3.6 - **/ -void -e_source_registry_server_queue_auth_session (ESourceRegistryServer *server, - EAuthenticationSession *session) -{ - const gchar *uid; - GQueue *queue; - - g_return_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server)); - g_return_if_fail (E_IS_AUTHENTICATION_SESSION (session)); - - uid = e_authentication_session_get_source_uid (session); - g_return_if_fail (uid != NULL); - - g_mutex_lock (server->priv->auth_lock); - - /* Add the session to the appropriate queue. */ - queue = source_registry_server_auth_table_lookup (server, uid); - g_queue_push_tail (queue, g_object_ref (session)); - - g_mutex_unlock (server->priv->auth_lock); - - source_registry_server_maybe_start_auth_session (server, uid); -} - -/** * e_source_registry_server_load_all: * @server: an #ESourceRegistryServer * @error: return location for a #GError, or %NULL @@ -1797,3 +1920,134 @@ e_source_registry_server_ref_backend_factory (ESourceRegistryServer *server, return E_COLLECTION_BACKEND_FACTORY (factory); } +/** + * e_source_registry_server_authenticate_sync: + * @server: an #ESourceRegistryServer + * @session: an #EAuthenticationSession + * @cancellable: optional #GCancellable object, or %NULL + * @error: return location for a #GError, or %NULL + * + * Queues the @session behind any ongoing or pending authentication + * sessions for the same data source, and eventually executes @session + * (see e_authentication_session_execute_sync() for more details). + * + * This function blocks until @session is finished executing. For a + * non-blocking variation see e_source_registry_server_authenticate(). + * + * If an error occurs, the function sets @error and returns %FALSE. + * + * Returns: %TRUE on success, %FALSE on failure + * + * Since: 3.6 + **/ +gboolean +e_source_registry_server_authenticate_sync (ESourceRegistryServer *server, + EAuthenticationSession *session, + GCancellable *cancellable, + GError **error) +{ + EAsyncClosure *closure; + GAsyncResult *result; + gboolean success; + + g_return_val_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server), FALSE); + g_return_val_if_fail (E_IS_AUTHENTICATION_SESSION (session), FALSE); + + closure = e_async_closure_new (); + + e_source_registry_server_authenticate ( + server, session, cancellable, + e_async_closure_callback, closure); + + result = e_async_closure_wait (closure); + + success = e_source_registry_server_authenticate_finish ( + server, result, error); + + e_async_closure_free (closure); + + return success; +} + +/** + * e_source_registry_server_authenticate: + * @server: an #ESourceRegistryServer + * @session: an #EAuthenticationSession + * @cancellable: optional #GCancellable object, or %NULL + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: data to pass to the callback function + * + * Queues the @session behind any ongoing or pending authentication + * sessions for the same data source, and eventually executes @session + * (see e_authentication_session_execute_sync() for more details). + * + * This function returns immediately after enqueuing @session. When + * @session is finished executing, @callback will be called. You can + * then call e_source_registry_server_authenticate_finish() to get the + * result of the operation. + * + * Since: 3.6 + **/ +void +e_source_registry_server_authenticate (ESourceRegistryServer *server, + EAuthenticationSession *session, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + AuthRequest *request; + const gchar *uid; + + g_return_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server)); + g_return_if_fail (E_IS_AUTHENTICATION_SESSION (session)); + + uid = e_authentication_session_get_source_uid (session); + g_return_if_fail (uid != NULL); + + simple = g_simple_async_result_new ( + G_OBJECT (server), callback, user_data, + e_source_registry_server_authenticate); + + g_simple_async_result_set_check_cancellable (simple, cancellable); + + request = auth_request_new (session, simple, cancellable); + source_registry_server_auth_request_push (server, uid, request); + auth_request_unref (request); + + source_registry_server_maybe_start_auth_session (server, uid); + + g_object_unref (simple); +} + +/** + * e_source_registry_server_authenticate_finish: + * @server: an #ESourceRegistryServer + * @result: a #GAsyncResult + * @error: return location for a #GError, or %NULL + * + * Finishes the operation started with e_source_registry_server_authenticate(). + * If an error occurred, the function will set @error and return %FALSE. + * + * Returns: %TRUE on success, %FALSE on failure + * + * Since: 3.6 + **/ +gboolean +e_source_registry_server_authenticate_finish (ESourceRegistryServer *server, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail ( + g_simple_async_result_is_valid ( + result, G_OBJECT (server), + e_source_registry_server_authenticate), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + /* Assume success unless a GError is set. */ + return !g_simple_async_result_propagate_error (simple, error); +} + diff --git a/libebackend/e-source-registry-server.h b/libebackend/e-source-registry-server.h index 6427083..5b78ceb 100644 --- a/libebackend/e-source-registry-server.h +++ b/libebackend/e-source-registry-server.h @@ -101,9 +101,6 @@ void e_source_registry_server_add_source void e_source_registry_server_remove_source (ESourceRegistryServer *server, ESource *source); -void e_source_registry_server_queue_auth_session - (ESourceRegistryServer *server, - EAuthenticationSession *session); gboolean e_source_registry_server_load_all (ESourceRegistryServer *server, GError **error); @@ -131,6 +128,21 @@ ECollectionBackendFactory * e_source_registry_server_ref_backend_factory (ESourceRegistryServer *server, ESource *source); +gboolean e_source_registry_server_authenticate_sync + (ESourceRegistryServer *server, + EAuthenticationSession *session, + GCancellable *cancellable, + GError **error); +void e_source_registry_server_authenticate + (ESourceRegistryServer *server, + EAuthenticationSession *session, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean e_source_registry_server_authenticate_finish + (ESourceRegistryServer *server, + GAsyncResult *result, + GError **error); G_END_DECLS