sync

Backup service to store encrypted wallet databases (experimental)
Log | Files | Refs | Submodules | README | LICENSE

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 */