From 229907c6e233609ccfafe1823f281581bf5e9680 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 14 Dec 2017 15:33:10 +0100 Subject: implement taler-bank-transfer, fixes #5195 --- src/bank-lib/Makefile.am | 13 ++ src/bank-lib/taler-bank-transfer.c | 264 +++++++++++++++++++++++++ src/exchange-lib/test_exchange_api.c | 3 +- src/exchange-tools/Makefile.am | 18 -- src/exchange-tools/taler-exchange-reservemod.c | 225 --------------------- 5 files changed, 278 insertions(+), 245 deletions(-) create mode 100644 src/bank-lib/taler-bank-transfer.c delete mode 100644 src/exchange-tools/taler-exchange-reservemod.c (limited to 'src') diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index da8dd9d39..967d95ed3 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -6,6 +6,19 @@ if USE_COVERAGE XLIB = -lgcov endif +bin_PROGRAMS = \ + taler-bank-transfer + +taler_bank_transfer_SOURCES = \ + taler-bank-transfer.c +taler_bank_transfer_LDADD = \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/util/libtalerutil.la \ + libtalerbank.la \ + -lgnunetcurl \ + -lgnunetutil \ + -ljansson $(XLIB) + lib_LTLIBRARIES = \ libtalerbank.la \ libtalerfakebank.la diff --git a/src/bank-lib/taler-bank-transfer.c b/src/bank-lib/taler-bank-transfer.c new file mode 100644 index 000000000..4ba8a020e --- /dev/null +++ b/src/bank-lib/taler-bank-transfer.c @@ -0,0 +1,264 @@ +/* + This file is part of TALER + Copyright (C) 2017 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file taler-bank-transfer.c + * @brief Execute wire transfer. + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include +#include "taler_bank_service.h" + +/** + * Bank URL. + */ +static char *bank_url; + +/** + * Amount to transfer. + */ +static struct TALER_Amount amount; + +/** + * Debit account number. + */ +static unsigned long long debit_account_no; + +/** + * Credit account number. + */ +static unsigned long long credit_account_no; + +/** + * Wire transfer subject. + */ +static char *subject; + +/** + * Username for authentication. + */ +static char *username; + +/** + * Password for authentication. + */ +static char *password; + +/** + * Return value from main(). + */ +static int global_ret; + +/** + * Main execution context for the main loop. + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * Handle to access the exchange. + */ +static struct TALER_BANK_AdminAddIncomingHandle *op; + +/** + * Context for running the CURL event loop. + */ +static struct GNUNET_CURL_RescheduleContext *rc; + + +/** + * Function run when the test terminates (good or bad). + * Cleans up our state. + * + * @param cls NULL + */ +static void +do_shutdown (void *cls) +{ + if (NULL != op) + { + TALER_BANK_admin_add_incoming_cancel (op); + op = NULL; + } + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } +} + + +/** + * Function called with the result of the operation. + * + * @param cls closure + * @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) + * @param ec detailed error code + * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error + * @param json detailed response from the HTTPD, or NULL if reply was not in JSON + */ +static void +res_cb (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + uint64_t serial_id, + const json_t *json) +{ + op = NULL; + switch (ec) + { + case TALER_EC_NONE: + global_ret = 0; + fprintf (stdout, + "%llu\n", + (unsigned long long) serial_id); + break; + default: + fprintf (stderr, + "Operation failed with staus code %u/%u\n", + (unsigned int) ec, + http_status); + if (NULL != json) + json_dumpf (json, + stderr, + JSON_INDENT (2)); + break; + } + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct TALER_BANK_AuthenticationData auth; + + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + GNUNET_assert (NULL != ctx); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + + auth.method = TALER_BANK_AUTH_BASIC; + auth.details.basic.username = username; + auth.details.basic.password = password; + op = TALER_BANK_admin_add_incoming (ctx, + bank_url, + &auth, + "https://exchange.com/legacy", + subject, + &amount, + debit_account_no, + credit_account_no, + &res_cb, + NULL); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + if (NULL == op) + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * The main function of the reservemod tool + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_mandatory + (TALER_getopt_get_amount ('a', + "amount", + "VALUE", + "value to transfer", + &amount)), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_string ('b', + "bank", + "URL", + "base URL of the bank", + &bank_url)), + GNUNET_GETOPT_option_help ("Deposit funds into a Taler reserve"), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_ulong ('C', + "credit", + "ACCOUNT", + "number of the bank account to credit", + &credit_account_no)), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_ulong ('D', + "debit", + "ACCOUNT", + "number of the bank account to debit", + &debit_account_no)), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_string ('s', + "subject", + "STRING", + "specifies the wire transfer subject", + &subject)), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_string ('u', + "user", + "USERNAME", + "username to use for authentication", + &username)), + GNUNET_GETOPT_option_mandatory + (GNUNET_GETOPT_option_string ('p', + "pass", + "PASSPHRASE", + "passphrase to use for authentication", + &subject)), + GNUNET_GETOPT_OPTION_END + }; + + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-bank-transfer", + "WARNING", + NULL)); + global_ret = 1; + if (GNUNET_OK != + GNUNET_PROGRAM_run (argc, argv, + "taler-bank-transfer", + "Execute bank transfer", + options, + &run, NULL)) + return 1; + return global_ret; +} + +/* end taler-bank-transfer.c */ diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index 475fbde4e..6fd9ad693 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -2870,13 +2870,12 @@ do_shutdown (void *cls) { struct InterpreterState *is = cls; struct Command *cmd; - unsigned int i; fprintf (stderr, "Executing shutdown at `%s'\n", is->commands[is->ip].label); - for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++) + for (unsigned int i=0;OC_END != (cmd = &is->commands[i])->oc;i++) { switch (cmd->oc) { diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index 8eb2ac210..8d00415c8 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -15,7 +15,6 @@ endif bin_PROGRAMS = \ taler-exchange-keyup \ taler-exchange-keycheck \ - taler-exchange-reservemod \ taler-exchange-wire \ taler-exchange-dbinit @@ -51,23 +50,6 @@ taler_exchange_keycheck_LDADD = \ -lgnunetutil $(XLIB) taler_exchange_keycheck_LDFLAGS = $(POSTGRESQL_LDFLAGS) -taler_exchange_reservemod_SOURCES = \ - taler-exchange-reservemod.c -taler_exchange_reservemod_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/util/libtalerutil.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ - -lgnunetjson \ - -lgnunetutil \ - -ljansson $(XLIB) -taler_exchange_reservemod_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) -taler_exchange_reservemod_CPPFLAGS = \ - -I$(top_srcdir)/src/include \ - -I$(top_srcdir)/src/pq/ \ - $(POSTGRESQL_CPPFLAGS) - taler_exchange_dbinit_SOURCES = \ taler-exchange-dbinit.c taler_exchange_dbinit_LDADD = \ diff --git a/src/exchange-tools/taler-exchange-reservemod.c b/src/exchange-tools/taler-exchange-reservemod.c deleted file mode 100644 index e901b694d..000000000 --- a/src/exchange-tools/taler-exchange-reservemod.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2017 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see -*/ -/** - * @file taler-exchange-reservemod.c - * @brief Modify reserves. Allows manipulation of reserve balances. - * @author Florian Dold - * @author Benedikt Mueller - */ -#include "platform.h" -#include -#include -#include -#include -#include "taler_exchangedb_plugin.h" - -/** - * Director of the exchange, containing the keys. - */ -static char *exchange_directory; - -/** - * Our DB plugin. - */ -static struct TALER_EXCHANGEDB_Plugin *plugin; - -/** - * Public key of the reserve. - */ -static struct TALER_ReservePublicKeyP reserve_pub; - -/** - * Amount to add. Invalid if not initialized. - */ -static struct TALER_Amount add_value; - -/** - * Details about the sender account in JSON format. - */ -static json_t *sender_details; - -/** - * Details about the wire transfer in JSON format. - */ -static json_t *transfer_details; - -/** - * Return value from main(). - */ -static int global_ret; - - -/** - * Run the database transaction. - * - * @param reserve_pub public key of the reserve to use - * @param add_value value to add - * @param jdetails JSON details about sender - * @param tdetails JSON details about transfer - * @return #GNUNET_OK on success, #GNUNET_SYSERR on hard error, - * #GNUNET_NO if record exists - */ -static int -run_transaction (const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *add_value, - json_t *jdetails, - json_t *tdetails) -{ - int ret; - struct TALER_EXCHANGEDB_Session *session; - void *json_str; - struct GNUNET_TIME_Absolute now; - - session = plugin->get_session (plugin->cls); - if (NULL == session) - { - fprintf (stderr, - "Failed to initialize DB session\n"); - return GNUNET_SYSERR; - } - /* FIXME: maybe allow passing timestamp via command-line? */ - json_str = json_dumps (tdetails, - JSON_INDENT(2)); - if (NULL == json_str) - { - GNUNET_break (0); /* out of memory? */ - return GNUNET_SYSERR; - } - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); - ret = plugin->reserves_in_insert (plugin->cls, - session, - reserve_pub, - add_value, - now, - jdetails, - json_str, - strlen (json_str)); - free (json_str); - if (GNUNET_SYSERR == ret) - { - fprintf (stderr, - "Failed to update reserve.\n"); - } - if (GNUNET_NO == ret) - { - fprintf (stderr, - "Record exists, reserve not updated.\n"); - } - return ret; -} - - -/** - * Main function that will be run. - * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - "exchange", - "KEYDIR", - &exchange_directory)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "KEYDIR"); - global_ret = 1; - return; - } - if (NULL == - (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) - { - fprintf (stderr, - "Failed to initialize database plugin.\n"); - global_ret = 1; - return; - } - if (GNUNET_SYSERR == - run_transaction (&reserve_pub, - &add_value, - sender_details, - transfer_details)) - global_ret = 1; - TALER_EXCHANGEDB_plugin_unload (plugin); - json_decref (transfer_details); - json_decref (sender_details); -} - - -/** - * The main function of the reservemod tool - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_mandatory - (TALER_getopt_get_amount ('a', - "add", - "DENOM", - "value to add", - &add_value)), - GNUNET_GETOPT_option_mandatory - (GNUNET_JSON_getopt ('s', - "sender", - "JSON", - "details about the sender's bank account", - &sender_details)), - GNUNET_GETOPT_option_mandatory - (GNUNET_JSON_getopt ('t', - "transfer", - "JSON", - "details that uniquely identify the bank transfer", - &transfer_details)), - GNUNET_GETOPT_option_help ("Deposit funds into a Taler reserve"), - GNUNET_GETOPT_option_mandatory - (GNUNET_GETOPT_option_base32_auto ('R', - "reserve", - "KEY", - "reserve (public key) to modify", - &reserve_pub)), - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_assert (GNUNET_OK == - GNUNET_log_setup ("taler-exchange-reservemod", - "WARNING", - NULL)); - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, - "taler-exchange-reservemod", - "Deposit funds into a Taler reserve", - options, - &run, NULL)) - return 1; - return global_ret; -} - -/* end taler-exchange-reservemod.c */ -- cgit v1.2.3