exchange_api_post-management-global-fees.c (8370B)
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/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-global-fees.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_PostManagementGlobalFeesHandle 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_PostManagementGlobalFeesCallback cb; 60 61 /** 62 * Closure for @a cb. 63 */ 64 TALER_EXCHANGE_POST_MANAGEMENT_GLOBAL_FEES_RESULT_CLOSURE *cb_cls; 65 66 /** 67 * Reference to the execution context. 68 */ 69 struct GNUNET_CURL_Context *ctx; 70 71 /** 72 * Start of validity period. 73 */ 74 struct GNUNET_TIME_Timestamp validity_start; 75 76 /** 77 * End of validity period. 78 */ 79 struct GNUNET_TIME_Timestamp validity_end; 80 81 /** 82 * Global fees for this time period. 83 */ 84 struct TALER_GlobalFeeSet fees; 85 86 /** 87 * When do purses time out. 88 */ 89 struct GNUNET_TIME_Relative purse_timeout; 90 91 /** 92 * How long are account histories preserved. 93 */ 94 struct GNUNET_TIME_Relative history_expiration; 95 96 /** 97 * How many purses are free per account. 98 */ 99 uint32_t purse_account_limit; 100 101 /** 102 * Signature affirming the global fees. 103 */ 104 struct TALER_MasterSignatureP master_sig; 105 106 }; 107 108 109 /** 110 * Function called when we're done processing the 111 * HTTP POST /management/global-fees request. 112 * 113 * @param cls the `struct TALER_EXCHANGE_PostManagementGlobalFeesHandle` 114 * @param response_code HTTP response code, 0 on error 115 * @param response response body, NULL if not in JSON 116 */ 117 static void 118 handle_global_fees_finished (void *cls, 119 long response_code, 120 const void *response) 121 { 122 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh = cls; 123 const json_t *json = response; 124 struct TALER_EXCHANGE_PostManagementGlobalFeesResponse res = { 125 .hr.http_status = (unsigned int) response_code, 126 .hr.reply = json 127 }; 128 129 pmgfh->job = NULL; 130 switch (response_code) 131 { 132 case MHD_HTTP_NO_CONTENT: 133 break; 134 case MHD_HTTP_FORBIDDEN: 135 res.hr.ec = TALER_JSON_get_error_code (json); 136 res.hr.hint = TALER_JSON_get_error_hint (json); 137 break; 138 case MHD_HTTP_CONFLICT: 139 res.hr.ec = TALER_JSON_get_error_code (json); 140 res.hr.hint = TALER_JSON_get_error_hint (json); 141 break; 142 case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE: 143 res.hr.ec = TALER_JSON_get_error_code (json); 144 res.hr.hint = TALER_JSON_get_error_hint (json); 145 break; 146 default: 147 /* unexpected response code */ 148 GNUNET_break_op (0); 149 res.hr.ec = TALER_JSON_get_error_code (json); 150 res.hr.hint = TALER_JSON_get_error_hint (json); 151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 152 "Unexpected response code %u/%d for exchange management set global fee\n", 153 (unsigned int) response_code, 154 (int) res.hr.ec); 155 break; 156 } 157 if (NULL != pmgfh->cb) 158 { 159 pmgfh->cb (pmgfh->cb_cls, 160 &res); 161 pmgfh->cb = NULL; 162 } 163 TALER_EXCHANGE_post_management_global_fees_cancel (pmgfh); 164 } 165 166 167 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle * 168 TALER_EXCHANGE_post_management_global_fees_create ( 169 struct GNUNET_CURL_Context *ctx, 170 const char *exchange_base_url, 171 struct GNUNET_TIME_Timestamp validity_start, 172 struct GNUNET_TIME_Timestamp validity_end, 173 const struct TALER_GlobalFeeSet *fees, 174 struct GNUNET_TIME_Relative purse_timeout, 175 struct GNUNET_TIME_Relative history_expiration, 176 uint32_t purse_account_limit, 177 const struct TALER_MasterSignatureP *master_sig) 178 { 179 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh; 180 181 pmgfh = GNUNET_new (struct TALER_EXCHANGE_PostManagementGlobalFeesHandle); 182 pmgfh->ctx = ctx; 183 pmgfh->base_url = GNUNET_strdup (exchange_base_url); 184 pmgfh->validity_start = validity_start; 185 pmgfh->validity_end = validity_end; 186 pmgfh->fees = *fees; 187 pmgfh->purse_timeout = purse_timeout; 188 pmgfh->history_expiration = history_expiration; 189 pmgfh->purse_account_limit = purse_account_limit; 190 pmgfh->master_sig = *master_sig; 191 return pmgfh; 192 } 193 194 195 enum TALER_ErrorCode 196 TALER_EXCHANGE_post_management_global_fees_start ( 197 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh, 198 TALER_EXCHANGE_PostManagementGlobalFeesCallback cb, 199 TALER_EXCHANGE_POST_MANAGEMENT_GLOBAL_FEES_RESULT_CLOSURE *cb_cls) 200 { 201 CURL *eh; 202 json_t *body; 203 204 pmgfh->cb = cb; 205 pmgfh->cb_cls = cb_cls; 206 pmgfh->url = TALER_url_join (pmgfh->base_url, 207 "management/global-fee", 208 NULL); 209 if (NULL == pmgfh->url) 210 { 211 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 212 "Could not construct request URL.\n"); 213 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 214 } 215 body = GNUNET_JSON_PACK ( 216 GNUNET_JSON_pack_data_auto ("master_sig", 217 &pmgfh->master_sig), 218 GNUNET_JSON_pack_timestamp ("fee_start", 219 pmgfh->validity_start), 220 GNUNET_JSON_pack_timestamp ("fee_end", 221 pmgfh->validity_end), 222 TALER_JSON_pack_amount ("history_fee", 223 &pmgfh->fees.history), 224 TALER_JSON_pack_amount ("account_fee", 225 &pmgfh->fees.account), 226 TALER_JSON_pack_amount ("purse_fee", 227 &pmgfh->fees.purse), 228 GNUNET_JSON_pack_time_rel ("purse_timeout", 229 pmgfh->purse_timeout), 230 GNUNET_JSON_pack_time_rel ("history_expiration", 231 pmgfh->history_expiration), 232 GNUNET_JSON_pack_uint64 ("purse_account_limit", 233 pmgfh->purse_account_limit)); 234 eh = TALER_EXCHANGE_curl_easy_get_ (pmgfh->url); 235 if ( (NULL == eh) || 236 (GNUNET_OK != 237 TALER_curl_easy_post (&pmgfh->post_ctx, 238 eh, 239 body)) ) 240 { 241 GNUNET_break (0); 242 if (NULL != eh) 243 curl_easy_cleanup (eh); 244 json_decref (body); 245 GNUNET_free (pmgfh->url); 246 pmgfh->url = NULL; 247 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 248 } 249 json_decref (body); 250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 251 "Requesting URL '%s'\n", 252 pmgfh->url); 253 pmgfh->job = GNUNET_CURL_job_add2 (pmgfh->ctx, 254 eh, 255 pmgfh->post_ctx.headers, 256 &handle_global_fees_finished, 257 pmgfh); 258 if (NULL == pmgfh->job) 259 { 260 GNUNET_break (0); 261 TALER_curl_easy_post_finished (&pmgfh->post_ctx); 262 GNUNET_free (pmgfh->url); 263 pmgfh->url = NULL; 264 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 265 } 266 return TALER_EC_NONE; 267 } 268 269 270 void 271 TALER_EXCHANGE_post_management_global_fees_cancel ( 272 struct TALER_EXCHANGE_PostManagementGlobalFeesHandle *pmgfh) 273 { 274 if (NULL != pmgfh->job) 275 { 276 GNUNET_CURL_job_cancel (pmgfh->job); 277 pmgfh->job = NULL; 278 } 279 TALER_curl_easy_post_finished (&pmgfh->post_ctx); 280 GNUNET_free (pmgfh->url); 281 GNUNET_free (pmgfh->base_url); 282 GNUNET_free (pmgfh); 283 } 284 285 286 /* end of exchange_api_post-management-global-fees.c */