diff options
| author | Christian Grothoff <christian@grothoff.org> | 2018-10-28 16:44:48 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2018-10-28 16:44:48 +0100 | 
| commit | a57080651d9666c8d3d2acc8e872178b7022a7b0 (patch) | |
| tree | c138f92c4f6ce5ad499ac1751fc7e764bc6470be | |
| parent | af416245918966b790378e48cfe2eaddb7422e2a (diff) | |
implement /exchanges API in libtalerauditor
| -rw-r--r-- | src/auditor-lib/Makefile.am | 3 | ||||
| -rw-r--r-- | src/auditor-lib/auditor_api_exchanges.c | 245 | ||||
| -rw-r--r-- | src/include/taler_auditor_service.h | 71 | 
3 files changed, 318 insertions, 1 deletions
| diff --git a/src/auditor-lib/Makefile.am b/src/auditor-lib/Makefile.am index 1e7c87a4..1d3810fd 100644 --- a/src/auditor-lib/Makefile.am +++ b/src/auditor-lib/Makefile.am @@ -15,7 +15,8 @@ libtalerauditor_la_LDFLAGS = \  libtalerauditor_la_SOURCES = \    curl_defaults.c \    auditor_api_handle.c auditor_api_handle.h \ -  auditor_api_deposit_confirmation.c +  auditor_api_deposit_confirmation.c \ +  auditor_api_exchanges.c  libtalerauditor_la_LIBADD = \    $(top_builddir)/src/json/libtalerjson.la \    $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/auditor-lib/auditor_api_exchanges.c b/src/auditor-lib/auditor_api_exchanges.c new file mode 100644 index 00000000..2ddd2e5b --- /dev/null +++ b/src/auditor-lib/auditor_api_exchanges.c @@ -0,0 +1,245 @@ +/* +  This file is part of TALER +  Copyright (C) 2014-2018 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 +  <http://www.gnu.org/licenses/> +*/ +/** + * @file auditor-lib/auditor_api_exchanges.c + * @brief Implementation of the /exchanges request of the auditor'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_json_lib.h> +#include <gnunet/gnunet_curl_lib.h> +#include "taler_json_lib.h" +#include "taler_auditor_service.h" +#include "auditor_api_handle.h" +#include "taler_signatures.h" +#include "curl_defaults.h" + +/** + * How many exchanges do we allow a single auditor to + * audit at most? + */ +#define MAX_EXCHANGES 1024 + + +/** + * @brief A ListExchanges Handle + */ +struct TALER_AUDITOR_ListExchangesHandle +{ + +  /** +   * The connection to auditor this request handle will use +   */ +  struct TALER_AUDITOR_Handle *auditor; + +  /** +   * The url for this request. +   */ +  char *url; + +  /** +   * Handle for the request. +   */ +  struct GNUNET_CURL_Job *job; + +  /** +   * Function to call with the result. +   */ +  TALER_AUDITOR_ListExchangesResultCallback cb; + +  /** +   * Closure for @a cb. +   */ +  void *cb_cls; + +}; + + +/** + * Function called when we're done processing the + * HTTP /deposit-confirmation request. + * + * @param cls the `struct TALER_AUDITOR_ListExchangesHandle` + * @param response_code HTTP response code, 0 on error + * @param djson parsed JSON result, NULL on error + */ +static void +handle_exchanges_finished (void *cls, +                           long response_code, +                           const void *djson) +{ +  const json_t *json = djson; +  const json_t *ja; +  unsigned int ja_len; +  struct TALER_AUDITOR_ListExchangesHandle *leh = cls; + +  leh->job = NULL; +  switch (response_code) +  { +  case 0: +    break; +  case MHD_HTTP_OK: +    ja = json_object_get (json, +                          "exchanges"); +    if ( (NULL == ja) || +         (! json_is_array (ja)) ) +    { +      GNUNET_break (0); +      response_code = 0; +      break; +    } + +    ja_len = json_array_size (ja); +    if (ja_len > MAX_EXCHANGES) +    { +      GNUNET_break (0); +      response_code = 0; +      break; +    } +    { +      struct TALER_AUDITOR_ExchangeInfo ei[ja_len]; +      int ok; + +      ok = GNUNET_YES; +      for (unsigned int i=0;i<ja_len;i++) +      { +        struct GNUNET_JSON_Specification spec[] = { +          GNUNET_JSON_spec_fixed_auto ("master_pub", &ei[i].master_pub), +          GNUNET_JSON_spec_string ("exchange_url", &ei[i].exchange_url), +          GNUNET_JSON_spec_end() +        }; + +        if (GNUNET_OK != +            GNUNET_JSON_parse (json_array_get (ja, +                                               i), +                               spec, +                               NULL, NULL)) +        { +          GNUNET_break_op (0); +          ok = GNUNET_NO; +          break; +        } +      } +      if (GNUNET_YES != ok) +        break; +      leh->cb (leh->cb_cls, +               response_code, +               TALER_EC_NONE, +               ja_len, +               ei, +               json); +      leh->cb = NULL; +    } +    break; +  case MHD_HTTP_BAD_REQUEST: +    /* This should never happen, either us or the auditor is buggy +       (or API version conflict); just pass JSON reply to the application */ +    break; +  case MHD_HTTP_NOT_FOUND: +    /* Nothing really to verify, this should never +       happen, we should pass the JSON reply to the application */ +    break; +  case MHD_HTTP_INTERNAL_SERVER_ERROR: +    /* Server had an internal issue; we should retry, but this API +       leaves this to the application */ +    break; +  default: +    /* unexpected response code */ +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Unexpected response code %u\n", +                (unsigned int) response_code); +    GNUNET_break (0); +    response_code = 0; +    break; +  } +  if (NULL != leh->cb) +    leh->cb (leh->cb_cls, +             response_code, +             TALER_JSON_get_error_code (json), +             0, +             NULL, +             json); +  TALER_AUDITOR_list_exchanges_cancel (leh); +} + + +/** + * Submit an /exchanges request to the auditor and get the + * auditor's response.  If the auditor's reply is not + * well-formed, we return an HTTP status code of zero to @a cb. + * + * @param auditor the auditor handle; the auditor must be ready to operate + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + *         signatures fail to verify).  In this case, the callback is not called. + */ +struct TALER_AUDITOR_ListExchangesHandle * +TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor, +                              TALER_AUDITOR_ListExchangesResultCallback cb, +                              void *cb_cls) +{ +  struct TALER_AUDITOR_ListExchangesHandle *leh; +  struct GNUNET_CURL_Context *ctx; +  CURL *eh; + +  GNUNET_assert (GNUNET_YES == +		 MAH_handle_is_ready (auditor)); + +  leh = GNUNET_new (struct TALER_AUDITOR_ListExchangesHandle); +  leh->auditor = auditor; +  leh->cb = cb; +  leh->cb_cls = cb_cls; +  leh->url = MAH_path_to_url (auditor, "/exchanges"); + +  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +              "URL for list-exchanges: `%s'\n", +              leh->url); +  eh = TAL_curl_easy_get (leh->url); +  ctx = MAH_handle_to_context (auditor); +  leh->job = GNUNET_CURL_job_add (ctx, +                                  eh, +                                  GNUNET_NO, +                                  &handle_exchanges_finished, +                                  leh); +  return leh; +} + + +/** + * Cancel a deposit-confirmation permission request.  This function cannot be used + * on a request handle if a response is already served for it. + * + * @param deposit-confirmation the deposit-confirmation permission request handle + */ +void +TALER_AUDITOR_list_exchanges_cancel (struct TALER_AUDITOR_ListExchangesHandle *leh) +{ +  if (NULL != leh->job) +  { +    GNUNET_CURL_job_cancel (leh->job); +    leh->job = NULL; +  } +  GNUNET_free (leh->url); +  GNUNET_free (leh); +} + + +/* end of auditor_api_exchanges.c */ diff --git a/src/include/taler_auditor_service.h b/src/include/taler_auditor_service.h index a494a931..6f9fef5a 100644 --- a/src/include/taler_auditor_service.h +++ b/src/include/taler_auditor_service.h @@ -240,4 +240,75 @@ TALER_AUDITOR_deposit_confirmation (struct TALER_AUDITOR_Handle *auditor,  void  TALER_AUDITOR_deposit_confirmation_cancel (struct TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation); + +/** + * Handle for /exchanges API returned by + * #TALER_AUDITOR_list_exchanges() so that the operation can be + * cancelled with #TALER_AUDITOR_list_exchanges_cancel() + */ +struct TALER_AUDITOR_ListExchangesHandle; + + +/** + * Information about an exchange kept by the auditor. + */ +struct TALER_AUDITOR_ExchangeInfo +{ +  /** +   * Master public key of the exchange. +   */ +  struct TALER_MasterPublicKeyP master_pub; + +  /** +   * Base URL of the exchange's API. +   */ +  const char *exchange_url; +}; + + +/** + * Function called with the result from /exchagnes. + * + * @param cls closure + * @param http_status the HTTP status code, 200 on success + * @param ec detailed Taler error status code, #TALER_EC_NONE on success + * @param num_exchanges length of array at @a ei + * @param ei information about exchanges returned by the auditor + * @param raw_response raw JSON response + */ +typedef void +(*TALER_AUDITOR_ListExchangesResultCallback)(void *cls, +                                             unsigned int http_status, +                                             enum TALER_ErrorCode ec, +                                             unsigned int num_exchanges, +                                             const struct TALER_AUDITOR_ExchangeInfo *ei, +                                             const json_t *raw_response); + +/** + * Submit an /exchanges request to the auditor and get the + * auditor's response.  If the auditor's reply is not + * well-formed, we return an HTTP status code of zero to @a cb. + * + * @param auditor the auditor handle; the auditor must be ready to operate + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + *         signatures fail to verify).  In this case, the callback is not called. + */ +struct TALER_AUDITOR_ListExchangesHandle * +TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor, +                              TALER_AUDITOR_ListExchangesResultCallback cb, +                              void *cb_cls); + + +/** + * Cancel a deposit-confirmation permission request.  This function cannot be used + * on a request handle if a response is already served for it. + * + * @param deposit-confirmation the deposit-confirmation permission request handle + */ +void +TALER_AUDITOR_list_exchanges_cancel (struct TALER_AUDITOR_ListExchangesHandle *leh); + +  #endif  /* _TALER_AUDITOR_SERVICE_H */ | 
