Chnaged the op-assuan interface.
authorWerner Koch <wk@gnupg.org>
Tue, 24 Feb 2009 15:13:01 +0000 (15:13 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 24 Feb 2009 15:13:01 +0000 (15:13 +0000)
NEWS
assuan/ChangeLog
assuan/assuan-buffer.c
src/ChangeLog
src/engine-assuan.c
src/gpgme.h.in
src/opassuan.c
tests/ChangeLog
tests/opassuan/t-command.c

diff --git a/NEWS b/NEWS
index c2b812a739b190585a958fbeecfd908cd2b4938d..3999bbb2d9b9ae991932418ccbe7c4a18e41ba52 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,7 +5,6 @@ Noteworthy changes in version 1.1.9
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  GPGME_PROTOCOL_ASSUAN          NEW.
  gpgme_assuan_data_cb_t         NEW.
- gpgme_assuan_sendfnc_ctx_t     NEW.
  gpgme_assuan_inquire_cb_t      NEW.
  gpgme_assuan_status_cb_t       NEW.
  gpgme_op_assuan_transact_start NEW.
index cc39213ce01d6f56cafcc57c28f5130461c78e7d..e620d205c7cd8460d407bf0258b5aacdd72d9560 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-24  Werner Koch  <wk@g10code.com>
+
+       * assuan-buffer.c (assuan_send_data): Add hack to optionally send
+       a final "CAN".
+
 2008-11-03  Marcus Brinkmann  <marcus@g10code.com>
 
        * Makefile.am (INCLUDES): Replace gpgme path with src.
index 1fad0b5e8f79f6ec1edbafc2e047c1d46df90884..31f339456c97dc3493041f2b1491cce15e56849a 100644 (file)
@@ -491,6 +491,9 @@ _assuan_cookie_write_flush (void *cookie)
  * a INQUIRE response.  However, when assuan_transact() is used, this
  * function takes care of sending END itself.
  * 
+ * If BUFFER is NULL and LENGTH is 1 and we are a client, a "CAN" is
+ * send instead of an "END".
+ * 
  * Return value: 0 on success or an error code
  **/
 \f
@@ -499,7 +502,7 @@ assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
 {
   if (!ctx)
     return _assuan_error (ASSUAN_Invalid_Value);
-  if (!buffer && length)
+  if (!buffer && length > 1)
     return _assuan_error (ASSUAN_Invalid_Value);
 
   if (!buffer)
@@ -508,7 +511,7 @@ assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
       if (ctx->outbound.data.error)
         return ctx->outbound.data.error;
       if (!ctx->is_server)
-        return assuan_write_line (ctx, "END");
+        return assuan_write_line (ctx, length == 1? "CAN":"END");
     }
   else
     {
index 1cd86436814a915fe7b3bac3d9a7a574fd129a24..f78cb11ede567edaf656893db9b20ce86b832f27 100644 (file)
@@ -1,3 +1,20 @@
+2009-02-24  Werner Koch  <wk@g10code.com>
+
+       * gpgme.h.in (struct _gpgme_op_assuan_result): New.
+       (gpgme_assuan_result_t): New.
+       (gpgme_op_assuan_result): Change return type.
+       (struct _gpgme_assuan_sendfnc_ctx)
+       (gpgme_assuan_sendfnc_ctx_t, gpgme_assuan_sendfnc_t):Remove.
+       (gpgme_assuan_inquire_cb_t): Changed.
+       * opassuan.c (op_data_t): Make use of a result structure.
+       (gpgme_op_assuan_result): Change return type.
+       (opassuan_start): Use result structure.
+       (result_cb): Ditto.
+       * engine-assuan.c (struct _gpgme_assuan_sendfnc_ctx): Remove.
+       (inquire_cb_sendfnc): Remove.
+       (inquire_cb): Change for new callback scheme.  Not yet finished.
+       (llass_status_handler): Allow sending a CANCEL from the inquire CB.
+
 2009-02-04  Werner Koch  <wk@g10code.com>
 
        * w32-glib-io.c (_gpgme_io_spawn): Make ARGV argument const to
index fb74868988cbbf7245a4738c7753db049ee721ca..bfe7a037364672dae9979cb0531c1f096e9cea37 100644 (file)
@@ -94,12 +94,6 @@ struct engine_llass
 };
 typedef struct engine_llass *engine_llass_t;
 
-/* Helper to pass data to a callback.  */
-struct _gpgme_assuan_sendfnc_ctx
-{
-  assuan_context_t assuan_ctx;
-};
-
 
 
 /* Prototypes.  */
@@ -212,6 +206,8 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
     {
       home_dir++;
       /* Very simple parser only working for the one option we support.  */
+      /* Note that wk promised to write a regression test if this
+         parser will be extended.  */
       if (!strncmp (home_dir, "GPG_AGENT", 9) 
           && (!home_dir[9] || home_dir[9] == ' '))
         llass->opt.gpg_agent = 1;
@@ -372,18 +368,6 @@ llass_set_locale (void *engine, int category, const char *value)
 }
 
 
-
-static gpgme_error_t
-inquire_cb_sendfnc (gpgme_assuan_sendfnc_ctx_t ctx,
-                    const void *data, size_t datalen)
-{
-  if (data && datalen)
-    return assuan_send_data (ctx->assuan_ctx, data, datalen);
-  else
-    return 0;  /* Don't allow an inquire to send a flush.  */
-}
-
-
 /* This is the inquiry callback.  It handles stuff which ee need to
    handle here and passes everything on to the user callback.  */
 static gpgme_error_t
@@ -398,12 +382,18 @@ inquire_cb (engine_llass_t llass, const char *keyword, const char *args)
 
   if (llass->user.inq_cb)
     {
-      struct _gpgme_assuan_sendfnc_ctx sendfnc_ctx;
+      gpgme_data_t data = NULL;
 
-      sendfnc_ctx.assuan_ctx = llass->assuan_ctx;
       err = llass->user.inq_cb (llass->user.inq_cb_value,
-                                keyword, args,
-                                inquire_cb_sendfnc, &sendfnc_ctx);
+                                keyword, args, &data);
+      if (!err && data)
+        {
+          /* FIXME: Returning data is not yet implemented.  However we
+             need to allow the caller to cleanup his data object.
+             Thus we run the callback in finish mode immediately.  */
+          err = llass->user.inq_cb (llass->user.inq_cb_value,
+                                    NULL, NULL, &data);
+        }
     }
   else
     err = 0;
@@ -528,8 +518,16 @@ llass_status_handler (void *opaque, int fd)
             args++;
 
           err = inquire_cb (llass, src, args);
-          if (!err) /* Flush and send END.  */
-            err = assuan_send_data (llass->assuan_ctx, NULL, 0);
+          if (!err) 
+            {
+              /* Flush and send END.  */
+              err = assuan_send_data (llass->assuan_ctx, NULL, 0);
+            }
+          else if (gpg_err_code (err) == GPG_ERR_ASS_CANCELED)
+            {
+              /* Flush and send CANcel.  */
+              err = assuan_send_data (llass->assuan_ctx, NULL, 1);
+            }
         }
       else if (linelen >= 3
               && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
index e83b1fb14a0b312504aac86d89d5931273297e3e..2538aaf9866056243dc2e3a422fec341e71b3d11 100644 (file)
@@ -1671,21 +1671,24 @@ gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output,
 typedef gpgme_error_t (*gpgme_assuan_data_cb_t) 
      (void *opaque, const void *data, size_t datalen);
 
-struct _gpgme_assuan_sendfnc_ctx;
-typedef struct _gpgme_assuan_sendfnc_ctx *gpgme_assuan_sendfnc_ctx_t;
-typedef gpgme_error_t (*gpgme_assuan_sendfnc_t)
-     (gpgme_assuan_sendfnc_ctx_t ctx, const void *data, size_t datalen);
-
 typedef gpgme_error_t (*gpgme_assuan_inquire_cb_t)
      (void *opaque, const char *name, const char *args,
-      gpgme_assuan_sendfnc_t sendfnc, 
-      gpgme_assuan_sendfnc_ctx_t sendfnc_ctx);
+      gpgme_data_t *r_data);
 
 typedef gpgme_error_t (*gpgme_assuan_status_cb_t)
      (void *opaque, const char *status, const char *args);
 
+struct _gpgme_op_assuan_result
+{
+  /* The result of the actual assuan command.  An OK is indicated by a
+     value of 0 and an ERR by the respective error error value.  */
+  gpgme_error_t err;
+};
+typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
+
+
 /* Return the result of the last Assuan command. */
-gpgme_error_t gpgme_op_assuan_result (gpgme_ctx_t ctx);
+gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx);
 
 /* Send the Assuan COMMAND and return results via the callbacks.
    Asynchronous variant. */
index f07dade6bd3ba1bba0d5dc0d41389bb931e048a1..09f69ee84e33b79243026c6556028a3a411d1a16 100644 (file)
 #include "ops.h"
 #include "util.h"
 
+
 typedef struct
 {
-  /* The result of the assuan command with 0 for OK and an error value
-     for ERR.  */
-  gpgme_error_t result;
+  struct _gpgme_op_assuan_result result;
+
 } *op_data_t;
 
 
@@ -55,12 +55,12 @@ result_cb (void *priv, gpgme_error_t result)
   if (!opd)
     return gpg_error (GPG_ERR_INTERNAL);
 
-  opd->result = result;
+  opd->result.err = result;
   return 0;
 }
 
 
-gpgme_error_t
+gpgme_assuan_result_t
 gpgme_op_assuan_result (gpgme_ctx_t ctx)
 {
   gpgme_error_t err;
@@ -69,12 +69,12 @@ gpgme_op_assuan_result (gpgme_ctx_t ctx)
 
   err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
   opd = hook;
-  if (err)
-    return err;
-  if (!opd)
-    return gpg_error (GPG_ERR_INTERNAL);
+  /* Check in case this function is used without having run a command
+     before.  */
+  if (err || !opd)
+    return NULL;
 
-  return opd->result;
+  return &opd->result;
 }
 
 
@@ -105,7 +105,7 @@ opassuan_start (gpgme_ctx_t ctx, int synchronous,
   opd = hook;
   if (err)
     return err;
-  opd->result = gpg_error (GPG_ERR_UNFINISHED);
+  opd->result.err = gpg_error (GPG_ERR_UNFINISHED);
 
   return _gpgme_engine_op_assuan_transact (ctx->engine, command,
                                            result_cb, ctx,
index efd756c456ecc26d56f51dd12e67c8c96c6a95fe..027afccf4095167abdafe81431b2ae22ef5f30a9 100644 (file)
@@ -1,3 +1,7 @@
+2009-02-24  Werner Koch  <wk@g10code.com>
+
+       * opassuan/t-command.c: Adjust for changed new op_assuan interface.
+
 2009-02-03  Werner Koch  <wk@g10code.com>
 
        * gpg/t-keylist.c (main): Check that new fields is_cardkey and
index b6a2d904adbd895f6694ba2a68b9d9eec8d1b30c..161b8a84b7c5affc3a555137dd492ffed60b99b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <locale.h>
+#include <assert.h>
 
 #include <gpgme.h>
 
@@ -52,10 +53,36 @@ data_cb (void *opaque, const void *data, size_t datalen)
 
 static gpg_error_t
 inq_cb (void *opaque, const char *name, const char *args,
-        gpgme_assuan_sendfnc_t sendfnc,
-        gpgme_assuan_sendfnc_ctx_t sendfnc_value)
+        gpgme_data_t *r_data)
 {
-  printf ("INQ_CB: name=`%s' args=`%s'\n", name, args);
+  gpgme_data_t data;
+  gpg_error_t err;
+
+  if (name)
+    {
+      printf ("INQ_CB: name=`%s' args=`%s'\n", name, args);
+      /* There shall be no data object.  */
+      assert (!*r_data);
+      
+      err = gpgme_data_new (&data);
+      fail_if_err (err);
+      *r_data = data;
+      printf ("        sending data object %p\n", data);
+    }
+  else /* Finished using the formerly returned data object.  */
+    {
+      printf ("INQ_CB: data object %p finished\n", *r_data);
+      /* There shall be a data object so that it can be cleaned up. */
+      assert (r_data);
+
+      gpgme_data_release (*r_data);
+    }
+
+  /* Uncomment the next lines and send a "SCD LEARN" to test sending
+     cancel from in inquiry.  */
+  /* if (name && !strcmp (name, "KNOWNCARDP")) */
+  /*   return gpg_error (GPG_ERR_ASS_CANCELED); */
+
 
   return 0;
 }     
@@ -70,9 +97,6 @@ status_cb (void *opaque, const char *status, const char *args)
 
 
 
-
-
-
 int 
 main (int argc, char **argv)
 {
@@ -106,7 +130,7 @@ main (int argc, char **argv)
                                   inq_cb, NULL,
                                   status_cb, NULL);
   fail_if_err (err);
-  err = gpgme_op_assuan_result (ctx);
+  err = gpgme_op_assuan_result (ctx)->err;
   if (err)
     fprintf (stderr, "assuan command `%s' failed: %s <%s> (%d)\n", 
              command, gpg_strerror (err), gpg_strsource (err), err);