cash2ecash

cash2ecash: cash acceptor that issues digital cash (experimental)
Log | Files | Refs | README | LICENSE

commit 123c4a344533f83ce5d5933404bf6e4a82715573
parent 2b5d168b9589b1ee38405d72dee52866217bd685
Author: Tellenbach Reto <tellr1@bfh.ch>
Date:   Sun, 31 May 2026 09:15:43 +0200

[new] thinker_TalerAPI: pars get_config response

Diffstat:
Mthinker/taler_api/src/lib/CMakeLists.txt | 3++-
Mthinker/taler_api/src/lib/bank_api_get_config.c | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mthinker/taler_api/src/lib/bank_api_get_config.h | 148+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mthinker/taler_api/src/taler-digitizer.c | 19++++++-------------
Mthinker/taler_api/src/taler/taler_digitizer_service.h | 6++++++
5 files changed, 257 insertions(+), 89 deletions(-)

diff --git a/thinker/taler_api/src/lib/CMakeLists.txt b/thinker/taler_api/src/lib/CMakeLists.txt @@ -3,8 +3,9 @@ add_library(bank bank_api_get_config.c bank_api_curl_defaults.c) find_package(CURL REQUIRED) pkg_check_modules(GNUNET REQUIRED gnunetutil) +pkg_check_modules(LIBMICROHTTPD REQUIRED libmicrohttpd) target_link_libraries(bank - PUBLIC CURL::libcurl gnunetutil talerutil + PUBLIC CURL::libcurl gnunetutil talerutil microhttpd PRIVATE talercurl talerjson gnunetutil gnunetcurl gnunetjson jansson ) \ No newline at end of file diff --git a/thinker/taler_api/src/lib/bank_api_get_config.c b/thinker/taler_api/src/lib/bank_api_get_config.c @@ -1,5 +1,7 @@ +#include <microhttpd.h> #include "bank_api_get_config.h" #include "bank_api_curl_defaults.h" +#include "taler/taler_json_lib.h" /** * Which revision of the Taler core-bank protocol is implemented @@ -14,6 +16,19 @@ /** + * Log error related to CURL operations. + * + * @param type log level + * @param function which function failed to run + * @param code what was the curl error code + */ +#define CURL_STRERROR(type, function, code) \ + GNUNET_log (type, \ + "Curl function `%s' has failed at `%s:%d' with error: %s", \ + function, __FILE__, __LINE__, curl_easy_strerror (code)); + + +/** * Handle for the get config request. */ struct TALER_BANK_GetConfigHandle @@ -24,7 +39,7 @@ struct TALER_BANK_GetConfigHandle struct GNUNET_CURL_Context *ctx; /** - * Function to call with the auditor's certification data, + * Function to call with the , * NULL if this has already been done. */ TALER_BANK_ConfigCallback config_cb; @@ -46,33 +61,174 @@ struct TALER_BANK_GetConfigHandle char *job_url; }; + +/** + * Decode the JSON in @a resp_obj from the /config response + * + * @param[in] resp_obj JSON object to parse + * @param[in,out] vi where to store the results we decoded + * @param[out] vc where to store config compatibility data + * @return #TALER_EC_NONE on success + */ +static enum TALER_ErrorCode +decode_config_json (const json_t *resp_obj, + struct TALER_BANK_ConfigInformation *vi, + enum TALER_BANK_VersionCompatibility *vc) +{ + struct TALER_JSON_ProtocolVersion pv; + const char *ver; + bool bank_name_missing; + + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_version ("version", + &pv), + GNUNET_JSON_spec_string ("version", + &ver), + GNUNET_JSON_spec_string ("currency", + &vi->currency), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("bank_name", + &vi->bank_name), + &bank_name_missing), + GNUNET_JSON_spec_end () + }; + + if (JSON_OBJECT != json_typeof (resp_obj)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + if (GNUNET_OK != + GNUNET_JSON_parse (resp_obj, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + + /* Set default fot optional values */ + if (bank_name_missing) + { + vi->bank_name = GNUNET_strdup("Taler Bank"); + } + + /* Version comparison */ + vi->version = ver; + *vc = TALER_BANK_VC_MATCH; + if (TALER_PROTOCOL_CURRENT < pv.current) + { + *vc |= TALER_BANK_VC_NEWER; + if (TALER_PROTOCOL_CURRENT < pv.current - pv.age) + *vc |= TALER_BANK_VC_INCOMPATIBLE; + } + if (TALER_PROTOCOL_CURRENT > pv.current) + { + *vc |= TALER_BANK_VC_OLDER; + if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > pv.current) + *vc |= TALER_BANK_VC_INCOMPATIBLE; + } + + struct GNUNET_JSON_Specification spec2[] = { + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ("min_wire_transfer_amount", + vi->currency, + &vi->min_wire_transfer_amount), + NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ("max_wire_transfer_amount", + vi->currency, + &vi->max_wire_transfer_amount), + NULL), + TALER_JSON_spec_currency_specification ("currency_specification", + vi->currency, + &vi->currency_specification), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount("wire_transfer_fees", + vi->currency, + &vi->wire_transfer_fees), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (resp_obj, + spec2, + NULL, NULL)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + + return TALER_EC_NONE; +} + + /** * Callback used when http reply arived to a /config request. * * @param cls the `struct TALER_BANK_GetConfigHandle` * @param response_code HTTP response code or 0 on error - * @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *` + * @param gresp_obj JSON result, NULL on error, must be a `const json_t *` */ static void response_cb(void *cls, long response_code, - const void *response) + const void *gresp_obj) { struct TALER_BANK_GetConfigHandle *bank = cls; - const json_t *resp_obj = response; + const json_t *resp_obj = gresp_obj; - struct TALER_BANK_ConfigResponse vr = { + struct TALER_BANK_ConfigResponse cr = { .hr.response = resp_obj, .hr.http_status = (unsigned int)response_code }; - bank->job = NULL; + bank->job = NULL; //job was successfull, curl job cancel not needed anymore in cleanup GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received config from URL `%s' with status %ld.\n", bank->job_url, response_code); + + switch (response_code) + { + case 0: + GNUNET_break_op (0); + cr.hr.ec = TALER_EC_INVALID; + break; + case MHD_HTTP_OK: + if (NULL == resp_obj) + { + GNUNET_break_op (0); + cr.hr.http_status = 0; + cr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + cr.hr.ec = decode_config_json (resp_obj, + &cr.details.ok.configi, + &cr.details.ok.version_compa); + if (TALER_EC_NONE != cr.hr.ec) + { + GNUNET_break_op (0); + cr.hr.http_status = 0; + break; + } + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + cr.hr.ec = TALER_JSON_get_error_code (resp_obj); + cr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + break; + default: + cr.hr.ec = TALER_JSON_get_error_code (resp_obj); + cr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d\n", + (unsigned int) response_code, + (int) cr.hr.ec); + break; + } - bank->config_cb (bank->config_cb_cls, &vr); + bank->config_cb (bank->config_cb_cls, &cr); TALER_BANK_get_config_cancel(bank); } diff --git a/thinker/taler_api/src/lib/bank_api_get_config.h b/thinker/taler_api/src/lib/bank_api_get_config.h @@ -9,10 +9,6 @@ */ struct TALER_BANK_ConfigInformation { - /** - * Name of api - */ - const char *api_name; /** * Supported Taler protocol version by the bank. @@ -23,88 +19,93 @@ struct TALER_BANK_ConfigInformation const char *version; /** - * Bank display name to be used in user interfaces. - * For consistency use "Taler Bank" if missing. + * Currency used by this bank. */ - const char *bank_name; + const char *currency; /** - * Advertised base URL to use when you sharing an URL with another program. - */ - const char *base_url; - - /** If 'true' the server provides local currency conversion support - * If 'false' some parts of the API are not supported and return 501 - */ - const bool allow_conversion; - - /** If 'true' anyone can register - * If 'false' only admin can + * Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals. */ - const bool allow_registrations; + struct TALER_Amount min_wire_transfer_amount; /** - * If 'true' account can delete themselves - * If 'false' only admin can delete accounts + * Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals. */ - const bool allow_deletions; - - /** - * If 'true' anyone can edit their name - * If 'false' only admin can - */ - const bool allow_edit_name; - - /** - * If 'true' anyone can edit their cashout account - * If 'false' only admin can - */ - const bool allow_edit_cashout_payto_uri; - - /** - * Default debt limit for newly created accounts - */ - const struct TALER_AmountNBO default_debit_threshold; - - - /** - * Currency used by this bank. - */ - const char *currency; + struct TALER_Amount max_wire_transfer_amount; /** * How the bank SPA should render this currency. */ - const struct TALER_CurrencySpecification currency_specification; + struct TALER_CurrencySpecification currency_specification; - /** - * Stand in string for the TAN channel. Not used in the callbacks - * when used needs to be addapted - * TAN channels supported by the server - */ - const char *supported_tan_channels; - - /** - * Wire transfer type supported by the bank. - * Defaults to 'iban' is missing + /** + * Bank display name to be used in user interfaces. + * For consistency use "Taler Bank" if missing. */ - const char *wire_type; + const char *bank_name; /** * Wire transfer execution fees. Only applies to bank transactions and withdrawals. */ - const struct TALER_AmountNBO wire_transfer_fees; - - /** - * Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals. - */ - const struct TALER_AmountNBO min_wire_transfer_amount; + struct TALER_Amount wire_transfer_fees; + + // /** + // * Name of api + // */ + // const char *api_name; + + + // /** + // * Advertised base URL to use when you sharing an URL with another program. + // */ + // const char *base_url; + + // /** If 'true' the server provides local currency conversion support + // * If 'false' some parts of the API are not supported and return 501 + // */ + // const bool allow_conversion; + + // /** If 'true' anyone can register + // * If 'false' only admin can + // */ + // const bool allow_registrations; + + // /** + // * If 'true' account can delete themselves + // * If 'false' only admin can delete accounts + // */ + // const bool allow_deletions; + + // /** + // * If 'true' anyone can edit their name + // * If 'false' only admin can + // */ + // const bool allow_edit_name; + + // /** + // * If 'true' anyone can edit their cashout account + // * If 'false' only admin can + // */ + // const bool allow_edit_cashout_payto_uri; + + // /** + // * Default debt limit for newly created accounts + // */ + // const struct TALER_AmountNBO default_debit_threshold; + + // /** + // * Stand in string for the TAN channel. Not used in the callbacks + // * when used needs to be addapted + // * TAN channels supported by the server + // */ + // const char *supported_tan_channels; + + // /** + // * Wire transfer type supported by the bank. + // * Defaults to 'iban' is missing + // */ + // const char *wire_type; - - /** - * Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals. - */ - const struct TALER_AmountNBO max_wire_transfer_amount; }; /** @@ -130,6 +131,14 @@ struct TALER_BANK_ConfigResponse struct { + /** + * Protocol compatibility evaluation. + */ + enum TALER_BANK_VersionCompatibility version_compa; + + /** + * Config data returned by /config. + */ struct TALER_BANK_ConfigInformation configi; } ok; @@ -159,6 +168,9 @@ struct TALER_BANK_GetConfigHandle; /** * Obtain config inforamtion about the connected Bank + * @param ctx + * @param url + * @return NULL on failure */ struct TALER_BANK_GetConfigHandle * TALER_BANK_get_config ( struct GNUNET_CURL_Context *ctx, diff --git a/thinker/taler_api/src/taler-digitizer.c b/thinker/taler_api/src/taler-digitizer.c @@ -64,20 +64,10 @@ static struct GNUNET_CURL_RescheduleContext *reschedule_ctx; */ static struct TALER_BANK_GetConfigHandle *get_config_handle; -/** - * All the variables needed in run() that must be cleaned in shutdown - */ -struct TALER_DIGITIZER_State -{ - struct GNUNET_CURL_Context *curl_ctx; - struct GNUNET_CURL_RescheduleContext *reschedule_ctx; - struct TALER_BANK_GetConfigHandle *get_config_handle; -}; - static void -after_get_config (void *cls, - const struct TALER_BANK_ConfigResponse *vr) +on_config_received (void *cls, + const struct TALER_BANK_ConfigResponse *vr) { (void) cls; (void) vr; @@ -86,6 +76,7 @@ after_get_config (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Config Callback\n"); + GNUNET_SCHEDULER_shutdown (); } @@ -230,8 +221,10 @@ run (void *cls, get_config_handle = TALER_BANK_get_config (curl_ctx, cfg_backend_base_url, - &after_get_config, + &on_config_received, NULL); + + return; } diff --git a/thinker/taler_api/src/taler/taler_digitizer_service.h b/thinker/taler_api/src/taler/taler_digitizer_service.h @@ -70,6 +70,12 @@ struct TALER_BANK_HttpResponse */ const json_t *response; + /** + * Set to the human-readable 'hint' that is optionally + * provided by the exchange together with errors. NULL + * if no hint was provided or if there was no error. + */ + const char *hint; /** * HTTP status code for the response.