diff options
| author | Christian Grothoff <christian@grothoff.org> | 2016-01-25 11:08:19 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2016-01-25 11:08:19 +0100 | 
| commit | ccb4ac92a3e69d26e6c04b10b407f5491eda7001 (patch) | |
| tree | 99cff6ba9c5bb2a7b1725b1a852d9ef8bc28291c | |
| parent | 941cb8182f052bbd6344ba7daf91f3aa792027bd (diff) | |
more work on wire plugin
| -rw-r--r-- | configure.ac | 1 | ||||
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/include/taler_bank_service.h | 1 | ||||
| -rw-r--r-- | src/wire/Makefile.am | 1 | ||||
| -rw-r--r-- | src/wire/plugin_wire_test.c | 287 | 
5 files changed, 273 insertions, 19 deletions
| diff --git a/configure.ac b/configure.ac index 8f06b520..95457e5b 100644 --- a/configure.ac +++ b/configure.ac @@ -357,6 +357,7 @@ AC_CONFIG_FILES([Makefile                   src/include/Makefile                   src/util/Makefile                   src/pq/Makefile +                 src/bank-lib/Makefile                   src/wire/Makefile                   src/mintdb/Makefile                   src/mint/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 986dcc5d..ac839d52 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ if WALLET_ONLY  SUBDIRS = include util  else -SUBDIRS = include util $(PQ_DIR) wire mintdb mint mint-tools +SUBDIRS = include util $(PQ_DIR) bank-lib wire mintdb mint mint-tools  if HAVE_LIBCURL   SUBDIRS += mint-lib  else diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h index b19e213a..b292a7bc 100644 --- a/src/include/taler_bank_service.h +++ b/src/include/taler_bank_service.h @@ -16,6 +16,7 @@  /**   * @file include/taler_bank_service.h   * @brief C interface of libtalerbank, a C library to use the Taler bank's HTTP API + *        This is currently ONLY used to provide the "test" wire transfer protocol.   * @author Christian Grothoff   */  #ifndef _TALER_BANK_SERVICE_H diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am index a27a59c7..64f50d97 100644 --- a/src/wire/Makefile.am +++ b/src/wire/Makefile.am @@ -21,6 +21,7 @@ libtaler_plugin_wire_test_la_LIBADD = \    $(LTLIBINTL)  libtaler_plugin_wire_test_la_LDFLAGS = \    $(TALER_PLUGIN_LDFLAGS) \ +  $(top_builddir)/src/bank-lib/libtalerbank.la \    $(top_builddir)/src/util/libtalerutil.la \    -lgnunetutil $(XLIB) diff --git a/src/wire/plugin_wire_test.c b/src/wire/plugin_wire_test.c index 1ea856fd..917cf09b 100644 --- a/src/wire/plugin_wire_test.c +++ b/src/wire/plugin_wire_test.c @@ -17,13 +17,14 @@  /**   * @file plugin_wire_test.c   * @brief plugin for the "test" wire method - * @author Florian Dold   * @author Christian Grothoff - * @author Sree Harsha Totakura   */  #include "platform.h"  #include "taler_wire_plugin.h" +#include "taler_bank_service.h" +/* only for HTTP status codes */ +#include <microhttpd.h>  /**   * Type of the "cls" argument given to each of the functions in @@ -33,19 +34,165 @@ struct TestClosure  {    /** -   * URI of the bank for sending funds to the bank. +   * Handle to the bank for sending funds to the bank.     */ -  char *bank_uri; +  struct TALER_BANK_Context *bank;    /**     * Which currency do we support?     */    char *currency; +  /** +   * Handle to the bank task, or NULL. +   */ +  struct GNUNET_SCHEDULER_Task *bt; + +}; + + +/** + * Handle returned by #test_prepare_wire_transfer. + */ +struct TALER_WIRE_PrepareHandle +{ + +  /** +   * Task we use for async execution. +   */ +  struct GNUNET_SCHEDULER_Task *task; + +  /** +   * Test closure we run in. +   */ +  struct TestClosure *tc; + +  /** +   * Wire data for the transfer. +   */ +  json_t *wire; + +  /** +   * Function to call with the serialized data. +   */ +  TALER_WIRE_PrepareTransactionCallback ptc; + +  /** +   * Closure for @e ptc. +   */ +  void *ptc_cls; + +  /** +   * Amount to transfer. +   */ +  struct TALER_Amount amount; + +  /** +   * Subject of the wire transfer. +   */ +  struct TALER_WireTransferIdentifierRawP wtid; + +  };  /** + * Handle returned by #test_execute_wire_transfer. + */ +struct TALER_WIRE_ExecuteHandle +{ + +  /** +   * Handle to the HTTP request to the bank. +   */ +  struct TALER_BANK_AdminAddIncomingHandle *aaih; + +  /** +   * Function to call with the result. +   */ +  TALER_WIRE_ConfirmationCallback cc; + +  /** +   * Closure for @e cc. +   */ +  void *cc_cls; +}; + + +/** + * Task that runs the bank's context's event loop with the GNUnet + * scheduler. + * + * @param cls our `struct TestClosure` + * @param tc scheduler context (unused) + */ +static void +context_task (void *cls, +              const struct GNUNET_SCHEDULER_TaskContext *sct) +{ +  struct TestClosure *tc = cls; +  long timeout; +  int max_fd; +  fd_set read_fd_set; +  fd_set write_fd_set; +  fd_set except_fd_set; +  struct GNUNET_NETWORK_FDSet *rs; +  struct GNUNET_NETWORK_FDSet *ws; +  struct GNUNET_TIME_Relative delay; + +  tc->bt = NULL; +  TALER_BANK_perform (tc->bank); +  max_fd = -1; +  timeout = -1; +  FD_ZERO (&read_fd_set); +  FD_ZERO (&write_fd_set); +  FD_ZERO (&except_fd_set); +  TALER_BANK_get_select_info (tc->bank, +                              &read_fd_set, +                              &write_fd_set, +                              &except_fd_set, +                              &max_fd, +                              &timeout); +  if (timeout >= 0) +    delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, +                                           timeout); +  else +    delay = GNUNET_TIME_UNIT_FOREVER_REL; +  rs = GNUNET_NETWORK_fdset_create (); +  GNUNET_NETWORK_fdset_copy_native (rs, +                                    &read_fd_set, +                                    max_fd + 1); +  ws = GNUNET_NETWORK_fdset_create (); +  GNUNET_NETWORK_fdset_copy_native (ws, +                                    &write_fd_set, +                                    max_fd + 1); +  tc->bt = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, +                                        delay, +                                        rs, +                                        ws, +                                        &context_task, +                                        cls); +  GNUNET_NETWORK_fdset_destroy (rs); +  GNUNET_NETWORK_fdset_destroy (ws); +} + + +/** + * Run the bank task now. + * + * @param tc context for which we should initiate running the task + */ +static void +run_bt (struct TestClosure *tc) +{ +  if (NULL != tc->bt) +    GNUNET_SCHEDULER_cancel (tc->bt); +  tc->bt = GNUNET_SCHEDULER_add_now (&context_task, +                                     tc); +} + + +/**   * Round amount DOWN to the amount that can be transferred via the wire   * method.  For example, Taler may support 0.000001 EUR as a unit of   * payment, but SEPA only supports 0.01 EUR.  This function would @@ -94,7 +241,33 @@ test_wire_validate (const json_t *wire)  /** - * Prepare for exeuction of a wire transfer. + * Prepare for exeuction of a wire transfer.  Calls the + * callback with the serialized state. + * + * @param cls the `struct TALER_WIRE_PrepareHandle` + * @param sct unused + */ +static void +do_prepare (void *cls, +            const struct GNUNET_SCHEDULER_TaskContext *sct) +{ +  struct TALER_WIRE_PrepareHandle *pth = cls; +  char buf[42]; // FIXME: init: serialize buf! + +  pth->task = NULL; +  pth->ptc (pth->ptc_cls, +            buf, +            sizeof (buf)); +  GNUNET_free (pth); +} + + +/** + * Prepare for exeuction of a wire transfer.  Note that we should call + * @a ptc asynchronously (as that is what the API requires, because + * some transfer methods need it).  So while we could immediately call + * @a ptc, we first bundle up all the data and schedule a task to do + * the work.   *   * @param cls the @e cls of this struct with the plugin-specific state   * @param wire valid wire account information @@ -112,8 +285,20 @@ test_prepare_wire_transfer (void *cls,                              TALER_WIRE_PrepareTransactionCallback ptc,                              void *ptc_cls)  { -  GNUNET_break (0); -  return NULL; +  struct TestClosure *tc = cls; +  struct TALER_WIRE_PrepareHandle *pth; + +  pth = GNUNET_new (struct TALER_WIRE_PrepareHandle); +  pth->tc = tc; +  pth->wire = (json_t *) wire; +  json_incref (pth->wire); +  pth->wtid = *wtid; +  pth->ptc = ptc; +  pth->ptc_cls = ptc_cls; +  pth->amount = *amount; +  pth->task = GNUNET_SCHEDULER_add_now (&do_prepare, +                                        pth); +  return pth;  } @@ -128,7 +313,36 @@ static void  test_prepare_wire_transfer_cancel (void *cls,                                     struct TALER_WIRE_PrepareHandle *pth)  { -  GNUNET_break (0); +  GNUNET_SCHEDULER_cancel (pth->task); +  json_decref (pth->wire); +  GNUNET_free (pth); +} + + +/** + * Called with the result of submitting information about an incoming + * transaction to a bank. + * + * @param cls closure with the `struct TALER_WIRE_ExecuteHandle` + * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request + *                    0 if the bank's reply is bogus (fails to follow the protocol) + */ +static void +execute_cb (void *cls, +            unsigned int http_status) +{ +  struct TALER_WIRE_ExecuteHandle *eh = cls; +  char s[14]; + +  eh->aaih = NULL; +  GNUNET_snprintf (s, +                   sizeof (s), +                   "%u", +                   http_status); +  eh->cc (eh->cc_cls, +          (MHD_HTTP_OK == http_status) ? GNUNET_OK : GNUNET_SYSERR, +          (MHD_HTTP_OK == http_status) ? NULL : s); +  GNUNET_free (eh);  } @@ -149,8 +363,32 @@ test_execute_wire_transfer (void *cls,                              TALER_WIRE_ConfirmationCallback cc,                              void *cc_cls)  { -  GNUNET_break (0); -  return NULL; +  struct TestClosure *tc = cls; +  struct TALER_WIRE_ExecuteHandle *eh; +  json_t *wire; +  struct TALER_Amount amount; +  struct TALER_WireTransferIdentifierRawP wtid; + +  /* FIXME: deserialize buf */ +  wire = NULL; + +  eh = GNUNET_new (struct TALER_WIRE_ExecuteHandle); +  eh->cc = cc; +  eh->cc_cls = cc_cls; +  eh->aaih = TALER_BANK_admin_add_incoming (tc->bank, +                                            &wtid, +                                            &amount, +                                            wire, +                                            &execute_cb, +                                            eh); +  if (NULL == eh->aaih) +  { +    GNUNET_break (0); +    GNUNET_free (eh); +    return NULL; +  } +  run_bt (tc); +  return eh;  } @@ -170,7 +408,8 @@ static void  test_execute_wire_transfer_cancel (void *cls,                                     struct TALER_WIRE_ExecuteHandle *eh)  { -  GNUNET_break (0); +  TALER_BANK_admin_add_incoming_cancel (eh->aaih); +  GNUNET_free (eh);  } @@ -186,21 +425,20 @@ libtaler_plugin_wire_test_init (void *cls)    struct GNUNET_CONFIGURATION_Handle *cfg = cls;    struct TestClosure *tc;    struct TALER_WIRE_Plugin *plugin; - -  tc = GNUNET_new (struct TestClosure); +  char *uri;    if (GNUNET_OK !=        GNUNET_CONFIGURATION_get_value_string (cfg,                                               "wire-test",                                               "bank_uri", -                                             &tc->bank_uri)) -    { +                                             &uri)) +  {      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,                                 "wire-test",                                 "bank_uri"); -    GNUNET_free (tc);      return NULL;    } +  tc = GNUNET_new (struct TestClosure);    if (GNUNET_OK !=        GNUNET_CONFIGURATION_get_value_string (cfg,                                               "mint", @@ -210,7 +448,15 @@ libtaler_plugin_wire_test_init (void *cls)      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,                                 "mint",                                 "CURRENCY"); -    GNUNET_free (tc->bank_uri); +    GNUNET_free (uri); +    GNUNET_free (tc); +    return NULL; +  } +  tc->bank = TALER_BANK_init (uri); +  if (NULL == tc->bank) +  { +    GNUNET_break (0); +    GNUNET_free (tc->currency);      GNUNET_free (tc);      return NULL;    } @@ -239,7 +485,12 @@ libtaler_plugin_wire_test_done (void *cls)    struct TALER_WIRE_Plugin *plugin = cls;    struct TestClosure *tc = plugin->cls; -  GNUNET_free (tc->bank_uri); +  if (NULL != tc->bt) +  { +    GNUNET_SCHEDULER_cancel (tc->bt); +    tc->bt = NULL; +  } +  TALER_BANK_fini (tc->bank);    GNUNET_free (tc->currency);    GNUNET_free (tc);    GNUNET_free (plugin); | 
