exchange

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

exchange_api_purse_delete.c (7133B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022 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_purse_delete.c
     19  * @brief Implementation of the client to delete a purse
     20  *        into an account
     21  * @author Christian Grothoff
     22  */
     23 #include "taler/platform.h"
     24 #include <jansson.h>
     25 #include <microhttpd.h> /* just for HTTP status codes */
     26 #include <gnunet/gnunet_util_lib.h>
     27 #include <gnunet/gnunet_json_lib.h>
     28 #include <gnunet/gnunet_curl_lib.h>
     29 #include "taler/taler_json_lib.h"
     30 #include "taler/taler_exchange_service.h"
     31 #include "exchange_api_handle.h"
     32 #include "exchange_api_common.h"
     33 #include "taler/taler_signatures.h"
     34 #include "exchange_api_curl_defaults.h"
     35 
     36 
     37 /**
     38  * @brief A purse delete with deposit handle
     39  */
     40 struct TALER_EXCHANGE_PurseDeleteHandle
     41 {
     42 
     43   /**
     44    * The url for this request.
     45    */
     46   char *url;
     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_PurseDeleteCallback cb;
     57 
     58   /**
     59    * Closure for @a cb.
     60    */
     61   void *cb_cls;
     62 
     63   /**
     64    * Header with the purse_sig.
     65    */
     66   struct curl_slist *xhdr;
     67 };
     68 
     69 
     70 /**
     71  * Function called when we're done processing the
     72  * HTTP DELETE /purse/$PID request.
     73  *
     74  * @param cls the `struct TALER_EXCHANGE_PurseDeleteHandle`
     75  * @param response_code HTTP response code, 0 on error
     76  * @param response parsed JSON result, NULL on error
     77  */
     78 static void
     79 handle_purse_delete_finished (void *cls,
     80                               long response_code,
     81                               const void *response)
     82 {
     83   struct TALER_EXCHANGE_PurseDeleteHandle *pdh = cls;
     84   const json_t *j = response;
     85   struct TALER_EXCHANGE_PurseDeleteResponse dr = {
     86     .hr.reply = j,
     87     .hr.http_status = (unsigned int) response_code
     88   };
     89 
     90   pdh->job = NULL;
     91   switch (response_code)
     92   {
     93   case 0:
     94     dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     95     break;
     96   case MHD_HTTP_NO_CONTENT:
     97     break;
     98   case MHD_HTTP_BAD_REQUEST:
     99     /* This should never happen, either us or the exchange is buggy
    100        (or API version conflict); just pass JSON reply to the application */
    101     dr.hr.ec = TALER_JSON_get_error_code (j);
    102     dr.hr.hint = TALER_JSON_get_error_hint (j);
    103     break;
    104   case MHD_HTTP_FORBIDDEN:
    105     dr.hr.ec = TALER_JSON_get_error_code (j);
    106     dr.hr.hint = TALER_JSON_get_error_hint (j);
    107     /* Nothing really to verify, exchange says one of the signatures is
    108        invalid; as we checked them, this should never happen, we
    109        should pass the JSON reply to the application */
    110     break;
    111   case MHD_HTTP_NOT_FOUND:
    112     dr.hr.ec = TALER_JSON_get_error_code (j);
    113     dr.hr.hint = TALER_JSON_get_error_hint (j);
    114     /* Nothing really to verify, this should never
    115        happen, we should pass the JSON reply to the application */
    116     break;
    117   case MHD_HTTP_CONFLICT:
    118     dr.hr.ec = TALER_JSON_get_error_code (j);
    119     dr.hr.hint = TALER_JSON_get_error_hint (j);
    120     break;
    121   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    122     dr.hr.ec = TALER_JSON_get_error_code (j);
    123     dr.hr.hint = TALER_JSON_get_error_hint (j);
    124     /* Server had an internal issue; we should retry, but this API
    125        leaves this to the application */
    126     break;
    127   default:
    128     /* unexpected response code */
    129     dr.hr.ec = TALER_JSON_get_error_code (j);
    130     dr.hr.hint = TALER_JSON_get_error_hint (j);
    131     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    132                 "Unexpected response code %u/%d for exchange deposit\n",
    133                 (unsigned int) response_code,
    134                 dr.hr.ec);
    135     GNUNET_break_op (0);
    136     break;
    137   }
    138   pdh->cb (pdh->cb_cls,
    139            &dr);
    140   TALER_EXCHANGE_purse_delete_cancel (pdh);
    141 }
    142 
    143 
    144 struct TALER_EXCHANGE_PurseDeleteHandle *
    145 TALER_EXCHANGE_purse_delete (
    146   struct GNUNET_CURL_Context *ctx,
    147   const char *url,
    148   const struct TALER_PurseContractPrivateKeyP *purse_priv,
    149   TALER_EXCHANGE_PurseDeleteCallback cb,
    150   void *cb_cls)
    151 {
    152   struct TALER_EXCHANGE_PurseDeleteHandle *pdh;
    153   CURL *eh;
    154   struct TALER_PurseContractPublicKeyP purse_pub;
    155   struct TALER_PurseContractSignatureP purse_sig;
    156   char arg_str[sizeof (purse_pub) * 2 + 32];
    157 
    158   pdh = GNUNET_new (struct TALER_EXCHANGE_PurseDeleteHandle);
    159   pdh->cb = cb;
    160   pdh->cb_cls = cb_cls;
    161   GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv,
    162                                       &purse_pub.eddsa_pub);
    163   {
    164     char pub_str[sizeof (purse_pub) * 2];
    165     char *end;
    166 
    167     end = GNUNET_STRINGS_data_to_string (&purse_pub,
    168                                          sizeof (purse_pub),
    169                                          pub_str,
    170                                          sizeof (pub_str));
    171     *end = '\0';
    172     GNUNET_snprintf (arg_str,
    173                      sizeof (arg_str),
    174                      "purses/%s",
    175                      pub_str);
    176   }
    177   pdh->url = TALER_url_join (url,
    178                              arg_str,
    179                              NULL);
    180   if (NULL == pdh->url)
    181   {
    182     GNUNET_break (0);
    183     GNUNET_free (pdh);
    184     return NULL;
    185   }
    186   TALER_wallet_purse_delete_sign (purse_priv,
    187                                   &purse_sig);
    188   {
    189     char *delete_str;
    190     char *xhdr;
    191 
    192     delete_str =
    193       GNUNET_STRINGS_data_to_string_alloc (&purse_sig,
    194                                            sizeof (purse_sig));
    195     GNUNET_asprintf (&xhdr,
    196                      "Taler-Purse-Signature: %s",
    197                      delete_str);
    198     GNUNET_free (delete_str);
    199     pdh->xhdr = curl_slist_append (NULL,
    200                                    xhdr);
    201     GNUNET_free (xhdr);
    202   }
    203   eh = TALER_EXCHANGE_curl_easy_get_ (pdh->url);
    204   if (NULL == eh)
    205   {
    206     GNUNET_break (0);
    207     curl_slist_free_all (pdh->xhdr);
    208     GNUNET_free (pdh->url);
    209     GNUNET_free (pdh);
    210     return NULL;
    211   }
    212   GNUNET_assert (CURLE_OK ==
    213                  curl_easy_setopt (eh,
    214                                    CURLOPT_CUSTOMREQUEST,
    215                                    MHD_HTTP_METHOD_DELETE));
    216   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    217               "URL for purse delete: `%s'\n",
    218               pdh->url);
    219   pdh->job = GNUNET_CURL_job_add2 (ctx,
    220                                    eh,
    221                                    pdh->xhdr,
    222                                    &handle_purse_delete_finished,
    223                                    pdh);
    224   return pdh;
    225 }
    226 
    227 
    228 void
    229 TALER_EXCHANGE_purse_delete_cancel (
    230   struct TALER_EXCHANGE_PurseDeleteHandle *pdh)
    231 {
    232   if (NULL != pdh->job)
    233   {
    234     GNUNET_CURL_job_cancel (pdh->job);
    235     pdh->job = NULL;
    236   }
    237   curl_slist_free_all (pdh->xhdr);
    238   GNUNET_free (pdh->url);
    239   GNUNET_free (pdh);
    240 }
    241 
    242 
    243 /* end of exchange_api_purse_delete.c */