exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

exchange_api_post-management-global-fees.c (8251B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2020-2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file lib/exchange_api_post-management-global-fees.c
     19  * @brief functions to set global fees at an exchange
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/taler_json_lib.h"
     23 #include <gnunet/gnunet_curl_lib.h>
     24 #include <microhttpd.h>
     25 #include "taler/exchange/post-management-global-fees.h"
     26 #include "exchange_api_curl_defaults.h"
     27 #include "taler/taler_curl_lib.h"
     28 
     29 
     30 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle
     31 {
     32 
     33   /**
     34    * The base URL for this request.
     35    */
     36   char *base_url;
     37 
     38   /**
     39    * The full URL for this request, set during _start.
     40    */
     41   char *url;
     42 
     43   /**
     44    * Minor context that holds body and headers.
     45    */
     46   struct TALER_CURL_PostContext post_ctx;
     47 
     48   /**
     49    * Handle for the request.
     50    */
     51   struct GNUNET_CURL_Job *job;
     52 
     53   /**
     54    * Function to call with the result.
     55    */
     56   TALER_EXCHANGE_PostManagementGlobalFeesCallback cb;
     57 
     58   /**
     59    * Closure for @a cb.
     60    */
     61   TALER_EXCHANGE_POST_MANAGEMENT_GLOBAL_FEES_RESULT_CLOSURE *cb_cls;
     62 
     63   /**
     64    * Reference to the execution context.
     65    */
     66   struct GNUNET_CURL_Context *ctx;
     67 
     68   /**
     69    * Start of validity period.
     70    */
     71   struct GNUNET_TIME_Timestamp validity_start;
     72 
     73   /**
     74    * End of validity period.
     75    */
     76   struct GNUNET_TIME_Timestamp validity_end;
     77 
     78   /**
     79    * Global fees for this time period.
     80    */
     81   struct TALER_GlobalFeeSet fees;
     82 
     83   /**
     84    * When do purses time out.
     85    */
     86   struct GNUNET_TIME_Relative purse_timeout;
     87 
     88   /**
     89    * How long are account histories preserved.
     90    */
     91   struct GNUNET_TIME_Relative history_expiration;
     92 
     93   /**
     94    * How many purses are free per account.
     95    */
     96   uint32_t purse_account_limit;
     97 
     98   /**
     99    * Signature affirming the global fees.
    100    */
    101   struct TALER_MasterSignatureP master_sig;
    102 
    103 };
    104 
    105 
    106 /**
    107  * Function called when we're done processing the
    108  * HTTP POST /management/global-fees request.
    109  *
    110  * @param cls the `struct TALER_EXCHANGE_PostManagementGlobalFeesHandle`
    111  * @param response_code HTTP response code, 0 on error
    112  * @param response response body, NULL if not in JSON
    113  */
    114 static void
    115 handle_global_fees_finished (void *cls,
    116                              long response_code,
    117                              const void *response)
    118 {
    119   struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh = cls;
    120   const json_t *json = response;
    121   struct TALER_EXCHANGE_PostManagementGlobalFeesResponse res = {
    122     .hr.http_status = (unsigned int) response_code,
    123     .hr.reply = json
    124   };
    125 
    126   pmgfh->job = NULL;
    127   switch (response_code)
    128   {
    129   case MHD_HTTP_NO_CONTENT:
    130     break;
    131   case MHD_HTTP_FORBIDDEN:
    132     res.hr.ec = TALER_JSON_get_error_code (json);
    133     res.hr.hint = TALER_JSON_get_error_hint (json);
    134     break;
    135   case MHD_HTTP_CONFLICT:
    136     res.hr.ec = TALER_JSON_get_error_code (json);
    137     res.hr.hint = TALER_JSON_get_error_hint (json);
    138     break;
    139   case MHD_HTTP_CONTENT_TOO_LARGE:
    140     res.hr.ec = TALER_JSON_get_error_code (json);
    141     res.hr.hint = TALER_JSON_get_error_hint (json);
    142     break;
    143   default:
    144     /* unexpected response code */
    145     GNUNET_break_op (0);
    146     res.hr.ec = TALER_JSON_get_error_code (json);
    147     res.hr.hint = TALER_JSON_get_error_hint (json);
    148     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    149                 "Unexpected response code %u/%d for exchange management set global fee\n",
    150                 (unsigned int) response_code,
    151                 (int) res.hr.ec);
    152     break;
    153   }
    154   if (NULL != pmgfh->cb)
    155   {
    156     pmgfh->cb (pmgfh->cb_cls,
    157                &res);
    158     pmgfh->cb = NULL;
    159   }
    160   TALER_EXCHANGE_post_management_global_fees_cancel (pmgfh);
    161 }
    162 
    163 
    164 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *
    165 TALER_EXCHANGE_post_management_global_fees_create (
    166   struct GNUNET_CURL_Context *ctx,
    167   const char *exchange_base_url,
    168   struct GNUNET_TIME_Timestamp validity_start,
    169   struct GNUNET_TIME_Timestamp validity_end,
    170   const struct TALER_GlobalFeeSet *fees,
    171   struct GNUNET_TIME_Relative purse_timeout,
    172   struct GNUNET_TIME_Relative history_expiration,
    173   uint32_t purse_account_limit,
    174   const struct TALER_MasterSignatureP *master_sig)
    175 {
    176   struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh;
    177 
    178   pmgfh = GNUNET_new (struct TALER_EXCHANGE_PostManagementGlobalFeesHandle);
    179   pmgfh->ctx = ctx;
    180   pmgfh->base_url = GNUNET_strdup (exchange_base_url);
    181   pmgfh->validity_start = validity_start;
    182   pmgfh->validity_end = validity_end;
    183   pmgfh->fees = *fees;
    184   pmgfh->purse_timeout = purse_timeout;
    185   pmgfh->history_expiration = history_expiration;
    186   pmgfh->purse_account_limit = purse_account_limit;
    187   pmgfh->master_sig = *master_sig;
    188   return pmgfh;
    189 }
    190 
    191 
    192 enum TALER_ErrorCode
    193 TALER_EXCHANGE_post_management_global_fees_start (
    194   struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh,
    195   TALER_EXCHANGE_PostManagementGlobalFeesCallback cb,
    196   TALER_EXCHANGE_POST_MANAGEMENT_GLOBAL_FEES_RESULT_CLOSURE *cb_cls)
    197 {
    198   CURL *eh;
    199   json_t *body;
    200 
    201   pmgfh->cb = cb;
    202   pmgfh->cb_cls = cb_cls;
    203   pmgfh->url = TALER_url_join (pmgfh->base_url,
    204                                "management/global-fee",
    205                                NULL);
    206   if (NULL == pmgfh->url)
    207   {
    208     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    209                 "Could not construct request URL.\n");
    210     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    211   }
    212   body = GNUNET_JSON_PACK (
    213     GNUNET_JSON_pack_data_auto ("master_sig",
    214                                 &pmgfh->master_sig),
    215     GNUNET_JSON_pack_timestamp ("fee_start",
    216                                 pmgfh->validity_start),
    217     GNUNET_JSON_pack_timestamp ("fee_end",
    218                                 pmgfh->validity_end),
    219     TALER_JSON_pack_amount ("history_fee",
    220                             &pmgfh->fees.history),
    221     TALER_JSON_pack_amount ("account_fee",
    222                             &pmgfh->fees.account),
    223     TALER_JSON_pack_amount ("purse_fee",
    224                             &pmgfh->fees.purse),
    225     GNUNET_JSON_pack_time_rel ("purse_timeout",
    226                                pmgfh->purse_timeout),
    227     GNUNET_JSON_pack_time_rel ("history_expiration",
    228                                pmgfh->history_expiration),
    229     GNUNET_JSON_pack_uint64 ("purse_account_limit",
    230                              pmgfh->purse_account_limit));
    231   eh = TALER_EXCHANGE_curl_easy_get_ (pmgfh->url);
    232   if ( (NULL == eh) ||
    233        (GNUNET_OK !=
    234         TALER_curl_easy_post (&pmgfh->post_ctx,
    235                               eh,
    236                               body)) )
    237   {
    238     GNUNET_break (0);
    239     if (NULL != eh)
    240       curl_easy_cleanup (eh);
    241     json_decref (body);
    242     GNUNET_free (pmgfh->url);
    243     pmgfh->url = NULL;
    244     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    245   }
    246   json_decref (body);
    247   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    248               "Requesting URL '%s'\n",
    249               pmgfh->url);
    250   pmgfh->job = GNUNET_CURL_job_add2 (pmgfh->ctx,
    251                                      eh,
    252                                      pmgfh->post_ctx.headers,
    253                                      &handle_global_fees_finished,
    254                                      pmgfh);
    255   if (NULL == pmgfh->job)
    256   {
    257     GNUNET_break (0);
    258     TALER_curl_easy_post_finished (&pmgfh->post_ctx);
    259     GNUNET_free (pmgfh->url);
    260     pmgfh->url = NULL;
    261     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    262   }
    263   return TALER_EC_NONE;
    264 }
    265 
    266 
    267 void
    268 TALER_EXCHANGE_post_management_global_fees_cancel (
    269   struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh)
    270 {
    271   if (NULL != pmgfh->job)
    272   {
    273     GNUNET_CURL_job_cancel (pmgfh->job);
    274     pmgfh->job = NULL;
    275   }
    276   TALER_curl_easy_post_finished (&pmgfh->post_ctx);
    277   GNUNET_free (pmgfh->url);
    278   GNUNET_free (pmgfh->base_url);
    279   GNUNET_free (pmgfh);
    280 }
    281 
    282 
    283 /* end of exchange_api_post-management-global-fees.c */