Blame gck/gck-call.c

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