From b60b339ee4257124044ef3bcd56a4c8b9e482a63 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 13 Jul 2023 23:07:33 +0200 Subject: merging /keys and /wire --- src/lib/Makefile.am | 3 +- src/lib/exchange_api_common.c | 78 +++++++-- src/lib/exchange_api_handle.c | 321 +++++++++++++++++++++++++++++++--- src/lib/exchange_api_wire.c | 392 ------------------------------------------ 4 files changed, 361 insertions(+), 433 deletions(-) delete mode 100644 src/lib/exchange_api_wire.c (limited to 'src/lib') diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 762a3f805..3d4604c13 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -75,8 +75,7 @@ libtalerexchange_la_SOURCES = \ exchange_api_reserves_status.c \ exchange_api_transfers_get.c \ exchange_api_withdraw.c \ - exchange_api_withdraw2.c \ - exchange_api_wire.c + exchange_api_withdraw2.c libtalerexchange_la_LIBADD = \ libtalerauditor.la \ $(top_builddir)/src/json/libtalerjson.la \ diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 7c86ec597..337fbabaf 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -2241,15 +2241,17 @@ parse_restrictions (const json_t *jresta, if (0 == strcmp (type, "regex")) { + const char *regex; + const char *hint; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ( "payto_regex", - &ar->details.regex.posix_egrep), + ®ex), GNUNET_JSON_spec_string ( "human_hint", - &ar->details.regex.human_hint), + &hint), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_object_const ( + GNUNET_JSON_spec_json ( "human_hint_i18n", &ar->details.regex.human_hint_i18n), NULL), @@ -2266,6 +2268,8 @@ parse_restrictions (const json_t *jresta, goto fail; } ar->type = TALER_EXCHANGE_AR_REGEX; + ar->details.regex.posix_egrep = GNUNET_strdup (regex); + ar->details.regex.human_hint = GNUNET_strdup (hint); continue; } /* unsupported type */ @@ -2297,14 +2301,16 @@ TALER_EXCHANGE_parse_accounts ( i++) { struct TALER_EXCHANGE_WireAccount *wa = &was[i]; + const char *payto_uri; + const char *conversion_url; const json_t *credit_restrictions; const json_t *debit_restrictions; struct GNUNET_JSON_Specification spec_account[] = { GNUNET_JSON_spec_string ("payto_uri", - &wa->payto_uri), + &payto_uri), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("conversion_url", - &wa->conversion_url), + &conversion_url), NULL), GNUNET_JSON_spec_array_const ("credit_restrictions", &credit_restrictions), @@ -2330,7 +2336,7 @@ TALER_EXCHANGE_parse_accounts ( { char *err; - err = TALER_payto_validate (wa->payto_uri); + err = TALER_payto_validate (payto_uri); if (NULL != err) { GNUNET_break_op (0); @@ -2341,12 +2347,13 @@ TALER_EXCHANGE_parse_accounts ( if ( (NULL != master_pub) && (GNUNET_OK != - TALER_exchange_wire_signature_check (wa->payto_uri, - wa->conversion_url, - debit_restrictions, - credit_restrictions, - master_pub, - &wa->master_sig)) ) + TALER_exchange_wire_signature_check ( + payto_uri, + conversion_url, + debit_restrictions, + credit_restrictions, + master_pub, + &wa->master_sig)) ) { /* bogus reply */ GNUNET_break_op (0); @@ -2365,11 +2372,44 @@ TALER_EXCHANGE_parse_accounts ( GNUNET_break_op (0); return GNUNET_SYSERR; } + wa->payto_uri = GNUNET_strdup (payto_uri); + if (NULL != conversion_url) + wa->conversion_url = GNUNET_strdup (conversion_url); } /* end 'for all accounts */ return GNUNET_OK; } +/** + * Free array of account restrictions. + * + * @param ar_len length of @a ar + * @param[in] ar array to free contents of (but not @a ar itself) + */ +static void +free_restrictions (unsigned int ar_len, + struct TALER_EXCHANGE_AccountRestriction ar[static ar_len]) +{ + for (unsigned int i = 0; itype) + { + case TALER_EXCHANGE_AR_INVALID: + GNUNET_break (0); + break; + case TALER_EXCHANGE_AR_DENY: + break; + case TALER_EXCHANGE_AR_REGEX: + GNUNET_free (ar->details.regex.posix_egrep); + GNUNET_free (ar->details.regex.human_hint); + json_decref (ar->details.regex.human_hint_i18n); + break; + } + } +} + + void TALER_EXCHANGE_free_accounts ( unsigned int was_len, @@ -2379,8 +2419,18 @@ TALER_EXCHANGE_free_accounts ( { struct TALER_EXCHANGE_WireAccount *wa = &was[i]; - GNUNET_free (wa->credit_restrictions); - GNUNET_free (wa->debit_restrictions); + GNUNET_free (wa->payto_uri); + GNUNET_free (wa->conversion_url); + free_restrictions (wa->credit_restrictions_length, + wa->credit_restrictions); + GNUNET_array_grow (wa->credit_restrictions, + wa->credit_restrictions_length, + 0); + free_restrictions (wa->debit_restrictions_length, + wa->debit_restrictions); + GNUNET_array_grow (wa->debit_restrictions, + wa->debit_restrictions_length, + 0); } } diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index 6d1e7b692..e409ee471 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -123,6 +123,115 @@ struct TALER_EXCHANGE_GetKeysHandle }; +/** + * Frees @a wfm array. + * + * @param wfm fee array to release + * @param wfm_len length of the @a wfm array + */ +static void +free_fees (struct TALER_EXCHANGE_WireFeesByMethod *wfm, + unsigned int wfm_len) +{ + for (unsigned int i = 0; ifees_head) + { + struct TALER_EXCHANGE_WireAggregateFees *fe + = wfmi->fees_head; + + wfmi->fees_head = fe->next; + GNUNET_free (fe); + } + GNUNET_free (wfmi->method); + } + GNUNET_free (wfm); +} + + +/** + * Parse wire @a fees and return array. + * + * @param master_pub master public key to use to check signatures + * @param fees json AggregateTransferFee to parse + * @param[out] fees_len set to length of returned array + * @return NULL on error + */ +static struct TALER_EXCHANGE_WireFeesByMethod * +parse_fees (const struct TALER_MasterPublicKeyP *master_pub, + const json_t *fees, + unsigned int *fees_len) +{ + struct TALER_EXCHANGE_WireFeesByMethod *fbm; + unsigned int fbml = json_object_size (fees); + unsigned int i = 0; + const char *key; + const json_t *fee_array; + + fbm = GNUNET_new_array (fbml, + struct TALER_EXCHANGE_WireFeesByMethod); + *fees_len = fbml; + json_object_foreach ((json_t *) fees, key, fee_array) { + struct TALER_EXCHANGE_WireFeesByMethod *fe = &fbm[i++]; + unsigned int idx; + json_t *fee; + + fe->method = GNUNET_strdup (key); + fe->fees_head = NULL; + json_array_foreach (fee_array, idx, fee) + { + struct TALER_EXCHANGE_WireAggregateFees *wa + = GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees); + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("sig", + &wa->master_sig), + TALER_JSON_spec_amount_any ("wire_fee", + &wa->fees.wire), + TALER_JSON_spec_amount_any ("closing_fee", + &wa->fees.closing), + GNUNET_JSON_spec_timestamp ("start_date", + &wa->start_date), + GNUNET_JSON_spec_timestamp ("end_date", + &wa->end_date), + GNUNET_JSON_spec_end () + }; + + wa->next = fe->fees_head; + fe->fees_head = wa; + if (GNUNET_OK != + GNUNET_JSON_parse (fee, + spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + free_fees (fbm, + i); + return NULL; + } + if (GNUNET_OK != + TALER_exchange_offline_wire_fee_verify ( + key, + wa->start_date, + wa->end_date, + &wa->fees, + master_pub, + &wa->master_sig)) + { + GNUNET_break_op (0); + free_fees (fbm, + i); + return NULL; + } + } /* for all fees over time */ + } /* for all methods */ + GNUNET_assert (i == fbml); + return fbm; +} + + void TEAH_get_auditors_for_dc ( struct TALER_EXCHANGE_Keys *keys, @@ -541,6 +650,9 @@ decode_keys_json (const json_t *resp_obj, const json_t *manifests = NULL; bool no_extensions = false; bool no_signature = false; + const json_t *accounts; + const json_t *fees; + const json_t *wads; if (JSON_OBJECT != json_typeof (resp_obj)) { @@ -612,6 +724,12 @@ decode_keys_json (const json_t *resp_obj, GNUNET_JSON_spec_fixed_auto ( "master_public_key", &key_data->master_pub), + GNUNET_JSON_spec_array_const ("accounts", + &accounts), + GNUNET_JSON_spec_object_const ("wire_fees", + &fees), + GNUNET_JSON_spec_array_const ("wads", + &wads), GNUNET_JSON_spec_timestamp ( "list_issue_date", &key_data->list_issue_date), @@ -740,6 +858,26 @@ decode_keys_json (const json_t *resp_obj, } } + /* Parse wire accounts */ + key_data->fees = parse_fees (&key_data->master_pub, + fees, + &key_data->fees_len); + EXITIF (NULL == key_data->fees); + /* parse accounts */ + GNUNET_array_grow (key_data->accounts, + key_data->accounts_len, + json_array_size (accounts)); + EXITIF (GNUNET_OK != + TALER_EXCHANGE_parse_accounts (&key_data->master_pub, + accounts, + key_data->accounts_len, + key_data->accounts)); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Parsed %u wire accounts from JSON\n", + (unsigned int) json_array_size (accounts)); + + /* Parse the supported extension(s): age-restriction. */ /* TODO: maybe lift all this into a FP in TALER_Extension ? */ if (! no_extensions) @@ -1546,6 +1684,13 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) GNUNET_array_grow (keys->auditors, keys->auditors_size, 0); + TALER_EXCHANGE_free_accounts (keys->accounts_len, + keys->accounts); + GNUNET_array_grow (keys->accounts, + keys->accounts_len, + 0); + free_fees (keys->fees, + keys->fees_len); json_decref (keys->extensions); GNUNET_free (keys->wallet_balance_limit_without_kyc); GNUNET_free (keys->version); @@ -1688,6 +1833,66 @@ add_grp (void *cls, } +/** + * Convert array of account restrictions @a ars to JSON. + * + * @param ar_len length of @a ars + * @param ars account restrictions to convert + * @return JSON representation + */ +static json_t * +ar_to_json (unsigned int ar_len, + const struct TALER_EXCHANGE_AccountRestriction ars[static ar_len]) +{ + json_t *rval; + + rval = json_array (); + GNUNET_assert (NULL != rval); + for (unsigned int i = 0; itype) + { + case TALER_EXCHANGE_AR_INVALID: + GNUNET_break (0); + json_decref (rval); + return NULL; + case TALER_EXCHANGE_AR_DENY: + GNUNET_assert ( + 0 == + json_array_append_new ( + rval, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("type", + "deny")))); + break; + case TALER_EXCHANGE_AR_REGEX: + GNUNET_assert ( + 0 == + json_array_append_new ( + rval, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ( + "type", + "regex"), + GNUNET_JSON_pack_string ( + "regex", + ar->details.regex.posix_egrep), + GNUNET_JSON_pack_string ( + "human_hint", + ar->details.regex.human_hint), + GNUNET_JSON_pack_object_incref ( + "human_hint_i18n", + (json_t *) ar->details.regex.human_hint_i18n) + ))); + break; + } + } + return rval; +} + + json_t * TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) { @@ -1697,16 +1902,14 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) json_t *denominations_by_group; json_t *auditors; json_t *recoup; + json_t *wire_fees; + json_t *accounts; json_t *global_fees; json_t *wblwk = NULL; now = GNUNET_TIME_timestamp_get (); signkeys = json_array (); - if (NULL == signkeys) - { - GNUNET_break (0); - return NULL; - } + GNUNET_assert (NULL != signkeys); for (unsigned int i = 0; inum_sign_keys; i++) { const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i]; @@ -1727,28 +1930,14 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) sk->valid_until), GNUNET_JSON_pack_timestamp ("stamp_end", sk->valid_legal)); - if (NULL == signkey) - { - GNUNET_break (0); - continue; - } - if (0 != json_array_append_new (signkeys, - signkey)) - { - GNUNET_break (0); - json_decref (signkey); - json_decref (signkeys); - return NULL; - } - } - denominations_by_group = json_array (); - if (NULL == denominations_by_group) - { - GNUNET_break (0); - json_decref (signkeys); - return NULL; + GNUNET_assert (NULL != signkey); + GNUNET_assert (0 == + json_array_append_new (signkeys, + signkey)); } + denominations_by_group = json_array (); + GNUNET_assert (NULL != denominations_by_group); { struct GNUNET_CONTAINER_MultiHashMap *dbg; @@ -1908,6 +2097,82 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) GNUNET_JSON_pack_data_auto ("master_sig", &gf->master_sig)))); } + + accounts = json_array (); + GNUNET_assert (NULL != accounts); + for (unsigned int i = 0; iaccounts_len; i++) + { + const struct TALER_EXCHANGE_WireAccount *acc + = &kd->accounts[i]; + json_t *credit_restrictions; + json_t *debit_restrictions; + + credit_restrictions + = ar_to_json (acc->credit_restrictions_length, + acc->credit_restrictions); + GNUNET_assert (NULL != credit_restrictions); + debit_restrictions + = ar_to_json (acc->debit_restrictions_length, + acc->debit_restrictions); + GNUNET_assert (NULL != debit_restrictions); + GNUNET_assert ( + 0 == + json_array_append_new ( + accounts, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("payto_uri", + acc->payto_uri), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("conversion_url", + acc->conversion_url)), + GNUNET_JSON_pack_array_steal ("debit_restrictions", + debit_restrictions), + GNUNET_JSON_pack_array_steal ("credit_restrictions", + credit_restrictions), + GNUNET_JSON_pack_data_auto ("master_sig", + &acc->master_sig)))); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Serialized %u/%u wire accounts to JSON\n", + (unsigned int) json_array_size (accounts), + kd->accounts_len); + + wire_fees = json_object (); + GNUNET_assert (NULL != wire_fees); + for (unsigned int i = 0; ifees_len; i++) + { + const struct TALER_EXCHANGE_WireFeesByMethod *fbw + = &kd->fees[i]; + json_t *wf; + + wf = json_array (); + GNUNET_assert (NULL != wf); + for (struct TALER_EXCHANGE_WireAggregateFees *p = fbw->fees_head; + NULL != p; + p = p->next) + { + GNUNET_assert ( + 0 == + json_array_append_new ( + wf, + GNUNET_JSON_PACK ( + TALER_JSON_pack_amount ("wire_fee", + &p->fees.wire), + TALER_JSON_pack_amount ("closing_fee", + &p->fees.closing), + GNUNET_JSON_pack_timestamp ("start_date", + p->start_date), + GNUNET_JSON_pack_timestamp ("end_date", + p->end_date), + GNUNET_JSON_pack_data_auto ("sig", + &p->master_sig)))); + } + GNUNET_assert (0 == + json_object_set_new (wire_fees, + fbw->method, + wf)); + } + recoup = json_array (); GNUNET_assert (NULL != recoup); for (unsigned int i = 0; inum_denom_keys; i++) @@ -1953,6 +2218,12 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) global_fees), GNUNET_JSON_pack_array_steal ("signkeys", signkeys), + GNUNET_JSON_pack_object_steal ("wire_fees", + wire_fees), + GNUNET_JSON_pack_array_steal ("accounts", + accounts), + GNUNET_JSON_pack_array_steal ("wads", + json_array ()), GNUNET_JSON_pack_array_steal ("denominations", denominations_by_group), GNUNET_JSON_pack_allow_null ( diff --git a/src/lib/exchange_api_wire.c b/src/lib/exchange_api_wire.c deleted file mode 100644 index a428f9fb8..000000000 --- a/src/lib/exchange_api_wire.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA - - 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 lib/exchange_api_wire.c - * @brief Implementation of the /wire request of the exchange's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "taler_signatures.h" -#include "exchange_api_handle.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A Wire Handle - */ -struct TALER_EXCHANGE_WireHandle -{ - - /** - * The keys of the exchange this request handle will use - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_WireCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - -}; - - -/** - * Frees @a wfm array. - * - * @param wfm fee array to release - * @param wfm_len length of the @a wfm array - */ -static void -free_fees (struct TALER_EXCHANGE_WireFeesByMethod *wfm, - unsigned int wfm_len) -{ - for (unsigned int i = 0; ifees_head) - { - struct TALER_EXCHANGE_WireAggregateFees *fe - = wfmi->fees_head; - - wfmi->fees_head = fe->next; - GNUNET_free (fe); - } - } - GNUNET_free (wfm); -} - - -/** - * Parse wire @a fees and return array. - * - * @param master_pub master public key to use to check signatures - * @param fees json AggregateTransferFee to parse - * @param[out] fees_len set to length of returned array - * @return NULL on error - */ -static struct TALER_EXCHANGE_WireFeesByMethod * -parse_fees (const struct TALER_MasterPublicKeyP *master_pub, - const json_t *fees, - unsigned int *fees_len) -{ - struct TALER_EXCHANGE_WireFeesByMethod *fbm; - unsigned int fbml = json_object_size (fees); - unsigned int i = 0; - const char *key; - const json_t *fee_array; - - fbm = GNUNET_new_array (fbml, - struct TALER_EXCHANGE_WireFeesByMethod); - *fees_len = fbml; - json_object_foreach ((json_t *) fees, key, fee_array) { - struct TALER_EXCHANGE_WireFeesByMethod *fe = &fbm[i++]; - unsigned int idx; - json_t *fee; - - fe->method = key; - fe->fees_head = NULL; - json_array_foreach (fee_array, idx, fee) - { - struct TALER_EXCHANGE_WireAggregateFees *wa - = GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees); - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("sig", - &wa->master_sig), - TALER_JSON_spec_amount_any ("wire_fee", - &wa->fees.wire), - TALER_JSON_spec_amount_any ("closing_fee", - &wa->fees.closing), - GNUNET_JSON_spec_timestamp ("start_date", - &wa->start_date), - GNUNET_JSON_spec_timestamp ("end_date", - &wa->end_date), - GNUNET_JSON_spec_end () - }; - - wa->next = fe->fees_head; - fe->fees_head = wa; - if (GNUNET_OK != - GNUNET_JSON_parse (fee, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - free_fees (fbm, - i); - return NULL; - } - if (GNUNET_OK != - TALER_exchange_offline_wire_fee_verify ( - key, - wa->start_date, - wa->end_date, - &wa->fees, - master_pub, - &wa->master_sig)) - { - GNUNET_break_op (0); - free_fees (fbm, - i); - return NULL; - } - } /* for all fees over time */ - } /* for all methods */ - GNUNET_assert (i == fbml); - return fbm; -} - - -/** - * Function called when we're done processing the - * HTTP /wire request. - * - * @param cls the `struct TALER_EXCHANGE_WireHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_wire_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_WireHandle *wh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_WireResponse wr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - TALER_LOG_DEBUG ("Checking raw /wire response\n"); - wh->job = NULL; - switch (response_code) - { - case 0: - wr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - const json_t *accounts; - const json_t *fees; - const json_t *wads; - struct TALER_EXCHANGE_WireFeesByMethod *fbm; - struct TALER_MasterPublicKeyP master_pub; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("master_public_key", - &master_pub), - GNUNET_JSON_spec_array_const ("accounts", - &accounts), - GNUNET_JSON_spec_object_const ("fees", - &fees), - GNUNET_JSON_spec_array_const ("wads", - &wads), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - /* bogus reply */ - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - if (0 != GNUNET_memcmp (&wh->keys->master_pub, - &master_pub)) - { - /* bogus reply: master public key in /wire differs from that in /keys */ - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - - wr.details.ok.accounts_len - = json_array_size (accounts); - if (0 == wr.details.ok.accounts_len) - { - /* bogus reply */ - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - fbm = parse_fees (&master_pub, - fees, - &wr.details.ok.fees_len); - wr.details.ok.fees = fbm; - if (NULL == fbm) - { - /* bogus reply */ - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - - /* parse accounts */ - { - struct TALER_EXCHANGE_WireAccount was[wr.details.ok.accounts_len]; - - wr.details.ok.accounts = was; - if (GNUNET_OK != - TALER_EXCHANGE_parse_accounts (&master_pub, - accounts, - wr.details.ok.accounts_len, - was)) - { - GNUNET_break_op (0); - wr.hr.http_status = 0; - wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - } - else if (NULL != wh->cb) - { - wh->cb (wh->cb_cls, - &wr); - wh->cb = NULL; - } - TALER_EXCHANGE_free_accounts ( - wr.details.ok.accounts_len, - was); - } /* end of 'parse accounts */ - free_fees (fbm, - wr.details.ok.fees_len); - GNUNET_JSON_parse_free (spec); - } /* end of MHD_HTTP_OK */ - break; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - wr.hr.ec = TALER_JSON_get_error_code (j); - wr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - wr.hr.ec = TALER_JSON_get_error_code (j); - wr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - wr.hr.ec = TALER_JSON_get_error_code (j); - wr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - wr.hr.ec = TALER_JSON_get_error_code (j); - wr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange wire\n", - (unsigned int) response_code, - (int) wr.hr.ec); - break; - } - if (NULL != wh->cb) - wh->cb (wh->cb_cls, - &wr); - TALER_EXCHANGE_wire_cancel (wh); -} - - -struct TALER_EXCHANGE_WireHandle * -TALER_EXCHANGE_wire ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - TALER_EXCHANGE_WireCallback wire_cb, - void *wire_cb_cls) -{ - struct TALER_EXCHANGE_WireHandle *wh; - CURL *eh; - - wh = GNUNET_new (struct TALER_EXCHANGE_WireHandle); - wh->cb = wire_cb; - wh->cb_cls = wire_cb_cls; - wh->url = TALER_url_join (url, - "wire", - NULL); - if (NULL == wh->url) - { - GNUNET_free (wh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (wh->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (wh->url); - GNUNET_free (wh); - return NULL; - } - GNUNET_break (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_TIMEOUT, - 60 /* seconds */)); - wh->keys = TALER_EXCHANGE_keys_incref (keys); - wh->job = GNUNET_CURL_job_add_with_ct_json (ctx, - eh, - &handle_wire_finished, - wh); - return wh; -} - - -void -TALER_EXCHANGE_wire_cancel ( - struct TALER_EXCHANGE_WireHandle *wh) -{ - if (NULL != wh->job) - { - GNUNET_CURL_job_cancel (wh->job); - wh->job = NULL; - } - GNUNET_free (wh->url); - TALER_EXCHANGE_keys_decref (wh->keys); - GNUNET_free (wh); -} - - -/* end of exchange_api_wire.c */ -- cgit v1.2.3