summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-07-13 23:07:33 +0200
committerChristian Grothoff <christian@grothoff.org>2023-07-13 23:07:33 +0200
commitb60b339ee4257124044ef3bcd56a4c8b9e482a63 (patch)
tree2d5888d973bf8a6d98dc7170c9d5cb7d2ba6911f /src/lib
parenta5451527cb26d876388567dc26113a83e0b79e15 (diff)
downloadexchange-b60b339ee4257124044ef3bcd56a4c8b9e482a63.tar.gz
exchange-b60b339ee4257124044ef3bcd56a4c8b9e482a63.tar.bz2
exchange-b60b339ee4257124044ef3bcd56a4c8b9e482a63.zip
merging /keys and /wire
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am3
-rw-r--r--src/lib/exchange_api_common.c78
-rw-r--r--src/lib/exchange_api_handle.c321
-rw-r--r--src/lib/exchange_api_wire.c392
4 files changed, 361 insertions, 433 deletions
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),
+ &regex),
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; i<ar_len; i++)
+ {
+ struct TALER_EXCHANGE_AccountRestriction *a = &ar[i];
+ switch (a->type)
+ {
+ 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; i<wfm_len; i++)
+ {
+ struct TALER_EXCHANGE_WireFeesByMethod *wfmi = &wfm[i];
+
+ while (NULL != wfmi->fees_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; i<ar_len; i++)
+ {
+ const struct TALER_EXCHANGE_AccountRestriction *ar = &ars[i];
+
+ switch (ar->type)
+ {
+ 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; i<kd->num_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; i<kd->accounts_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; i<kd->fees_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; i<kd->num_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
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @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 <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#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; i<wfm_len; i++)
- {
- struct TALER_EXCHANGE_WireFeesByMethod *wfmi = &wfm[i];
-
- while (NULL != wfmi->fees_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 */