donau_api_csr_post.c (6421B)
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 } 114 csrh->cb (csrh->cb_cls, 115 &csrresp); 116 csrh->cb = NULL; 117 GNUNET_JSON_parse_free (spec); 118 break; 119 } 120 // Donation unit was revoked. 121 case MHD_HTTP_GONE: 122 csrresp.hr.ec = TALER_JSON_get_error_code (j); 123 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 124 break; 125 // Donation unit or endpoint not found. 126 case MHD_HTTP_NOT_FOUND: 127 csrresp.hr.ec = TALER_JSON_get_error_code (j); 128 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 129 break; 130 case MHD_HTTP_BAD_REQUEST: 131 csrresp.hr.ec = TALER_JSON_get_error_code (j); 132 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 133 break; 134 default: 135 /* unexpected response code */ 136 GNUNET_break_op (0); 137 csrresp.hr.ec = TALER_JSON_get_error_code (j); 138 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 140 "Unexpected response code %u/%d for POST %s\n", 141 (unsigned int) response_code, 142 (int) csrresp.hr.ec, 143 csrh->url); 144 break; 145 } 146 if (NULL != csrh->cb) 147 { 148 csrh->cb (csrh->cb_cls, 149 &csrresp); 150 csrh->cb = NULL; 151 } 152 DONAU_csr_cancel (csrh); 153 } 154 155 156 struct DONAU_CsRBatchIssueHandle * 157 DONAU_csr_issue ( 158 struct GNUNET_CURL_Context *ctx, 159 const char *url, 160 const struct DONAU_DonationUnitPublicKey *pk, 161 const struct GNUNET_CRYPTO_CsSessionNonce *nonce, 162 DONAU_CsRBatchIssueCallback cb, 163 void *cb_cls) 164 { 165 struct DONAU_CsRBatchIssueHandle *csrh; 166 CURL *eh; 167 json_t *body; 168 169 struct DONAU_DonationUnitHashP h_donation_unit_pub; 170 DONAU_donation_unit_pub_hash (pk, 171 &h_donation_unit_pub); 172 173 TALER_LOG_DEBUG ("Connecting to the donau (%s)\n", 174 url); 175 csrh = GNUNET_new (struct DONAU_CsRBatchIssueHandle); 176 csrh->cb = cb; 177 csrh->cb_cls = cb_cls; 178 csrh->ctx = ctx; 179 csrh->url = TALER_url_join (url, 180 "csr-issue", 181 NULL); 182 if (NULL == csrh->url) 183 { 184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 185 "Could not construct requested URL.\n"); 186 GNUNET_free (csrh); 187 return NULL; 188 } 189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 190 "Request CS R with URL `%s'.\n", 191 csrh->url); 192 body = GNUNET_JSON_PACK ( 193 GNUNET_JSON_pack_data_varsize ("nonce", 194 nonce, 195 sizeof(*nonce)), 196 GNUNET_JSON_pack_data_varsize ("du_pub_hash", 197 &h_donation_unit_pub, 198 sizeof(h_donation_unit_pub))); 199 eh = DONAU_curl_easy_get_ (csrh->url); 200 if ( (NULL == eh) || 201 (GNUNET_OK != 202 TALER_curl_easy_post (&csrh->post_ctx, 203 eh, 204 body)) ) 205 { 206 GNUNET_break (0); 207 if (NULL != eh) 208 curl_easy_cleanup (eh); 209 json_decref (body); 210 GNUNET_free (csrh->url); 211 GNUNET_free (csrh); 212 return NULL; 213 } 214 json_decref (body); 215 csrh->job = GNUNET_CURL_job_add2 (ctx, 216 eh, 217 csrh->post_ctx.headers, 218 &handle_csr_issue_post_finished, 219 csrh); 220 return csrh; 221 } 222 223 224 void 225 DONAU_csr_cancel ( 226 struct DONAU_CsRBatchIssueHandle *csrh) 227 { 228 if (NULL != csrh->job) 229 { 230 GNUNET_CURL_job_cancel (csrh->job); 231 csrh->job = NULL; 232 } 233 TALER_curl_easy_post_finished (&csrh->post_ctx); 234 GNUNET_free (csrh->url); 235 GNUNET_free (csrh); 236 }