[Gpa-commits] r956 - in trunk: . src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Feb 27 11:06:30 CET 2009


Author: werner
Date: 2009-02-27 11:06:24 +0100 (Fri, 27 Feb 2009)
New Revision: 956

Modified:
   trunk/NEWS
   trunk/src/ChangeLog
   trunk/src/cardman.c
   trunk/src/filewatch.c
Log:
Use a ticker to reload the card.


Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2009-02-26 18:57:16 UTC (rev 955)
+++ trunk/NEWS	2009-02-27 10:06:24 UTC (rev 956)
@@ -1,5 +1,7 @@
-Noteworthy changes in version 0.8.1
+Noteworthy changes in version 0.9.0
 ------------------------------------------------
+ 
+ * Add a basic smartcard manager and the option --card.
 
 
 Noteworthy changes in version 0.8.0 (2008-09-04)

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2009-02-26 18:57:16 UTC (rev 955)
+++ trunk/src/ChangeLog	2009-02-27 10:06:24 UTC (rev 956)
@@ -1,3 +1,13 @@
+2009-02-27  Werner Koch  <wk at g10code.com>
+
+	* filewatch.c: Remove debug output.
+
+	* cardman.c (struct _GpaCardManager): Add TICKER_TIMEOUT_ID and
+	EVENTCOUNTER.
+	(geteventcounter_status_cb, ticker_cb, start_ticker): New.
+	(gpa_card_manager_finalize): Remove the ticker.
+	(card_reload): Start the ticker and update the evntcounter.
+
 2009-02-26  Werner Koch  <wk at g10code.com>
 
 	* cm-object.c (gpa_cm_object_class_init): Register "update-status"

Modified: trunk/src/cardman.c
===================================================================
--- trunk/src/cardman.c	2009-02-26 18:57:16 UTC (rev 955)
+++ trunk/src/cardman.c	2009-02-27 10:06:24 UTC (rev 956)
@@ -81,6 +81,15 @@
   gpgme_ctx_t gpgagent;      /* Gpgme context for the assuan
                                 connection with the gpg-agent.  */
 
+
+  guint ticker_timeout_id;   /* Source Id of the timeout ticker or 0.  */
+
+
+  struct {
+    int card_any;           /* Any card event counter seen.  */
+    unsigned int card;      /* Last seen card event counter.  */      
+  } eventcounter;
+
 };
 
 /* There is only one instance of the card manager class.  Use a global
@@ -89,6 +98,7 @@
 
 
 /* Local prototypes */
+static void start_ticker (GpaCardManager *cardman);
 static void update_card_widget (GpaCardManager *cardman);
 
 static void gpa_card_manager_finalize (GObject *object);
@@ -228,7 +238,17 @@
         cardman->cardtypename = "Unknown";
 
     }
+  else if ( !strcmp (status, "EVENTCOUNTER") )
+    {
+      unsigned int count;
 
+      if (sscanf (args, "%*u %*u %u ", &count) == 1)
+        {
+          cardman->eventcounter.card_any = 1;
+          cardman->eventcounter.card = count;
+        }
+    }
+
   return 0;
 }     
 
@@ -242,6 +262,9 @@
 
   if (!cardman->gpgagent)
     return;  /* No support for GPGME_PROTOCOL_ASSUAN.  */
+
+  /* Start the ticker if not yet done.  */
+  start_ticker (cardman);
     
   if (!cardman->in_card_reload)
     {
@@ -276,6 +299,14 @@
  
       if (!err)
         {
+          /* Get the event counter to avoid a duplicate reload due to
+             the ticker.  */
+          gpgme_op_assuan_transact (cardman->gpgagent,
+                                    "GETEVENTCOUNTER",
+                                    NULL, NULL,
+                                    NULL, NULL,
+                                    scd_status_cb, cardman);
+
           /* Now we need to get the APPTYPE of the card so that the
              correct GpaCM* object can can act on the data.  */
           command = "SCD GETATTR APPTYPE";
@@ -296,6 +327,7 @@
               statusbar_update (cardman, _("Error accessing card"));
             }
         }
+
       
       update_card_widget (cardman);
       update_title (cardman);
@@ -334,6 +366,79 @@
 }
 
 
+static gpg_error_t
+geteventcounter_status_cb (void *opaque, const char *status, const char *args)
+{
+  GpaCardManager *cardman = opaque;
+
+  if ( !strcmp (status, "EVENTCOUNTER") )
+    {
+      unsigned int count;
+
+      /* We don't check while we are already reloading a card.  The
+         last action of the card reload code will also update the
+         event counter.  */
+      if (!cardman->in_card_reload
+          && sscanf (args, "%*u %*u %u ", &count) == 1)
+        {
+          if (cardman->eventcounter.card_any
+              && cardman->eventcounter.card != count)
+            {
+              /* Actually we should not do a reload based only on the
+                 eventcounter but check the actual card status first.
+                 However simply triggering a reload is not different
+                 from the user hitting the reload button.  */
+              g_object_ref (cardman);
+              g_idle_add (card_reload_idle_cb, cardman);
+            }
+          cardman->eventcounter.card_any = 1;
+          cardman->eventcounter.card = count;
+        }
+    }
+
+  return 0;
+}
+
+/* This fucntion is called by the timerout ticker started by
+   start_ticker.  It is used to poll scdaemon to detect a card status
+   change.  */
+static gboolean
+ticker_cb (gpointer user_data)
+{
+  GpaCardManager *cardman = user_data;
+
+  if (!cardman || !cardman->ticker_timeout_id || !cardman->gpgagent)
+    return TRUE;  /* Keep on ticking.  */
+  
+  /* Note that we are single threaded and thus there is no need to
+     lock the assuan context.  */
+
+  gpgme_op_assuan_transact (cardman->gpgagent,
+                            "GETEVENTCOUNTER",
+                            NULL, NULL,
+                            NULL, NULL,
+                            geteventcounter_status_cb, cardman);
+
+  return TRUE;  /* Keep on ticking.  */
+}
+
+
+/* If no ticker is active start one.  */
+static void
+start_ticker (GpaCardManager *cardman)
+{
+  if (!cardman->ticker_timeout_id)
+    {
+#if GTK_CHECK_VERSION (2, 14, 0)
+      cardman->ticker_timeout_id = g_timeout_add_seconds (1,
+                                                          ticker_cb, cardman); 
+#else
+      cardman->ticker_timeout_id = g_timeout_add (1000, ticker_cb, cardman); 
+#endif
+    }
+}
+
+
 /* Signal handler for the completed signal of the key generation. */
 static void
 card_genkey_completed (GpaCardManager *cardman, gpg_error_t err)
@@ -398,11 +503,6 @@
 
   if (cardman && strchr (reason, 'w') )
     {
-/*       reader_status_t reader_status; */
-
-/*       reader_status = reader_status_from_file (filename); */
-/*       if (reader_status == READER_STATUS_PRESENT) */
-/* 	statusbar_update (cardman, _("Reloading card data...")); */
       card_reload (cardman);
     }
 }
@@ -655,6 +755,9 @@
                     G_CALLBACK (card_manager_closed), cardman);
 
 
+  /* We use the file watcher to speed up card change detection.  If it
+     does not work (i.e. on non Linux based systems) the ticker takes
+     care of it.  */
   fname = g_build_filename (gnupg_homedir, "reader_0.status", NULL);
   cardman->watch = gpa_add_filewatch (fname, "w", watcher_cb, cardman);
   xfree (fname);
@@ -684,6 +787,12 @@
 
   gpgme_release (cardman->gpgagent);
   cardman->gpgagent = NULL;
+  
+  if (cardman->ticker_timeout_id)
+    {
+      g_source_remove (cardman->ticker_timeout_id);
+      cardman->ticker_timeout_id = 0;
+    }
 
   /* FIXME: Remove the watch object and all other resources.  */
 

Modified: trunk/src/filewatch.c
===================================================================
--- trunk/src/filewatch.c	2009-02-26 18:57:16 UTC (rev 955)
+++ trunk/src/filewatch.c	2009-02-27 10:06:24 UTC (rev 956)
@@ -81,7 +81,7 @@
                status, err->message);
       g_error_free (err);
     }
-  g_debug ("new file watch event, nread=%u", (unsigned int)nread);
+/*   g_debug ("new file watch event, nread=%u", (unsigned int)nread); */
   
   if (status == G_IO_STATUS_NORMAL)
     {
@@ -116,9 +116,9 @@
           MAKEREASON ('x', IN_IGNORED);
 #undef MAKEREASON
           reason[reasonidx] = 0;
-          g_debug ("event: wd=%d mask=%#x (%s) cookie=%#x len=%u name=`%.*s'",
-                   ev->wd, ev->mask, reason, ev->cookie, ev->len, 
-                   (int)ev->len, ev->name);
+/*           g_debug ("event: wd=%d mask=%#x (%s) cookie=%#x len=%u name=`%.*s'", */
+/*                    ev->wd, ev->mask, reason, ev->cookie, ev->len,  */
+/*                    (int)ev->len, ev->name); */
 
           walking_watch_list_p++;
           for (watch=watch_list; watch; watch = watch->next)



More information about the Gpa-commits mailing list