donau_api_csr_post.c (6392B)
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 "ewv", 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 break; 118 } 119 // Donation unit was revoked. 120 case MHD_HTTP_GONE: 121 csrresp.hr.ec = TALER_JSON_get_error_code (j); 122 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 123 break; 124 // Donation unit or endpoint not found. 125 case MHD_HTTP_NOT_FOUND: 126 csrresp.hr.ec = TALER_JSON_get_error_code (j); 127 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 128 break; 129 case MHD_HTTP_BAD_REQUEST: 130 csrresp.hr.ec = TALER_JSON_get_error_code (j); 131 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 132 break; 133 default: 134 /* unexpected response code */ 135 GNUNET_break_op (0); 136 csrresp.hr.ec = TALER_JSON_get_error_code (j); 137 csrresp.hr.hint = TALER_JSON_get_error_hint (j); 138 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 139 "Unexpected response code %u/%d for POST %s\n", 140 (unsigned int) response_code, 141 (int) csrresp.hr.ec, 142 csrh->url); 143 break; 144 } 145 if (NULL != csrh->cb) 146 { 147 csrh->cb (csrh->cb_cls, 148 &csrresp); 149 csrh->cb = NULL; 150 } 151 DONAU_csr_cancel (csrh); 152 } 153 154 155 struct DONAU_CsRBatchIssueHandle * 156 DONAU_csr_issue ( 157 struct GNUNET_CURL_Context *ctx, 158 const char *url, 159 const struct DONAU_DonationUnitPublicKey *pk, 160 const struct GNUNET_CRYPTO_CsSessionNonce *nonce, 161 DONAU_CsRBatchIssueCallback cb, 162 void *cb_cls) 163 { 164 struct DONAU_CsRBatchIssueHandle *csrh; 165 CURL *eh; 166 json_t *body; 167 168 struct DONAU_DonationUnitHashP h_donation_unit_pub; 169 DONAU_donation_unit_pub_hash (pk, 170 &h_donation_unit_pub); 171 172 TALER_LOG_DEBUG ("Connecting to the donau (%s)\n", 173 url); 174 csrh = GNUNET_new (struct DONAU_CsRBatchIssueHandle); 175 csrh->url = GNUNET_strdup (url); 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 return NULL; 212 } 213 json_decref (body); 214 csrh->job = GNUNET_CURL_job_add2 (ctx, 215 eh, 216 csrh->post_ctx.headers, 217 &handle_csr_issue_post_finished, 218 csrh); 219 return csrh; 220 } 221 222 223 void 224 DONAU_csr_cancel ( 225 struct DONAU_CsRBatchIssueHandle *csrh) 226 { 227 if (NULL != csrh->job) 228 { 229 GNUNET_CURL_job_cancel (csrh->job); 230 csrh->job = NULL; 231 } 232 TALER_curl_easy_post_finished (&csrh->post_ctx); 233 GNUNET_free (csrh->url); 234 GNUNET_free (csrh); 235 }