diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/Makefile.am | 3 | ||||
| -rw-r--r-- | src/lib/exchange_api_common.c | 78 | ||||
| -rw-r--r-- | src/lib/exchange_api_handle.c | 321 | ||||
| -rw-r--r-- | src/lib/exchange_api_wire.c | 392 | 
4 files changed, 361 insertions, 433 deletions
| diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 762a3f80..3d4604c1 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 7c86ec59..337fbaba 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; 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 6d1e7b69..e409ee47 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 a428f9fb..00000000 --- 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 */ | 
