gnome-keyring r1183 - in trunk: . gp11
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1183 - in trunk: . gp11
- Date: Sat, 19 Jul 2008 21:53:39 +0000 (UTC)
Author: nnielsen
Date: Sat Jul 19 21:53:39 2008
New Revision: 1183
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1183&view=rev
Log:
* gp11/gp11.h
* gp11/gp11.pc.in:
* gp11/gp11-call.c:
* gp11/gp11-private.h:
* gp11/gp11-session.c:
* gp11/gp11-slot.c:
* gp11/Makefile.am:
* gp11/tests/unit-test-gp11-session.c: Add ability to reuse sessions,
in a simple pool.
Modified:
trunk/ChangeLog
trunk/gp11/Makefile.am
trunk/gp11/gp11-call.c
trunk/gp11/gp11-private.h
trunk/gp11/gp11-session.c
trunk/gp11/gp11-slot.c
trunk/gp11/gp11.h
trunk/gp11/gp11.pc.in
Modified: trunk/gp11/Makefile.am
==============================================================================
--- trunk/gp11/Makefile.am (original)
+++ trunk/gp11/Makefile.am Sat Jul 19 21:53:39 2008
@@ -37,7 +37,10 @@
pkgconfig_DATA = gp11-$(GP11_MAJOR).pc
EXTRA_DIST = \
- gp11.pc.in
+ gp11.pc.in
+
+DISTCLEANFILES = \
+ gp11-$(GP11_MAJOR).pc
gp11-$(GP11_MAJOR).pc: gp11.pc
cp gp11.pc gp11-$(GP11_MAJOR).pc
Modified: trunk/gp11/gp11-call.c
==============================================================================
--- trunk/gp11/gp11-call.c (original)
+++ trunk/gp11/gp11-call.c Sat Jul 19 21:53:39 2008
@@ -304,6 +304,22 @@
return args;
}
+void
+_gp11_call_async_short (gpointer data, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GP11Arguments *args = (GP11Arguments*)data;
+
+ g_assert (GP11_IS_CALL (args->call));
+
+ args->call->callback = callback;
+ args->call->user_data = user_data;
+
+ /* Already complete, so just push it for processing in main loop */
+ g_assert (completed_queue);
+ g_async_queue_push (completed_queue, args->call);
+}
+
void
_gp11_call_async_go (gpointer data, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer user_data)
Modified: trunk/gp11/gp11-private.h
==============================================================================
--- trunk/gp11/gp11-private.h (original)
+++ trunk/gp11/gp11-private.h Sat Jul 19 21:53:39 2008
@@ -9,6 +9,10 @@
G_BEGIN_DECLS
+/* ---------------------------------------------------------------------------
+ * ATTRIBUTE INTERNALS
+ */
+
void _gp11_attribute_init_take (GP11Attribute *attr,
guint attr_type,
gpointer value,
@@ -92,6 +96,10 @@
GAsyncReadyCallback callback,
gpointer user_data);
+void _gp11_call_async_short (gpointer data,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
gboolean _gp11_call_basic_finish (gpointer object,
GAsyncResult *result,
GError **err);
Modified: trunk/gp11/gp11-session.c
==============================================================================
--- trunk/gp11/gp11-session.c (original)
+++ trunk/gp11/gp11-session.c Sat Jul 19 21:53:39 2008
@@ -7,6 +7,11 @@
#include <string.h>
enum {
+ DISCARD_HANDLE,
+ LAST_SIGNAL
+};
+
+enum {
PROP_0,
PROP_MODULE,
PROP_HANDLE
@@ -14,6 +19,8 @@
G_DEFINE_TYPE (GP11Session, gp11_session, G_TYPE_OBJECT);
+static guint signals[LAST_SIGNAL] = { 0 };
+
/* ----------------------------------------------------------------------------
* OBJECT
*/
@@ -64,6 +71,15 @@
{
GP11Session *session = GP11_SESSION (obj);
CK_RV rv;
+
+ g_return_if_fail (GP11_IS_SESSION (session));
+
+ /*
+ * Let the world know that we're discarding the session
+ * handle. This allows session reuse to work.
+ */
+ if (session->handle)
+ g_signal_emit_by_name (session, "discard-handle");
if (session->handle) {
g_return_if_fail (session->module && session->module->funcs);
@@ -112,6 +128,11 @@
g_object_class_install_property (gobject_class, PROP_HANDLE,
g_param_spec_uint ("handle", "Session Handle", "PKCS11 Session Handle",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ signals[DISCARD_HANDLE] = g_signal_new ("discard-handle", GP11_TYPE_SESSION,
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GP11SessionClass, discard_handle),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
}
/* ----------------------------------------------------------------------------
Modified: trunk/gp11/gp11-slot.c
==============================================================================
--- trunk/gp11/gp11-slot.c (original)
+++ trunk/gp11/gp11-slot.c Sat Jul 19 21:53:39 2008
@@ -9,11 +9,203 @@
enum {
PROP_0,
PROP_MODULE,
- PROP_HANDLE
+ PROP_HANDLE,
+ PROP_REUSE_SESSIONS
};
+typedef struct _GP11SlotPrivate {
+ gboolean reuse_sessions;
+ GHashTable *open_sessions;
+} GP11SlotPrivate;
+
G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT);
+#define GP11_SLOT_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_SLOT, GP11SlotPrivate))
+
+typedef struct _SessionPool {
+ guint flags;
+ GP11Module *module; /* weak */
+ GSList *sessions; /* list of CK_SESSION_HANDLE */
+} SessionPool;
+
+/* ----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static void
+close_session (GP11Module *module, CK_SESSION_HANDLE handle)
+{
+ CK_RV rv;
+
+ g_return_if_fail (GP11_IS_MODULE (module));
+ g_return_if_fail (module->funcs);
+ rv = (module->funcs->C_CloseSession) (handle);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't close session properly: %s",
+ gp11_message_from_rv (rv));
+ }
+}
+
+static void
+free_session_pool (gpointer p)
+{
+ SessionPool *pool = p;
+ GSList *l;
+ for (l = pool->sessions; l; l = g_slist_next (l))
+ close_session (pool->module, GPOINTER_TO_UINT (l->data));
+ g_free (pool);
+}
+
+#ifdef UNUSED
+
+static void
+foreach_count_sessions (gpointer key, gpointer value, gpointer user_data)
+{
+ SessionPool *pool = value;
+ guint *result = user_data;
+ *result += g_slist_length (pool->sessions);
+}
+
+static guint
+count_session_table (GP11Slot *slot, guint flags)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ guint result = 0;
+
+ if (!pv->open_sessions)
+ return 0;
+
+ g_hash_table_foreach (pv->open_sessions, foreach_count_sessions, &result);
+ return result;
+}
+
+#endif /* UNUSED */
+
+static void
+push_session_table (GP11Slot *slot, guint flags, CK_SESSION_HANDLE handle)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ SessionPool *pool;
+
+ if (!pv->open_sessions) {
+ close_session (slot->module, handle);
+ return;
+ }
+
+ g_assert (handle);
+ g_assert (GP11_IS_MODULE (slot->module));
+
+ pool = g_hash_table_lookup (pv->open_sessions, GUINT_TO_POINTER (flags));
+ if (!pool) {
+ pool = g_new0 (SessionPool, 1);
+ pool->flags = flags;
+ pool->module = slot->module; /* weak ref */
+ g_hash_table_insert (pv->open_sessions, GUINT_TO_POINTER (flags), pool);
+ }
+
+ g_assert (pool->flags == flags);
+ pool->sessions = g_slist_prepend (pool->sessions, GUINT_TO_POINTER (handle));
+}
+
+static CK_SESSION_HANDLE
+pop_session_table (GP11Slot *slot, guint flags)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ CK_SESSION_HANDLE result;
+ SessionPool *pool;
+
+ if (!pv->open_sessions)
+ return 0;
+
+ g_assert (GP11_IS_MODULE (slot->module));
+
+ pool = g_hash_table_lookup (pv->open_sessions, GUINT_TO_POINTER (flags));
+ if (!pool)
+ return 0;
+
+ result = GPOINTER_TO_UINT (pool->sessions->data);
+ g_assert (result != 0);
+ pool->sessions = g_slist_remove (pool->sessions, pool->sessions->data);
+
+ return result;
+}
+
+static void
+destroy_session_table (GP11Slot *slot)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ if (pv->open_sessions)
+ g_hash_table_unref (pv->open_sessions);
+ pv->open_sessions = NULL;
+}
+
+static void
+create_session_table (GP11Slot *slot)
+{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (slot);
+ if (!pv->open_sessions)
+ pv->open_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_session_pool);
+}
+
+static void
+reuse_session_handle (GP11Session *session, GP11Slot *slot)
+{
+ CK_SESSION_INFO info;
+ guint flags;
+ CK_RV rv;
+
+ g_return_if_fail (GP11_IS_SESSION (session));
+ g_return_if_fail (GP11_IS_SLOT (slot));
+ g_return_if_fail (GP11_IS_MODULE (slot->module));
+ g_return_if_fail (session->handle != 0);
+
+ /* Get the session info so we know where to categorize this */
+ rv = (slot->module->funcs->C_GetSessionInfo) (session->handle, &info);
+
+ /* An already closed session, we don't want to bother with */
+ if (rv == CKR_SESSION_CLOSED || rv == CKR_SESSION_HANDLE_INVALID) {
+ session->handle = 0;
+ return;
+ }
+
+ /* A strange session, let it go to be closed somewhere else */
+ if (rv != CKR_OK)
+ return;
+
+ /*
+ * Get the flags that this session was opened with originally, and
+ * check them against the session's current flags. If they're no
+ * longer present, then don't reuse this session.
+ */
+ flags = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (session),
+ "gp11-open-session-flags"));
+ if ((flags & info.flags) != flags)
+ return;
+
+ /* Keep this one around for later use */
+ push_session_table (slot, flags, session->handle);
+ session->handle = 0;
+}
+
+static GP11Session*
+make_session_object (GP11Slot *slot, guint flags, CK_SESSION_HANDLE handle)
+{
+ GP11Session *session;
+
+ g_return_val_if_fail (handle != 0, NULL);
+ session = gp11_session_from_handle (slot, handle);
+ g_return_val_if_fail (session != NULL, NULL);
+
+ /* Session keeps a reference to us, so this is safe */
+ g_signal_connect (session, "discard-handle", G_CALLBACK (reuse_session_handle), slot);
+
+ /* Mark the flags on the session for later looking up */
+ g_object_set_data (G_OBJECT (session), "gp11-open-session-flags", GUINT_TO_POINTER (flags));
+
+ return session;
+}
+
/* ----------------------------------------------------------------------------
* OBJECT
*/
@@ -28,6 +220,7 @@
gp11_slot_get_property (GObject *obj, guint prop_id, GValue *value,
GParamSpec *pspec)
{
+ GP11SlotPrivate *pv = GP11_SLOT_GET_PRIVATE (obj);
GP11Slot *slot = GP11_SLOT (obj);
switch (prop_id) {
@@ -37,6 +230,9 @@
case PROP_HANDLE:
g_value_set_uint (value, slot->handle);
break;
+ case PROP_REUSE_SESSIONS:
+ g_value_set_boolean (value, pv->open_sessions != NULL);
+ break;
}
}
@@ -57,6 +253,12 @@
g_return_if_fail (!slot->handle);
slot->handle = g_value_get_uint (value);
break;
+ case PROP_REUSE_SESSIONS:
+ if (g_value_get_boolean (value))
+ create_session_table (slot);
+ else
+ destroy_session_table (slot);
+ break;
}
}
@@ -64,7 +266,10 @@
gp11_slot_dispose (GObject *obj)
{
GP11Slot *slot = GP11_SLOT (obj);
-
+
+ /* Need to do this before the module goes away */
+ destroy_session_table (slot);
+
if (slot->module)
g_object_unref (slot->module);
slot->module = NULL;
@@ -102,6 +307,12 @@
g_object_class_install_property (gobject_class, PROP_HANDLE,
g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_REUSE_SESSIONS,
+ g_param_spec_boolean ("reuse-sessions", "Reuse Sessions", "Reuse sessions?",
+ FALSE, G_PARAM_READWRITE));
+
+ g_type_class_add_private (gobject_class, sizeof (GP11SlotPrivate));
}
/* ----------------------------------------------------------------------------
@@ -138,6 +349,20 @@
g_free (mech_info);
}
+gboolean
+gp11_slot_get_reuse_sessions (GP11Slot *slot)
+{
+ gboolean reuse = FALSE;
+ g_object_get (slot, "reuse-sessions", &reuse, NULL);
+ return reuse;
+}
+
+void
+gp11_slot_set_reuse_sessions (GP11Slot *slot, gboolean reuse)
+{
+ g_object_set (slot, "reuse-sessions", reuse, NULL);
+}
+
GP11SlotInfo*
gp11_slot_get_info (GP11Slot *slot)
{
@@ -365,11 +590,18 @@
gp11_slot_open_session_full (GP11Slot *slot, guint flags, GCancellable *cancellable, GError **err)
{
OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 };
+ CK_SESSION_HANDLE handle;
+
+ /* Try to use a cached session */
+ handle = pop_session_table (slot, flags);
+ if (handle != 0)
+ return make_session_object (slot, flags, handle);
+ /* Open a new session */
if (!_gp11_call_sync (slot, perform_open_session, &args, cancellable, err))
return FALSE;
- return gp11_session_from_handle (slot, args.session);
+ return make_session_object (slot, flags, args.session);
}
void
@@ -379,10 +611,14 @@
OpenSession *args = _gp11_call_async_prep (slot, perform_open_session,
sizeof (*args), NULL);
+ /* Try to use a cached session */
+ args->session = pop_session_table (slot, flags);
args->flags = flags;
- args->session = 0;
- _gp11_call_async_go (args, cancellable, callback, user_data);
+ if (args->session)
+ _gp11_call_async_short (args, callback, user_data);
+ else
+ _gp11_call_async_go (args, cancellable, callback, user_data);
}
GP11Session*
@@ -394,43 +630,5 @@
return NULL;
args = _gp11_call_arguments (result, OpenSession);
- return gp11_session_from_handle (slot, args->session);
-}
-
-#if UNIMPLEMENTED
-
-static CK_RV
-perform_close_all_sessions (GP11Arguments *args)
-{
- return (args->pkcs11->C_CloseAllSessions) (args->handle);
-}
-
-gboolean
-gp11_slot_close_all_sessions (GP11Slot *slot, GError **err)
-{
- return gp11_slot_close_all_sessions_full (slot, NULL, err);
+ return make_session_object (slot, args->flags, args->session);
}
-
-gboolean
-gp11_slot_close_all_sessions_full (GP11Slot *slot, GCancellable *cancellable, GError **err)
-{
- GP11Arguments args = GP11_ARGUMENTS_INIT;
- return _gp11_call_sync (slot, perform_close_all_sessions, &args, cancellable, err);
-}
-
-void
-gp11_slot_close_all_sessions_async (GP11Slot *slot, GCancellable *cancellable,
- GAsyncReadyCallback callback, gpointer user_data)
-{
- GP11Arguments *args = _gp11_call_async_prep (slot, perform_close_all_sessions, 0, NULL);
- _gp11_call_async_go (args, cancellable, callback, user_data);
-}
-
-gboolean
-gp11_slot_close_all_sessions_finish (GP11Slot *slot, GAsyncResult *result,
- GError **err)
-{
- return _gp11_call_basic_finish (slot, result, err);
-}
-
-#endif
Modified: trunk/gp11/gp11.h
==============================================================================
--- trunk/gp11/gp11.h (original)
+++ trunk/gp11/gp11.h Sat Jul 19 21:53:39 2008
@@ -302,6 +302,11 @@
GType gp11_slot_get_type (void) G_GNUC_CONST;
+gboolean gp11_slot_get_reuse_sessions (GP11Slot *slot);
+
+void gp11_slot_set_reuse_sessions (GP11Slot *slot,
+ gboolean reuse);
+
GP11SlotInfo* gp11_slot_get_info (GP11Slot *slot);
GP11TokenInfo* gp11_slot_get_token_info (GP11Slot *slot);
@@ -378,11 +383,13 @@
GObject parent;
GP11Module *module;
- CK_SLOT_ID handle;
+ CK_SESSION_HANDLE handle;
};
struct _GP11SessionClass {
GObjectClass parent;
+
+ void (*discard_handle) (GP11Session *session);
};
GType gp11_session_get_type (void) G_GNUC_CONST;
Modified: trunk/gp11/gp11.pc.in
==============================================================================
--- trunk/gp11/gp11.pc.in (original)
+++ trunk/gp11/gp11.pc.in Sat Jul 19 21:53:39 2008
@@ -9,6 +9,6 @@
Name: gp11
Description: GObject bindings for PKCS#11
Version: @GP11_MAJOR@
-Requires: gconf-2.0
+Requires: glib-2.0
Libs: -L${libdir} -lgp11
Cflags: -I${includedir}/gp11
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]