gnome-keyring r1183 - in trunk: . gp11



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]