sync_api_object_fetch.c (5375B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as 7 published by the Free Software Foundation; either version 3, or 8 (at your 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 * @file lib/sync_api_object_fetch.c 21 * @brief Implementation of the object fetch (GET) operation 22 * @author Iván Ávalos 23 */ 24 #include "platform.h" 25 #include <curl/curl.h> 26 #include <jansson.h> 27 #include <microhttpd.h> 28 #include <gnunet/gnunet_util_lib.h> 29 #include <gnunet/gnunet_curl_lib.h> 30 #include <gnunet/gnunet_json_lib.h> 31 #include <taler/taler_json_lib.h> 32 #include <taler/taler_curl_lib.h> 33 #include <sync/sync_service.h> 34 #include <sync/sync_util.h> 35 #include "sync_api_curl_defaults.h" 36 37 38 /** 39 * Handle for an object fetch operation. 40 */ 41 struct SYNC_ObjectFetchOperation 42 { 43 44 /** 45 * The url for this request. 46 */ 47 char *url; 48 49 /** 50 * Handle for the request. 51 */ 52 struct GNUNET_CURL_Job *job; 53 54 /** 55 * Reference to the execution context. 56 */ 57 struct GNUNET_CURL_Context *ctx; 58 59 /** 60 * Function to call with the result. 61 */ 62 SYNC_ObjectFetchCallback cb; 63 64 /** 65 * Closure for @e cb. 66 */ 67 void *cb_cls; 68 69 }; 70 71 72 /** 73 * Function called when we're done processing the 74 * GET /backups/$KEY/objects/$UID request. 75 * 76 * @param cls the `struct SYNC_ObjectFetchOperation *` 77 * @param response_code HTTP response code, 0 on error 78 * @param response response body as parsed JSON, or NULL 79 */ 80 static void 81 handle_object_fetch_finished (void *cls, 82 long response_code, 83 const void *response) 84 { 85 struct SYNC_ObjectFetchOperation *op = cls; 86 const json_t *json = response; 87 unsigned int http_status = (unsigned int) response_code; 88 enum TALER_ErrorCode ec = TALER_EC_INVALID; 89 struct SYNC_ObjectEntry entry = { 0 }; 90 91 op->job = NULL; 92 switch (response_code) 93 { 94 case 0: 95 break; 96 case MHD_HTTP_OK: 97 if (NULL != json) 98 { 99 if (GNUNET_OK != 100 SYNC_object_entry_parse ((json_t *) json, 101 &entry)) 102 { 103 GNUNET_break_op (0); 104 ec = TALER_EC_GENERIC_PARAMETER_MALFORMED; 105 break; 106 } 107 ec = TALER_EC_NONE; 108 } 109 else 110 { 111 ec = TALER_EC_GENERIC_INVALID_RESPONSE; 112 } 113 break; 114 case MHD_HTTP_BAD_REQUEST: 115 case MHD_HTTP_NOT_FOUND: 116 case MHD_HTTP_INTERNAL_SERVER_ERROR: 117 default: 118 if ( (response_code >= 400) && 119 (response_code < 500) ) 120 ec = (NULL != json) 121 ? TALER_JSON_get_error_code (json) 122 : TALER_EC_GENERIC_PARAMETER_MALFORMED; 123 else if (response_code >= 500) 124 ec = (NULL != json) 125 ? TALER_JSON_get_error_code (json) 126 : TALER_EC_GENERIC_INVALID_RESPONSE; 127 break; 128 } 129 if (NULL != op->cb) 130 { 131 op->cb (op->cb_cls, 132 http_status, 133 ec, 134 (TALER_EC_NONE == ec) ? &entry.uid : NULL, 135 (TALER_EC_NONE == ec) ? entry.data_size : 0, 136 (TALER_EC_NONE == ec) ? entry.data : NULL); 137 op->cb = NULL; 138 } 139 if (TALER_EC_NONE == ec) 140 SYNC_object_entry_clear (&entry); 141 SYNC_object_fetch_cancel (op); 142 } 143 144 145 struct SYNC_ObjectFetchOperation * 146 SYNC_object_fetch (struct GNUNET_CURL_Context *ctx, 147 const char *base_url, 148 const struct SYNC_AccountPublicKeyP *pub, 149 const struct SYNC_ObjectUID *uid, 150 SYNC_ObjectFetchCallback cb, 151 void *cb_cls) 152 { 153 struct SYNC_ObjectFetchOperation *op; 154 CURL *eh; 155 char *pub_s; 156 char *uid_s; 157 char *path; 158 char *url; 159 160 pub_s = GNUNET_STRINGS_data_to_string_alloc (pub, 161 sizeof (*pub)); 162 uid_s = GNUNET_STRINGS_data_to_string_alloc (uid, 163 sizeof (*uid)); 164 GNUNET_asprintf (&path, 165 "backups/%s/objects/%s", 166 pub_s, 167 uid_s); 168 GNUNET_free (pub_s); 169 GNUNET_free (uid_s); 170 url = TALER_url_join (base_url, 171 path, 172 NULL); 173 GNUNET_free (path); 174 if (NULL == url) 175 { 176 GNUNET_break (0); 177 return NULL; 178 } 179 180 op = GNUNET_new (struct SYNC_ObjectFetchOperation); 181 op->ctx = ctx; 182 op->cb = cb; 183 op->cb_cls = cb_cls; 184 op->url = url; 185 186 eh = SYNC_curl_easy_get_ (op->url); 187 if (NULL == eh) 188 { 189 GNUNET_break (0); 190 GNUNET_free (op->url); 191 GNUNET_free (op); 192 return NULL; 193 } 194 195 op->job = GNUNET_CURL_job_add2 (ctx, 196 eh, 197 NULL, 198 &handle_object_fetch_finished, 199 op); 200 return op; 201 } 202 203 204 void 205 SYNC_object_fetch_cancel (struct SYNC_ObjectFetchOperation *op) 206 { 207 if (NULL != op->job) 208 { 209 GNUNET_CURL_job_cancel (op->job); 210 op->job = NULL; 211 } 212 GNUNET_free (op->url); 213 GNUNET_free (op); 214 } 215 216 217 /* end of sync_api_object_fetch.c */