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