exchange_api_post-management-extensions.c (7302B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2015-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-extensions.c 19 * @brief functions to handle the settings for extensions (p2p and age restriction) 20 * @author Özgür Kesim 21 */ 22 #include "taler/platform.h" 23 #include "taler/taler_json_lib.h" 24 #include <gnunet/gnunet_curl_lib.h> 25 #include "taler/taler_extensions.h" 26 #include "taler/taler_exchange_service.h" 27 #include "taler/taler-exchange/post-management-extensions.h" 28 #include "exchange_api_curl_defaults.h" 29 #include "taler/taler_signatures.h" 30 #include "taler/taler_curl_lib.h" 31 32 33 /** 34 * @brief Handle for a POST /management/extensions request. 35 */ 36 struct TALER_EXCHANGE_PostManagementExtensionsHandle 37 { 38 39 /** 40 * The base URL for this request. 41 */ 42 char *base_url; 43 44 /** 45 * The full URL for this request, set during _start. 46 */ 47 char *url; 48 49 /** 50 * Minor context that holds body and headers. 51 */ 52 struct TALER_CURL_PostContext post_ctx; 53 54 /** 55 * Handle for the request. 56 */ 57 struct GNUNET_CURL_Job *job; 58 59 /** 60 * Function to call with the result. 61 */ 62 TALER_EXCHANGE_PostManagementExtensionsCallback cb; 63 64 /** 65 * Closure for @a cb. 66 */ 67 TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cb_cls; 68 69 /** 70 * Reference to the execution context. 71 */ 72 struct GNUNET_CURL_Context *ctx; 73 74 /** 75 * Extension configuration data (we hold a reference). 76 */ 77 json_t *extensions; 78 79 /** 80 * Signature over the extension configuration. 81 */ 82 struct TALER_MasterSignatureP extensions_sig; 83 84 }; 85 86 87 /** 88 * Function called when we're done processing the 89 * HTTP POST /management/extensions request. 90 * 91 * @param cls the `struct TALER_EXCHANGE_PostManagementExtensionsHandle` 92 * @param response_code HTTP response code, 0 on error 93 * @param response response body, NULL if not in JSON 94 */ 95 static void 96 handle_post_extensions_finished (void *cls, 97 long response_code, 98 const void *response) 99 { 100 struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh = cls; 101 const json_t *json = response; 102 struct TALER_EXCHANGE_PostManagementExtensionsResponse res = { 103 .hr.http_status = (unsigned int) response_code, 104 .hr.reply = json 105 }; 106 107 pmeh->job = NULL; 108 switch (response_code) 109 { 110 case MHD_HTTP_NO_CONTENT: 111 break; 112 case MHD_HTTP_FORBIDDEN: 113 res.hr.ec = TALER_JSON_get_error_code (json); 114 res.hr.hint = TALER_JSON_get_error_hint (json); 115 break; 116 case MHD_HTTP_NOT_FOUND: 117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 118 "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", 119 pmeh->url); 120 if (NULL != json) 121 { 122 res.hr.ec = TALER_JSON_get_error_code (json); 123 res.hr.hint = TALER_JSON_get_error_hint (json); 124 } 125 else 126 { 127 res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 128 res.hr.hint = TALER_ErrorCode_get_hint (res.hr.ec); 129 } 130 break; 131 default: 132 /* unexpected response code */ 133 GNUNET_break_op (0); 134 res.hr.ec = TALER_JSON_get_error_code (json); 135 res.hr.hint = TALER_JSON_get_error_hint (json); 136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 137 "Unexpected response code %u/%d for exchange management post extensions\n", 138 (unsigned int) response_code, 139 (int) res.hr.ec); 140 break; 141 } 142 if (NULL != pmeh->cb) 143 { 144 pmeh->cb (pmeh->cb_cls, 145 &res); 146 pmeh->cb = NULL; 147 } 148 TALER_EXCHANGE_post_management_extensions_cancel (pmeh); 149 } 150 151 152 struct TALER_EXCHANGE_PostManagementExtensionsHandle * 153 TALER_EXCHANGE_post_management_extensions_create ( 154 struct GNUNET_CURL_Context *ctx, 155 const char *url, 156 const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped) 157 { 158 struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh; 159 160 pmeh = GNUNET_new (struct TALER_EXCHANGE_PostManagementExtensionsHandle); 161 pmeh->ctx = ctx; 162 pmeh->base_url = GNUNET_strdup (url); 163 pmeh->extensions = json_incref ((json_t *) ped->extensions); 164 pmeh->extensions_sig = ped->extensions_sig; 165 return pmeh; 166 } 167 168 169 enum TALER_ErrorCode 170 TALER_EXCHANGE_post_management_extensions_start ( 171 struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh, 172 TALER_EXCHANGE_PostManagementExtensionsCallback cb, 173 TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cb_cls) 174 { 175 CURL *eh = NULL; 176 json_t *body = NULL; 177 json_t *extensions; 178 179 pmeh->cb = cb; 180 pmeh->cb_cls = cb_cls; 181 pmeh->url = TALER_url_join (pmeh->base_url, 182 "management/extensions", 183 NULL); 184 if (NULL == pmeh->url) 185 { 186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 187 "Could not construct request URL.\n"); 188 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 189 } 190 /* Transfer our reference to the body via steal; set to NULL first */ 191 extensions = pmeh->extensions; 192 pmeh->extensions = NULL; 193 body = GNUNET_JSON_PACK ( 194 GNUNET_JSON_pack_object_steal ("extensions", 195 extensions), 196 GNUNET_JSON_pack_data_auto ("extensions_sig", 197 &pmeh->extensions_sig)); 198 eh = TALER_EXCHANGE_curl_easy_get_ (pmeh->url); 199 if ( (NULL == eh) || 200 (GNUNET_OK != 201 TALER_curl_easy_post (&pmeh->post_ctx, 202 eh, 203 body)) ) 204 { 205 GNUNET_break (0); 206 if (NULL != eh) 207 curl_easy_cleanup (eh); 208 json_decref (body); 209 GNUNET_free (pmeh->url); 210 pmeh->url = NULL; 211 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 212 } 213 json_decref (body); 214 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 215 "Requesting URL '%s'\n", 216 pmeh->url); 217 pmeh->job = GNUNET_CURL_job_add2 (pmeh->ctx, 218 eh, 219 pmeh->post_ctx.headers, 220 &handle_post_extensions_finished, 221 pmeh); 222 if (NULL == pmeh->job) 223 { 224 TALER_curl_easy_post_finished (&pmeh->post_ctx); 225 GNUNET_free (pmeh->url); 226 pmeh->url = NULL; 227 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 228 } 229 return TALER_EC_NONE; 230 } 231 232 233 void 234 TALER_EXCHANGE_post_management_extensions_cancel ( 235 struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh) 236 { 237 if (NULL != pmeh->job) 238 { 239 GNUNET_CURL_job_cancel (pmeh->job); 240 pmeh->job = NULL; 241 } 242 TALER_curl_easy_post_finished (&pmeh->post_ctx); 243 if (NULL != pmeh->extensions) 244 { 245 json_decref (pmeh->extensions); 246 pmeh->extensions = NULL; 247 } 248 GNUNET_free (pmeh->url); 249 GNUNET_free (pmeh->base_url); 250 GNUNET_free (pmeh); 251 } 252 253 254 /* end of exchange_api_post-management-extensions.c */