summaryrefslogtreecommitdiff
path: root/gck/gck-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'gck/gck-call.c')
-rw-r--r--gck/gck-call.c542
1 files changed, 0 insertions, 542 deletions
diff --git a/gck/gck-call.c b/gck/gck-call.c
deleted file mode 100644
index f8393303..00000000
--- a/gck/gck-call.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* gck-call.c - the GObject PKCS#11 wrapper library
-
- Copyright (C) 2008, Stefan Walter
-
- The Gnome Keyring Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Keyring Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Stef Walter <nielsen@memberwebs.com>
-*/
-
-#include "config.h"
-
-#include "gck-private.h"
-
-#include <string.h>
-
-typedef struct _GckCallSource GckCallSource;
-
-static gpointer _gck_call_parent_class = NULL;
-
-struct _GckCall {
- GObject parent;
- GckModule *module;
-
- /* For making the call */
- GckPerformFunc perform;
- GckCompleteFunc complete;
- GckArguments *args;
- GCancellable *cancellable;
- GDestroyNotify destroy;
- CK_RV rv;
-
- /* For result callback only */
- gpointer object;
- GAsyncReadyCallback callback;
- gpointer user_data;
-};
-
-struct _GckCallClass {
- GObjectClass parent;
- GThreadPool *thread_pool;
- GAsyncQueue *completed_queue;
- guint completed_id;
-};
-
-struct _GckCallSource {
- GSource source;
- GckCallClass *klass;
-};
-
-/* ----------------------------------------------------------------------------
- * HELPER FUNCTIONS
- */
-
-static CK_RV
-perform_call (GckPerformFunc func, GCancellable *cancellable, GckArguments *args)
-{
- CK_RV rv;
-
- /* Double check a few things */
- g_assert (func);
- g_assert (args);
-
- if (cancellable) {
- if (g_cancellable_is_cancelled (cancellable)) {
- return CKR_FUNCTION_CANCELED;
- }
-
- /* Push for the notify callback */
- g_object_ref (cancellable);
- g_cancellable_push_current (cancellable);
- }
-
- rv = (func) (args);
-
- if (cancellable) {
- g_cancellable_pop_current (cancellable);
- g_object_unref (cancellable);
- }
-
- return rv;
-}
-
-static gboolean
-complete_call (GckCompleteFunc func, GckArguments *args, CK_RV result)
-{
- /* Double check a few things */
- g_assert (args);
-
- /* If no complete function, then just ignore */
- if (!func)
- return TRUE;
-
- return (func) (args, result);
-}
-
-
-static void
-process_async_call (gpointer data, GckCallClass *klass)
-{
- GckCall *call = GCK_CALL (data);
-
- g_assert (GCK_IS_CALL (call));
-
- call->rv = perform_call (call->perform, call->cancellable, call->args);
-
- g_async_queue_push (klass->completed_queue, call);
-
- /* Wakeup main thread if on a separate thread */
- g_main_context_wakeup (NULL);
-}
-
-static void
-process_result (GckCall *call, gpointer unused)
-{
- gboolean stop = FALSE;
-
- /* Double check a few things */
- g_assert (GCK_IS_CALL (call));
-
- if (call->cancellable) {
- /* Don't call the callback when cancelled */
- if (g_cancellable_is_cancelled (call->cancellable)) {
- call->rv = CKR_FUNCTION_CANCELED;
- stop = TRUE;
- }
- }
-
- /*
- * Hmmm, does the function want to actually be done?
- * If not, then queue this call again.
- */
- if (!stop && !complete_call (call->complete, call->args, call->rv)) {
- g_object_ref (call);
- g_thread_pool_push (GCK_CALL_GET_CLASS (call)->thread_pool, call, NULL);
-
- /* All done, finish processing */
- } else if (call->callback) {
- (call->callback) (call->object, G_ASYNC_RESULT (call),
- call->user_data);
- }
-}
-
-static gboolean
-process_completed (GckCallClass *klass)
-{
- gpointer call;
-
- g_assert (klass->completed_queue);
-
- call = g_async_queue_try_pop (klass->completed_queue);
- if (call) {
- process_result (call, NULL);
- g_object_unref (call);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-completed_prepare(GSource* base, gint *timeout)
-{
- GckCallSource *source = (GckCallSource*)base;
- gboolean have;
-
- g_assert (source->klass->completed_queue);
- have = g_async_queue_length (source->klass->completed_queue) > 0;
- *timeout = have ? 0 : -1;
- return have;
-}
-
-static gboolean
-completed_check(GSource* base)
-{
- GckCallSource *source = (GckCallSource*)base;
- g_assert (source->klass->completed_queue);
- return g_async_queue_length (source->klass->completed_queue) > 0;
-}
-
-static gboolean
-completed_dispatch(GSource* base, GSourceFunc callback, gpointer user_data)
-{
- GckCallSource *source = (GckCallSource*)base;
- process_completed (source->klass);
- return TRUE;
-}
-
-static void
-completed_finalize(GSource* base)
-{
-
-}
-
-static GSourceFuncs completed_functions = {
- completed_prepare,
- completed_check,
- completed_dispatch,
- completed_finalize
-};
-
-/* ----------------------------------------------------------------------------
- * OBJECT
- */
-
-static void
-_gck_call_init (GckCall *call)
-{
- call->rv = CKR_OK;
-}
-
-static void
-_gck_call_finalize (GObject *obj)
-{
- GckCall *call = GCK_CALL (obj);
-
- if (call->module)
- g_object_unref (call->module);
- call->module = NULL;
-
- if (call->object)
- g_object_unref (call->object);
- call->object = NULL;
-
- if (call->cancellable)
- g_object_unref (call->cancellable);
- call->cancellable = NULL;
-
- if (call->destroy)
- (call->destroy) (call->args);
- call->destroy = NULL;
- call->args = NULL;
-
- G_OBJECT_CLASS (_gck_call_parent_class)->finalize (obj);
-}
-
-static gpointer
-_gck_call_get_user_data (GAsyncResult *async_result)
-{
- g_return_val_if_fail (GCK_IS_CALL (async_result), NULL);
- return GCK_CALL (async_result)->user_data;
-}
-
-static GObject*
-_gck_call_get_source_object (GAsyncResult *async_result)
-{
- g_return_val_if_fail (GCK_IS_CALL (async_result), NULL);
- return GCK_CALL (async_result)->object;
-}
-
-static void
-_gck_call_implement_async_result (GAsyncResultIface *iface)
-{
- iface->get_user_data = _gck_call_get_user_data;
- iface->get_source_object = _gck_call_get_source_object;
-}
-
-static void
-_gck_call_class_init (GckCallClass *klass)
-{
- GObjectClass *gobject_class = (GObjectClass*)klass;
-
- _gck_call_parent_class = g_type_class_peek_parent (klass);
- gobject_class->finalize = _gck_call_finalize;
-}
-
-static void
-_gck_call_base_init (GckCallClass *klass)
-{
- GckCallSource *source;
- GMainContext *context;
- GError *err = NULL;
-
- klass->thread_pool = g_thread_pool_new ((GFunc)process_async_call, klass, 16, FALSE, &err);
- if (!klass->thread_pool) {
- g_critical ("couldn't create thread pool: %s",
- err && err->message ? err->message : "");
- return;
- }
-
- klass->completed_queue = g_async_queue_new_full (g_object_unref);
- g_assert (klass->completed_queue);
-
- context = g_main_context_default ();
- g_assert (context);
-
- /* Add our idle handler which processes other tasks */
- source = (GckCallSource*)g_source_new (&completed_functions, sizeof (GckCallSource));
- source->klass = klass;
- klass->completed_id = g_source_attach ((GSource*)source, context);
- g_source_set_callback ((GSource*)source, NULL, NULL, NULL);
- g_source_unref ((GSource*)source);
-}
-
-static void
-_gck_call_base_finalize (GckCallClass *klass)
-{
- GMainContext *context;
- GSource *src;
-
- if (klass->thread_pool) {
- g_assert (g_thread_pool_unprocessed (klass->thread_pool) == 0);
- g_thread_pool_free (klass->thread_pool, FALSE, TRUE);
- klass->thread_pool = NULL;
- }
-
- if (klass->completed_id) {
- context = g_main_context_default ();
- g_return_if_fail (context);
-
- src = g_main_context_find_source_by_id (context, klass->completed_id);
- g_assert (src);
- g_source_destroy (src);
- klass->completed_id = 0;
- }
-
- if (klass->completed_queue) {
- g_assert (g_async_queue_length (klass->completed_queue));
- g_async_queue_unref (klass->completed_queue);
- klass->completed_queue = NULL;
- }
-}
-
-GType
-_gck_call_get_type (void)
-{
- static volatile gsize type_id__volatile = 0;
-
- if (g_once_init_enter (&type_id__volatile)) {
-
- static const GTypeInfo type_info = {
- sizeof (GckCallClass),
- (GBaseInitFunc)_gck_call_base_init,
- (GBaseFinalizeFunc)_gck_call_base_finalize,
- (GClassInitFunc)_gck_call_class_init,
- (GClassFinalizeFunc)NULL,
- NULL, // class_data
- sizeof (GckCall),
- 0, // n_preallocs
- (GInstanceInitFunc)_gck_call_init,
- };
-
- static const GInterfaceInfo interface_info = {
- (GInterfaceInitFunc)_gck_call_implement_async_result
- };
-
- GType type_id = g_type_register_static (G_TYPE_OBJECT, "_GckCall", &type_info, 0);
- g_type_add_interface_static (type_id, G_TYPE_ASYNC_RESULT, &interface_info);
-
- g_once_init_leave (&type_id__volatile, type_id);
- }
-
- return type_id__volatile;
-}
-
-/* ----------------------------------------------------------------------------
- * PUBLIC
- */
-
-void
-_gck_call_uninitialize (void)
-{
-
-}
-
-gboolean
-_gck_call_sync (gpointer object, gpointer perform, gpointer complete,
- gpointer data, GCancellable *cancellable, GError **err)
-{
- GckArguments *args = (GckArguments*)data;
- GckModule *module = NULL;
- CK_RV rv;
-
- g_assert (!object || G_IS_OBJECT (object));
- g_assert (perform);
- g_assert (args);
-
- if (object) {
- g_object_get (object, "module", &module, "handle", &args->handle, NULL);
- g_assert (GCK_IS_MODULE (module));
-
- /* We now hold a reference to module until below */
- args->pkcs11 = gck_module_get_functions (module);
- g_assert (args->pkcs11);
- }
-
- do {
- rv = perform_call (perform, cancellable, args);
- if (rv == CKR_FUNCTION_CANCELED)
- break;
-
- } while (!complete_call (complete, args, rv));
-
- if (module)
- g_object_unref (module);
-
- if (rv == CKR_OK)
- return TRUE;
-
- g_set_error (err, GCK_ERROR, rv, "%s", gck_message_from_rv (rv));
- return FALSE;
-}
-
-gpointer
-_gck_call_async_prep (gpointer object, gpointer cb_object, gpointer perform,
- gpointer complete, gsize args_size, gpointer destroy)
-{
- GckArguments *args;
- GckCall *call;
-
- g_assert (!object || G_IS_OBJECT (object));
- g_assert (!cb_object || G_IS_OBJECT (cb_object));
- g_assert (perform);
-
- if (!destroy)
- destroy = g_free;
-
- if (args_size == 0)
- args_size = sizeof (GckArguments);
- g_assert (args_size >= sizeof (GckArguments));
-
- args = g_malloc0 (args_size);
- call = g_object_new (GCK_TYPE_CALL, NULL);
- call->destroy = (GDestroyNotify)destroy;
- call->perform = (GckPerformFunc)perform;
- call->complete = (GckCompleteFunc)complete;
- call->object = cb_object ? g_object_ref (cb_object) : NULL;
-
- /* Hook the two together */
- call->args = args;
- call->args->call = call;
-
- /* Setup call object if available */
- if (object != NULL)
- _gck_call_async_object (call, object);
-
- return args;
-}
-
-void
-_gck_call_async_object (GckCall *call, gpointer object)
-{
- g_assert (GCK_IS_CALL (call));
- g_assert (call->args);
-
- if (call->module)
- g_object_unref (call->module);
- call->module = NULL;
-
- g_object_get (object, "module", &call->module, "handle", &call->args->handle, NULL);
- g_assert (GCK_IS_MODULE (call->module));
- call->args->pkcs11 = gck_module_get_functions (call->module);
-
- /* We now hold a reference on module until finalize */
-}
-
-GckCall*
-_gck_call_async_ready (gpointer data, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckArguments *args = (GckArguments*)data;
- g_assert (GCK_IS_CALL (args->call));
-
- args->call->cancellable = cancellable;
- if (cancellable) {
- g_assert (G_IS_CANCELLABLE (cancellable));
- g_object_ref (cancellable);
- }
-
- args->call->callback = callback;
- args->call->user_data = user_data;
-
- return args->call;
-}
-
-void
-_gck_call_async_go (GckCall *call)
-{
- g_assert (GCK_IS_CALL (call));
-
- /* To keep things balanced, process at one completed event */
- process_completed(GCK_CALL_GET_CLASS (call));
-
- g_assert (GCK_CALL_GET_CLASS (call)->thread_pool);
- g_thread_pool_push (GCK_CALL_GET_CLASS (call)->thread_pool, call, NULL);
-}
-
-void
-_gck_call_async_ready_go (gpointer data, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GckCall *call = _gck_call_async_ready (data, cancellable, callback, user_data);
- _gck_call_async_go (call);
-}
-
-gboolean
-_gck_call_basic_finish (GAsyncResult *result, GError **err)
-{
- CK_RV rv;
-
- g_return_val_if_fail (GCK_IS_CALL (result), FALSE);
-
- rv = GCK_CALL (result)->rv;
- if (rv == CKR_OK)
- return TRUE;
-
- g_set_error (err, GCK_ERROR, rv, "%s", gck_message_from_rv (rv));
- return FALSE;
-}
-
-void
-_gck_call_async_short (GckCall *call, CK_RV rv)
-{
- g_assert (GCK_IS_CALL (call));
-
- call->rv = rv;
-
- /* Already complete, so just push it for processing in main loop */
- g_assert (GCK_CALL_GET_CLASS (call)->completed_queue);
- g_async_queue_push (GCK_CALL_GET_CLASS (call)->completed_queue, call);
- g_main_context_wakeup (NULL);
-}
-
-gpointer
-_gck_call_get_arguments (GckCall *call)
-{
- g_assert (GCK_IS_CALL (call));
- return call->args;
-}