donau_api_csr_post.c (6515B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file lib/donau_api_csr_post.c 22 * @brief Implementation of the "handle" component of the donau's HTTP API 23 * @author Lukas Matyja 24 */ 25 #include <gnunet/gnunet_curl_lib.h> 26 #include <taler/taler_json_lib.h> 27 #include <taler/taler_curl_lib.h> 28 #include "donau_service.h" 29 #include "donau_api_curl_defaults.h" 30 #include "donau_json_lib.h" 31 32 33 /** 34 * Handle for a POST /csr-issue request. 35 */ 36 struct DONAU_CsRBatchIssueHandle 37 { 38 /** 39 * The url for the /csr-issue request. 40 */ 41 char *url; 42 43 /** 44 * Minor context that holds body and headers. 45 */ 46 struct TALER_CURL_PostContext post_ctx; 47 48 /** 49 * Entry for this request with the `struct GNUNET_CURL_Context`. 50 */ 51 struct GNUNET_CURL_Job *job; 52 53 /** 54 * Function to call with the result. 55 */ 56 DONAU_CsRBatchIssueCallback cb; 57 58 /** 59 * Closure to pass to @e cb. 60 */ 61 void *cb_cls; 62 63 /** 64 * Reference to the execution context. 65 */ 66 struct GNUNET_CURL_Context *ctx; 67 68 }; 69 70 /** 71 * Function called when we're done processing the 72 * HTTP POST /csr-issue request. 73 * 74 * @param cls the `struct KeysRequest` 75 * @param response_code HTTP response code, 0 on error 76 * @param resp_obj parsed JSON result, NULL on error 77 */ 78 static void 79 handle_csr_issue_post_finished (void *cls, 80 long response_code, 81 const void *resp_obj) 82 { 83 struct DONAU_CsRBatchIssueHandle *csrh = cls; 84 const json_t *j = resp_obj; 85 86 struct DONAU_CsRBatchIssueResponse csrresp = { 87 .hr.reply = j, 88 .hr.http_status = (unsigned int) response_code 89 }; 90 91 csrh->job = NULL; 92 switch (response_code) 93 { 94 case MHD_HTTP_CREATED: 95 { 96 struct GNUNET_JSON_Specification spec[] = { 97 TALER_JSON_spec_exchange_blinding_values ( 98 "r_pubs", 99 (struct TALER_ExchangeBlindingValues *) &csrresp.details.ok.alg_values 100 ), 101 GNUNET_JSON_spec_end () 102 }; 103 104 if (GNUNET_OK != 105 GNUNET_JSON_parse (j, 106 spec, 107 NULL, 108 NULL)) 109 { 110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 111 "Could not parse response from csr POST\n"); 112 GNUNET_break_op (0); 113 csrresp.hr.http_status = 0; 114 csrresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; 115 } 116 csrh->cb (csrh->cb_cls, 117 &csrresp); 118 csrh->cb = NULL; 119 GNUNET_JSON_parse_free (spec); 120 break; 121 } 122 // Donation unit was revoked. 123 case MHD_HTTP_GONE: 124 csrresp.hr.ec = TALER_JSON_get_error_code (j); 125 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 126 break; 127 // Donation unit or endpoint not found. 128 case MHD_HTTP_NOT_FOUND: 129 csrresp.hr.ec = TALER_JSON_get_error_code (j); 130 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 131 break; 132 case MHD_HTTP_BAD_REQUEST: 133 csrresp.hr.ec = TALER_JSON_get_error_code (j); 134 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 135 break; 136 default: 137 /* unexpected response code */ 138 GNUNET_break_op (0); 139 csrresp.hr.ec = TALER_JSON_get_error_code (j); 140 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 142 "Unexpected response code %u/%d for POST %s\n", 143 (unsigned int) response_code, 144 (int) csrresp.hr.ec, 145 csrh->url); 146 break; 147 } 148 if (NULL != csrh->cb) 149 { 150 csrh->cb (csrh->cb_cls, 151 &csrresp); 152 csrh->cb = NULL; 153 } 154 DONAU_csr_cancel (csrh); 155 } 156 157 158 struct DONAU_CsRBatchIssueHandle * 159 DONAU_csr_issue ( 160 struct GNUNET_CURL_Context *ctx, 161 const char *url, 162 const struct DONAU_DonationUnitPublicKey *pk, 163 const struct GNUNET_CRYPTO_CsSessionNonce *nonce, 164 DONAU_CsRBatchIssueCallback cb, 165 void *cb_cls) 166 { 167 struct DONAU_CsRBatchIssueHandle *csrh; 168 CURL *eh; 169 json_t *body; 170 171 struct DONAU_DonationUnitHashP h_donation_unit_pub; 172 DONAU_donation_unit_pub_hash (pk, 173 &h_donation_unit_pub); 174 175 TALER_LOG_DEBUG ("Connecting to the donau (%s)\n", 176 url); 177 csrh = GNUNET_new (struct DONAU_CsRBatchIssueHandle); 178 csrh->cb = cb; 179 csrh->cb_cls = cb_cls; 180 csrh->ctx = ctx; 181 csrh->url = TALER_url_join (url, 182 "csr-issue", 183 NULL); 184 if (NULL == csrh->url) 185 { 186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 187 "Could not construct requested URL.\n"); 188 GNUNET_free (csrh); 189 return NULL; 190 } 191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 192 "Request CS R with URL `%s'.\n", 193 csrh->url); 194 body = GNUNET_JSON_PACK ( 195 GNUNET_JSON_pack_data_varsize ("nonce", 196 nonce, 197 sizeof(*nonce)), 198 GNUNET_JSON_pack_data_varsize ("du_pub_hash", 199 &h_donation_unit_pub, 200 sizeof(h_donation_unit_pub))); 201 eh = DONAU_curl_easy_get_ (csrh->url); 202 if ( (NULL == eh) || 203 (GNUNET_OK != 204 TALER_curl_easy_post (&csrh->post_ctx, 205 eh, 206 body)) ) 207 { 208 GNUNET_break (0); 209 if (NULL != eh) 210 curl_easy_cleanup (eh); 211 json_decref (body); 212 GNUNET_free (csrh->url); 213 GNUNET_free (csrh); 214 return NULL; 215 } 216 json_decref (body); 217 csrh->job = GNUNET_CURL_job_add2 (ctx, 218 eh, 219 csrh->post_ctx.headers, 220 &handle_csr_issue_post_finished, 221 csrh); 222 return csrh; 223 } 224 225 226 void 227 DONAU_csr_cancel ( 228 struct DONAU_CsRBatchIssueHandle *csrh) 229 { 230 if (NULL != csrh->job) 231 { 232 GNUNET_CURL_job_cancel (csrh->job); 233 csrh->job = NULL; 234 } 235 TALER_curl_easy_post_finished (&csrh->post_ctx); 236 GNUNET_free (csrh->url); 237 GNUNET_free (csrh); 238 }