[gnome-keyring] gck: Add async initialization functions.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gck: Add async initialization functions.
- Date: Thu, 25 Aug 2011 09:27:28 +0000 (UTC)
commit 25b32cc25c7bf5a2707204743c04fed63c7e2e18
Author: Stef Walter <stefw collabora co uk>
Date: Thu Aug 25 11:21:24 2011 +0200
gck: Add async initialization functions.
* PKCS#11 modules can take indeterminate time to initialize
* Allow initialization in a separate thread
docs/reference/gck/gck-sections.txt | 8 ++-
gck/gck-call.c | 7 +-
gck/gck-module.c | 150 +++++++++++++++++++++++++++--------
gck/gck-modules.c | 108 +++++++++++++++++++++----
gck/gck.h | 17 ++++-
gck/tests/Makefile.am | 2 +-
gck/tests/test-gck-module.c | 51 ++++++++++--
po/POTFILES.in | 2 +
8 files changed, 281 insertions(+), 64 deletions(-)
---
diff --git a/docs/reference/gck/gck-sections.txt b/docs/reference/gck/gck-sections.txt
index ed878b7..56e05c2 100644
--- a/docs/reference/gck/gck-sections.txt
+++ b/docs/reference/gck/gck-sections.txt
@@ -62,8 +62,10 @@ GckAllocator
<SECTION>
<FILE>gck-module</FILE>
GckModule
-gck_module_new
gck_module_initialize
+gck_module_initialize_async
+gck_module_initialize_finish
+gck_module_new
gck_module_equal
gck_module_hash
gck_module_get_path
@@ -86,10 +88,12 @@ GckModulePrivate
<SECTION>
<FILE>gck-modules</FILE>
+gck_modules_initialize_registered
+gck_modules_initialize_registered_async
+gck_modules_initialize_registered_finish
gck_modules_enumerate_objects
gck_modules_enumerate_uri
gck_modules_get_slots
-gck_modules_initialize_registered
gck_modules_object_for_uri
gck_modules_objects_for_uri
gck_modules_token_for_uri
diff --git a/gck/gck-call.c b/gck/gck-call.c
index 6e46632..f839330 100644
--- a/gck/gck-call.c
+++ b/gck/gck-call.c
@@ -149,8 +149,7 @@ process_result (GckCall *call, gpointer unused)
/* All done, finish processing */
} else if (call->callback) {
- g_assert (G_IS_OBJECT (call->object));
- (call->callback) (G_OBJECT (call->object), G_ASYNC_RESULT (call),
+ (call->callback) (call->object, G_ASYNC_RESULT (call),
call->user_data);
}
}
@@ -423,6 +422,7 @@ _gck_call_async_prep (gpointer object, gpointer cb_object, gpointer perform,
GckCall *call;
g_assert (!object || G_IS_OBJECT (object));
+ g_assert (!cb_object || G_IS_OBJECT (cb_object));
g_assert (perform);
if (!destroy)
@@ -437,8 +437,7 @@ _gck_call_async_prep (gpointer object, gpointer cb_object, gpointer perform,
call->destroy = (GDestroyNotify)destroy;
call->perform = (GckPerformFunc)perform;
call->complete = (GckCompleteFunc)complete;
- call->object = cb_object;
- g_object_ref (cb_object);
+ call->object = cb_object ? g_object_ref (cb_object) : NULL;
/* Hook the two together */
call->args = args;
diff --git a/gck/gck-module.c b/gck/gck-module.c
index c7e7646..fa2fd84 100644
--- a/gck/gck-module.c
+++ b/gck/gck-module.c
@@ -27,6 +27,8 @@
#include "gck-private.h"
#include "gck-marshal.h"
+#include <glib/gi18n.h>
+
#include <p11-kit/p11-kit.h>
#include <string.h>
@@ -371,66 +373,150 @@ gck_module_info_free (GckModuleInfo *module_info)
g_free (module_info);
}
-/**
- * gck_module_initialize:
- * @path: The file system path to the PKCS\#11 module to load.
- * @error: A location to store an error resulting from a failed load.
- *
- * Load and initialize a PKCS\#11 module represented by a GckModule object.
- *
- * Return value: The loaded PKCS\#11 module or NULL if failed.
- **/
-GckModule*
-gck_module_initialize (const gchar *path, GError **error)
+typedef struct {
+ GckArguments base;
+ gchar *path;
+ GckModule *result;
+ GError *error;
+} Initialize;
+
+static CK_RV
+perform_initialize (Initialize *args)
{
CK_C_GetFunctionList get_function_list;
CK_FUNCTION_LIST_PTR funcs;
GModule *module;
- GckModule *self;
+ GckModule *result;
CK_RV rv;
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (!error || !*error, NULL);
-
/* Load the actual module */
- module = g_module_open (path, 0);
+ module = g_module_open (args->path, 0);
if (!module) {
- g_set_error (error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
- "Error loading pkcs11 module: %s", g_module_error ());
- return NULL;
+ g_set_error (&args->error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
+ _("Error loading PKCS#11 module: %s"), g_module_error ());
+ return CKR_GCK_MODULE_PROBLEM;
}
/* Get the entry point */
if (!g_module_symbol (module, "C_GetFunctionList", (void**)&get_function_list)) {
- g_set_error (error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
- "Invalid pkcs11 module: %s", g_module_error ());
+ g_set_error (&args->error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
+ _("Invalid PKCS#11 module: %s"), g_module_error ());
g_module_close (module);
- return NULL;
+ return CKR_GCK_MODULE_PROBLEM;
}
/* Get the function list */
rv = (get_function_list) (&funcs);
if (rv != CKR_OK) {
- g_set_error (error, GCK_ERROR, rv, "Couldn't get pkcs11 function list: %s",
+ g_set_error (&args->error, GCK_ERROR, rv,
+ _("Couldn't setup PKCS#11 module: %s"),
gck_message_from_rv (rv));
g_module_close (module);
- return NULL;
+ return rv;
}
- self = g_object_new (GCK_TYPE_MODULE, "functions", funcs, "path", path, NULL);
- self->pv->module = module;
+ result = g_object_new (GCK_TYPE_MODULE,
+ "functions", funcs,
+ "path", args->path,
+ NULL);
+ result->pv->module = module;
/* Now initialize the module */
- rv = p11_kit_initialize_module (self->pv->funcs);
+ rv = p11_kit_initialize_module (funcs);
if (rv != CKR_OK) {
- g_set_error (error, GCK_ERROR, rv, "Couldn't initialize module: %s",
+ g_set_error (&args->error, GCK_ERROR, rv,
+ _("Couldn't initialize PKCS#11 module: %s"),
gck_message_from_rv (rv));
- g_object_unref (self);
- return NULL;
+ g_object_unref (result);
+ return rv;
+ }
+
+ result->pv->initialized = TRUE;
+ args->result = result;
+ return CKR_OK;
+}
+
+static void
+free_initialize (Initialize *args)
+{
+ g_free (args->path);
+ g_clear_error (&args->error);
+ g_clear_object (&args->result);
+ g_free (args);
+}
+
+/**
+ * gck_module_initialize:
+ * @path: The file system path to the PKCS\#11 module to load.
+ * @error: A location to store an error resulting from a failed load.
+ *
+ * Load and initialize a PKCS\#11 module represented by a GckModule object.
+ *
+ * Return value: The loaded PKCS\#11 module or NULL if failed.
+ **/
+GckModule*
+gck_module_initialize (const gchar *path,
+ GError **error)
+{
+ Initialize args = { GCK_ARGUMENTS_INIT, 0, };
+
+ g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (!error || !*error, NULL);
+
+ args.path = g_strdup (path);
+
+ if (!_gck_call_sync (NULL, perform_initialize, NULL, &args, NULL, error)) {
+
+ /* A custom error from perform_initialize */
+ if (args.error) {
+ g_clear_error (error);
+ g_propagate_error (error, args.error);
+ args.error = NULL;
+ }
}
- self->pv->initialized = TRUE;
- return self;
+ g_free (args.path);
+ g_clear_error (&args.error);
+ return args.result;
+}
+
+void
+gck_module_initialize_async (const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ Initialize *args;
+
+ args = _gck_call_async_prep (NULL, NULL, perform_initialize, NULL,
+ sizeof (*args), free_initialize);
+ args->path = g_strdup (path);
+
+ _gck_call_async_ready_go (args, cancellable, callback, user_data);
+}
+
+GckModule *
+gck_module_initialize_finish (GAsyncResult *result,
+ GError **error)
+{
+ GckModule *module = NULL;
+ Initialize *args;
+
+ args = _gck_call_arguments (result, Initialize);
+ if (_gck_call_basic_finish (result, error)) {
+ module = args->result;
+ args->result = NULL;
+
+ } else {
+ /* A custom error from perform_initialize */
+ if (args->error) {
+ g_clear_error (error);
+ g_propagate_error (error, args->error);
+ args->error = NULL;
+ }
+ }
+
+ return module;
}
/**
diff --git a/gck/gck-modules.c b/gck/gck-modules.c
index 4782688..fd0d456 100644
--- a/gck/gck-modules.c
+++ b/gck/gck-modules.c
@@ -27,6 +27,9 @@
#include "gck-private.h"
#include "gck-marshal.h"
+#include <glib/gi18n.h>
+
+#define P11_KIT_FUTURE_UNSTABLE_API 1
#include <p11-kit/p11-kit.h>
#include <string.h>
@@ -41,39 +44,110 @@
* operations on all of them.
*/
-/**
- * gck_modules_initialize_registered:
- *
- * Load and initialize all the registered modules.
- *
- * Returns: A newly allocated list of GckModule objects, which should
- * be released with gck_list_unref_free().
- */
-GList*
-gck_modules_initialize_registered (void)
+typedef struct {
+ GckArguments base;
+ GList *results;
+ GError *error;
+} InitializeRegistered;
+
+static CK_RV
+perform_initialize_registered (InitializeRegistered *args)
{
GckModule *module;
- GList *results = NULL;
CK_FUNCTION_LIST_PTR *modules, *funcs;
+ const gchar *message;
CK_RV rv;
rv = p11_kit_initialize_registered ();
if (rv != CKR_OK) {
- g_warning ("couldn't initialize registered PKCS#11 modules: %s",
- gck_message_from_rv (rv));
- return NULL;
+ message = p11_kit_message ();
+ if (message == NULL)
+ message = gck_message_from_rv (rv);
+ g_set_error (&args->error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
+ _("Couldn't initialize registered PKCS#11 modules: %s"), message);
+ return rv;
}
modules = p11_kit_registered_modules ();
-
for (funcs = modules; *funcs; ++funcs) {
module = _gck_module_new_initialized (*funcs);
- results = g_list_prepend (results, module);
+ args->results = g_list_prepend (args->results, module);
}
free (modules);
+ return CKR_OK;
+}
- return results;
+static void
+free_initialize_registered (InitializeRegistered *args)
+{
+ g_clear_error (&args->error);
+ gck_list_unref_free (args->results);
+ g_free (args);
+}
+
+/**
+ * gck_modules_initialize_registered:
+ *
+ * Load and initialize all the registered modules.
+ *
+ * Returns: A newly allocated list of GckModule objects, which should
+ * be released with gck_list_unref_free().
+ */
+GList*
+gck_modules_initialize_registered (void)
+{
+ InitializeRegistered args = { GCK_ARGUMENTS_INIT, 0, };
+ GError *error = NULL;
+
+ if (!_gck_call_sync (NULL, perform_initialize_registered, NULL, &args, NULL, &error)) {
+ if (args.error)
+ g_warning ("%s", args.error->message);
+ else
+ g_warning ("couldn't initialize registered PKCS#11 modules: %s",
+ error->message);
+ }
+
+ g_clear_error (&args.error);
+ g_clear_error (&error);
+ return args.results;
+}
+
+void
+gck_modules_initialize_registered_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ InitializeRegistered *args;
+
+ args = _gck_call_async_prep (NULL, NULL, perform_initialize_registered, NULL,
+ sizeof (*args), free_initialize_registered);
+
+ _gck_call_async_ready_go (args, cancellable, callback, user_data);
+}
+
+GList *
+gck_modules_initialize_registered_finish (GAsyncResult *result,
+ GError **error)
+{
+ GList *modules = NULL;
+ InitializeRegistered *args;
+
+ args = _gck_call_arguments (result, InitializeRegistered);
+ if (_gck_call_basic_finish (result, error)) {
+ modules = args->results;
+ args->results = NULL;
+
+ } else {
+ /* A custom error from perform_initialize */
+ if (args->error) {
+ g_clear_error (error);
+ g_propagate_error (error, args->error);
+ args->error = NULL;
+ }
+ }
+
+ return modules;
}
/**
diff --git a/gck/gck.h b/gck/gck.h
index 4de88fd..cdf280f 100644
--- a/gck/gck.h
+++ b/gck/gck.h
@@ -301,6 +301,14 @@ GckModule* gck_module_new (CK_FUNCTION_LIST_
GckModule* gck_module_initialize (const gchar *path,
GError **error);
+void gck_module_initialize_async (const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GckModule * gck_module_initialize_finish (GAsyncResult *result,
+ GError **error);
+
gboolean gck_module_equal (gconstpointer module1,
gconstpointer module2);
@@ -315,7 +323,14 @@ GckModuleInfo* gck_module_get_info (GckModule *self);
GList* gck_module_get_slots (GckModule *self,
gboolean token_present);
-GList* gck_modules_initialize_registered (void);
+GList* gck_modules_initialize_registered (void);
+
+void gck_modules_initialize_registered_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GList * gck_modules_initialize_registered_finish (GAsyncResult *result,
+ GError **error);
GList* gck_modules_get_slots (GList *modules,
gboolean token_present);
diff --git a/gck/tests/Makefile.am b/gck/tests/Makefile.am
index e43f2e6..4864fb8 100644
--- a/gck/tests/Makefile.am
+++ b/gck/tests/Makefile.am
@@ -30,7 +30,7 @@ TEST_PROGS = \
check_PROGRAMS = $(TEST_PROGS)
test: $(TEST_PROGS)
- gtester -k --verbose -m $(TEST_MODE) --g-fatal-warnings $(TEST_PROGS)
+ gtester --verbose -m $(TEST_MODE) --g-fatal-warnings $(TEST_PROGS)
check-local: test
diff --git a/gck/tests/test-gck-module.c b/gck/tests/test-gck-module.c
index 7e1b92a..72df360 100644
--- a/gck/tests/test-gck-module.c
+++ b/gck/tests/test-gck-module.c
@@ -27,6 +27,8 @@
#include <glib.h>
#include <string.h>
+#include "egg/egg-testing.h"
+
#include "gck/gck.h"
#include "gck/gck-test.h"
@@ -52,22 +54,56 @@ teardown (Test *test, gconstpointer unused)
}
static void
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ *((GAsyncResult**)user_data) = result;
+ g_object_ref (result);
+ egg_test_wait_stop ();
+}
+
+static void
+test_initialize_async (void)
+{
+ GckModule *module;
+ GAsyncResult *result;
+ GError *error = NULL;
+
+ /* Shouldn't be able to load modules */
+ gck_module_initialize_async (BUILDDIR "/.libs/libmock-test-module.so",
+ NULL, fetch_async_result, &result);
+
+ egg_test_wait_until (500);
+ g_assert (result != NULL);
+
+ /* Get the result */
+ module = gck_module_initialize_finish (result, &error);
+ g_assert_no_error (error);
+ g_assert (GCK_IS_MODULE (module));
+
+ g_object_unref (result);
+ g_object_unref (module);
+}
+
+
+static void
test_invalid_modules (Test *test, gconstpointer unused)
{
GckModule *invalid;
- GError *err = NULL;
+ GError *error = NULL;
/* Shouldn't be able to load modules */
- invalid = gck_module_initialize ("blah-blah-non-existant", &err);
+ invalid = gck_module_initialize ("blah-blah-non-existant", &error);
+ g_assert_error (error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM);
g_assert (invalid == NULL);
- g_assert_error (err, GCK_ERROR, CKR_GCK_MODULE_PROBLEM);
- g_clear_error (&err);
+ g_clear_error (&error);
/* Shouldn't be able to load any file successfully */
- invalid = gck_module_initialize ("/usr/lib/libm.so", &err);
+ invalid = gck_module_initialize ("/usr/lib/libm.so", &error);
+ g_assert_error (error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM);
g_assert (invalid == NULL);
- g_assert_error (err, GCK_ERROR, CKR_GCK_MODULE_PROBLEM);
+
+ g_clear_error (&error);
}
static void
@@ -130,10 +166,11 @@ main (int argc, char **argv)
g_type_init ();
g_test_init (&argc, &argv, NULL);
+ g_test_add_func ("/gck/module/initialize_async", test_initialize_async);
g_test_add ("/gck/module/invalid_modules", Test, NULL, setup, test_invalid_modules, teardown);
g_test_add ("/gck/module/module_equals_hash", Test, NULL, setup, test_module_equals_hash, teardown);
g_test_add ("/gck/module/module_props", Test, NULL, setup, test_module_props, teardown);
g_test_add ("/gck/module/module_info", Test, NULL, setup, test_module_info, teardown);
- return g_test_run ();
+ return egg_tests_run_in_thread_with_loop ();
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3b11f52..efe4a52 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,8 @@ daemon/login/gkd-login.c
daemon/org.gnome.keyring.service.in
egg/egg-oid.c
egg/egg-spawn.c
+gck/gck-module.c
+gck/gck-modules.c
gcr/gcr-certificate.c
gcr/gcr-certificate-exporter.c
gcr/gcr-certificate-extensions.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]