exchange_api_post-management-wire-fee.c (7431B)
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-wire-fee.c 19 * @brief functions to set wire fees at an exchange 20 * @author Christian Grothoff 21 */ 22 #include "taler/platform.h" 23 #include "taler/taler_json_lib.h" 24 #include <gnunet/gnunet_curl_lib.h> 25 #include <microhttpd.h> 26 #include "taler/taler_exchange_service.h" 27 #include "taler/taler-exchange/post-management-wire-fee.h" 28 #include "exchange_api_curl_defaults.h" 29 #include "taler/taler_signatures.h" 30 #include "taler/taler_curl_lib.h" 31 32 33 struct TALER_EXCHANGE_PostManagementWireFeesHandle 34 { 35 36 /** 37 * The base URL for this request. 38 */ 39 char *base_url; 40 41 /** 42 * The full URL for this request, set during _start. 43 */ 44 char *url; 45 46 /** 47 * Minor context that holds body and headers. 48 */ 49 struct TALER_CURL_PostContext post_ctx; 50 51 /** 52 * Handle for the request. 53 */ 54 struct GNUNET_CURL_Job *job; 55 56 /** 57 * Function to call with the result. 58 */ 59 TALER_EXCHANGE_PostManagementWireFeesCallback cb; 60 61 /** 62 * Closure for @a cb. 63 */ 64 TALER_EXCHANGE_POST_MANAGEMENT_WIRE_FEES_RESULT_CLOSURE *cb_cls; 65 66 /** 67 * Reference to the execution context. 68 */ 69 struct GNUNET_CURL_Context *ctx; 70 71 /** 72 * Wire method these fees are for. 73 */ 74 char *wire_method; 75 76 /** 77 * Start of validity period. 78 */ 79 struct GNUNET_TIME_Timestamp validity_start; 80 81 /** 82 * End of validity period. 83 */ 84 struct GNUNET_TIME_Timestamp validity_end; 85 86 /** 87 * Wire fees for this time period. 88 */ 89 struct TALER_WireFeeSet fees; 90 91 /** 92 * Signature affirming the wire fees. 93 */ 94 struct TALER_MasterSignatureP master_sig; 95 96 }; 97 98 99 /** 100 * Function called when we're done processing the 101 * HTTP POST /management/wire-fees request. 102 * 103 * @param cls the `struct TALER_EXCHANGE_PostManagementWireFeesHandle` 104 * @param response_code HTTP response code, 0 on error 105 * @param response response body, NULL if not in JSON 106 */ 107 static void 108 handle_wire_fees_finished (void *cls, 109 long response_code, 110 const void *response) 111 { 112 struct TALER_EXCHANGE_PostManagementWireFeesHandle *pmwfh = cls; 113 const json_t *json = response; 114 struct TALER_EXCHANGE_PostManagementWireFeesResponse res = { 115 .hr.http_status = (unsigned int) response_code, 116 .hr.reply = json 117 }; 118 119 pmwfh->job = NULL; 120 switch (response_code) 121 { 122 case MHD_HTTP_NO_CONTENT: 123 break; 124 case MHD_HTTP_FORBIDDEN: 125 res.hr.ec = TALER_JSON_get_error_code (json); 126 res.hr.hint = TALER_JSON_get_error_hint (json); 127 break; 128 case MHD_HTTP_CONFLICT: 129 res.hr.ec = TALER_JSON_get_error_code (json); 130 res.hr.hint = TALER_JSON_get_error_hint (json); 131 break; 132 default: 133 /* unexpected response code */ 134 GNUNET_break_op (0); 135 res.hr.ec = TALER_JSON_get_error_code (json); 136 res.hr.hint = TALER_JSON_get_error_hint (json); 137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 138 "Unexpected response code %u/%d for exchange management set wire fee\n", 139 (unsigned int) response_code, 140 (int) res.hr.ec); 141 break; 142 } 143 if (NULL != pmwfh->cb) 144 { 145 pmwfh->cb (pmwfh->cb_cls, 146 &res); 147 pmwfh->cb = NULL; 148 } 149 TALER_EXCHANGE_post_management_wire_fees_cancel (pmwfh); 150 } 151 152 153 struct TALER_EXCHANGE_PostManagementWireFeesHandle * 154 TALER_EXCHANGE_post_management_wire_fees_create ( 155 struct GNUNET_CURL_Context *ctx, 156 const char *exchange_base_url, 157 const char *wire_method, 158 struct GNUNET_TIME_Timestamp validity_start, 159 struct GNUNET_TIME_Timestamp validity_end, 160 const struct TALER_WireFeeSet *fees, 161 const struct TALER_MasterSignatureP *master_sig) 162 { 163 struct TALER_EXCHANGE_PostManagementWireFeesHandle *pmwfh; 164 165 pmwfh = GNUNET_new (struct TALER_EXCHANGE_PostManagementWireFeesHandle); 166 pmwfh->ctx = ctx; 167 pmwfh->base_url = GNUNET_strdup (exchange_base_url); 168 pmwfh->wire_method = GNUNET_strdup (wire_method); 169 pmwfh->validity_start = validity_start; 170 pmwfh->validity_end = validity_end; 171 pmwfh->fees = *fees; 172 pmwfh->master_sig = *master_sig; 173 return pmwfh; 174 } 175 176 177 enum TALER_ErrorCode 178 TALER_EXCHANGE_post_management_wire_fees_start ( 179 struct TALER_EXCHANGE_PostManagementWireFeesHandle *pmwfh, 180 TALER_EXCHANGE_PostManagementWireFeesCallback cb, 181 TALER_EXCHANGE_POST_MANAGEMENT_WIRE_FEES_RESULT_CLOSURE *cb_cls) 182 { 183 CURL *eh; 184 json_t *body; 185 186 pmwfh->cb = cb; 187 pmwfh->cb_cls = cb_cls; 188 pmwfh->url = TALER_url_join (pmwfh->base_url, 189 "management/wire-fee", 190 NULL); 191 if (NULL == pmwfh->url) 192 { 193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 194 "Could not construct request URL.\n"); 195 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 196 } 197 body = GNUNET_JSON_PACK ( 198 GNUNET_JSON_pack_string ("wire_method", 199 pmwfh->wire_method), 200 GNUNET_JSON_pack_data_auto ("master_sig", 201 &pmwfh->master_sig), 202 GNUNET_JSON_pack_timestamp ("fee_start", 203 pmwfh->validity_start), 204 GNUNET_JSON_pack_timestamp ("fee_end", 205 pmwfh->validity_end), 206 TALER_JSON_pack_amount ("closing_fee", 207 &pmwfh->fees.closing), 208 TALER_JSON_pack_amount ("wire_fee", 209 &pmwfh->fees.wire)); 210 eh = TALER_EXCHANGE_curl_easy_get_ (pmwfh->url); 211 if ( (NULL == eh) || 212 (GNUNET_OK != 213 TALER_curl_easy_post (&pmwfh->post_ctx, 214 eh, 215 body)) ) 216 { 217 GNUNET_break (0); 218 if (NULL != eh) 219 curl_easy_cleanup (eh); 220 json_decref (body); 221 GNUNET_free (pmwfh->url); 222 pmwfh->url = NULL; 223 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 224 } 225 json_decref (body); 226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 227 "Requesting URL '%s'\n", 228 pmwfh->url); 229 pmwfh->job = GNUNET_CURL_job_add2 (pmwfh->ctx, 230 eh, 231 pmwfh->post_ctx.headers, 232 &handle_wire_fees_finished, 233 pmwfh); 234 if (NULL == pmwfh->job) 235 { 236 TALER_curl_easy_post_finished (&pmwfh->post_ctx); 237 GNUNET_free (pmwfh->url); 238 pmwfh->url = NULL; 239 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 240 } 241 return TALER_EC_NONE; 242 } 243 244 245 void 246 TALER_EXCHANGE_post_management_wire_fees_cancel ( 247 struct TALER_EXCHANGE_PostManagementWireFeesHandle *pmwfh) 248 { 249 if (NULL != pmwfh->job) 250 { 251 GNUNET_CURL_job_cancel (pmwfh->job); 252 pmwfh->job = NULL; 253 } 254 TALER_curl_easy_post_finished (&pmwfh->post_ctx); 255 GNUNET_free (pmwfh->wire_method); 256 GNUNET_free (pmwfh->url); 257 GNUNET_free (pmwfh->base_url); 258 GNUNET_free (pmwfh); 259 } 260 261 262 /* end of exchange_api_post-management-wire-fee.c */