gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-donau] 01/03: [lib] implement charity get API


From: gnunet
Subject: [taler-donau] 01/03: [lib] implement charity get API
Date: Mon, 15 Jan 2024 10:41:20 +0100

This is an automated email from the git hooks/post-receive script.

lukas-matyja pushed a commit to branch master
in repository donau.

commit a1f8d7afc2e686377fb8b4e195111d2fa129c265
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
AuthorDate: Mon Jan 15 10:39:47 2024 +0100

    [lib] implement charity get API
---
 src/lib/donau_api_charity_get.c | 300 ++++++++++++++++++++++++----------------
 src/lib/donau_api_handle.c      |   2 +-
 2 files changed, 180 insertions(+), 122 deletions(-)

diff --git a/src/lib/donau_api_charity_get.c b/src/lib/donau_api_charity_get.c
index c55c61b..ed9b111 100644
--- a/src/lib/donau_api_charity_get.c
+++ b/src/lib/donau_api_charity_get.c
@@ -34,12 +34,6 @@
  */
 struct DONAU_CharityGetHandle
 {
-
-  /**
-   * The donau base URL (i.e. "http://donau.taler.net/";)
-   */
-  char *donau_url;
-
   /**
    * The url for the /charities/$CHARITY_ID request.
    */
@@ -51,18 +45,110 @@ struct DONAU_CharityGetHandle
   struct GNUNET_CURL_Job *job;
 
   /**
-   * Function to call with the donau's certification data,
-   * NULL if this has already been done.
+   * Function to call with the result.
    */
-  DONAU_GetCharityResponseCallback cert_cb;
+  DONAU_GetCharityResponseCallback cb;
 
   /**
-   * Closure to pass to @e cert_cb.
+   * Charity id we are querying.
    */
-  void *cert_cb_cls;
+  uint64_t charity_id;
+
+  /**
+   * Closure to pass to @e cb.
+   */
+  void *cb_cls;
 
 };
 
+/**
+ * Decode the JSON in @a resp_obj from the /charities/$ID response
+ * and store the data in the @a charity_data.
+ *
+ * @param[in] resp_obj JSON object to parse
+ * @param[out] charity_data where to store the results we decoded
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ * (malformed JSON)
+ */
+static enum GNUNET_GenericReturnValue
+handle_charity_get_ok (const json_t *resp_obj,
+                     struct DONAU_CharityGetHandle *cgh)
+{
+  const json_t *charity_hist_array;
+  const char *name;
+  if (JSON_OBJECT != json_typeof (resp_obj))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  struct DONAU_GetCharityResponse charity_resp = {
+    .hr.reply = resp_obj,
+    .hr.http_status = MHD_HTTP_OK
+  };
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("name",
+                           &name),
+    GNUNET_JSON_spec_fixed_auto ("pub_key",
+                                 &charity_resp.details.ok.charity->pub_key),
+    TALER_JSON_spec_amount_any ("max_per_year",
+                            &charity_resp.details.ok.charity->max_per_year),
+    GNUNET_JSON_spec_array_const ("donation_history",
+                                 &charity_hist_array),
+    GNUNET_JSON_spec_uint32 ("num_hist",
+                              &charity_resp.details.ok.charity->num_hist),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (resp_obj,
+                         spec,
+                         NULL,
+                         NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  charity_resp.details.ok.charity->name = GNUNET_strdup (name);
+
+  /* parse the charity history data */
+  charity_resp.details.ok.charity->num_hist
+    = json_array_size (charity_hist_array);
+  if (0 != charity_resp.details.ok.charity->num_hist)
+  {
+    json_t *charity_history_obj;
+    unsigned int index;
+
+    charity_resp.details.ok.charity->donation_history
+      = GNUNET_new_array (charity_resp.details.ok.charity->num_hist,
+                          struct DONAU_CharityHistoryYear);
+    json_array_foreach (charity_hist_array, index, charity_history_obj) {
+      struct DONAU_CharityHistoryYear *donation_history = 
&charity_resp.details.ok.charity->donation_history[index];
+      struct GNUNET_JSON_Specification history_spec[] = {
+        TALER_JSON_spec_amount_any ("final_amount",
+                                    &donation_history->final_amount),
+        GNUNET_JSON_spec_uint32 ("year",
+                                &donation_history->year),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (charity_history_obj,
+                            history_spec,
+                            NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+    }
+  }
+
+  cgh->cb (cgh->cb_cls,
+           &charity_resp);
+  cgh->cb = NULL;
+  return GNUNET_OK;
+}
+
+
 /**
  * Callback used when downloading the reply to a /charity request
  * is complete.
@@ -72,94 +158,70 @@ struct DONAU_CharityGetHandle
  * @param resp_obj parsed JSON result, NULL on error
  */
 static void
-charity_completed_cb (void *cls,
+handle_charity_get_finished (void *cls,
                    long response_code,
                    const void *resp_obj)
 {
-  struct DONAU_CharityGetHandle *cgh = cls;
-  //const json_t *j = resp_obj;
-  //struct Charity *cd = NULL;
+  //struct DONAU_Charity *cd = NULL;
   
-  // struct DONAU_KeysResponse kresp = {
-  //   .hr.reply = j,
-  //   .hr.http_status = (unsigned int) response_code,
-  //   .details.ok.compat = DONAU_VC_PROTOCOL_ERROR,
-  // };
-
-  // cgh->job = NULL;
-  // GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-  //             "Received keys from URL `%s' with status %ld.\n",
-  //             cgh->url,
-  //             response_code);
-  // switch (response_code)
-  // {
-  // case 0:
-  //   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-  //               "Failed to receive /keys response from donau %s\n",
-  //               cgh->donau_url);
-  //   break;
-  // case MHD_HTTP_OK:
-  //   if (NULL == j)
-  //   {
-  //     GNUNET_break (0);
-  //     response_code = 0;
-  //     break;
-  //   }
-  //   kd = GNUNET_new (struct DONAU_Keys);
-  //   kd->donau_url = GNUNET_strdup (cgh->donau_url);
-
-  //   if (GNUNET_OK !=
-  //       decode_keys_json (j,
-  //                         kd,
-  //                         &kresp.details.ok.compat))
-  //   {
-  //     TALER_LOG_ERROR ("Could not decode /keys response\n");
-  //     kd->rc = 1;
-  //     DONAU_keys_decref (kd);
-  //     kd = NULL;
-  //     kresp.hr.http_status = 0;
-  //     kresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
-  //     break;
-  //   }
-  //   kd->rc = 1;
-
-  //   kresp.details.ok.keys = kd;
-  //   break;
-  // case MHD_HTTP_BAD_REQUEST:
-  // case MHD_HTTP_UNAUTHORIZED:
-  // case MHD_HTTP_FORBIDDEN:
-  // case MHD_HTTP_NOT_FOUND:
-  //   if (NULL == j)
-  //   {
-  //     kresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
-  //     kresp.hr.hint = TALER_ErrorCode_get_hint (kresp.hr.ec);
-  //   }
-  //   else
-  //   {
-  //     kresp.hr.ec = TALER_JSON_get_error_code (j);
-  //     kresp.hr.hint = TALER_JSON_get_error_hint (j);
-  //   }
-  //   break;
-  // default:
-  //   if (NULL == j)
-  //   {
-  //     kresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
-  //     kresp.hr.hint = TALER_ErrorCode_get_hint (kresp.hr.ec);
-  //   }
-  //   else
-  //   {
-  //     kresp.hr.ec = TALER_JSON_get_error_code (j);
-  //     kresp.hr.hint = TALER_JSON_get_error_hint (j);
-  //   }
-  //   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-  //               "Unexpected response code %u/%d\n",
-  //               (unsigned int) response_code,
-  //               (int) kresp.hr.ec);
-  //   break;
-  // }
-  // cgh->cert_cb (cgh->cert_cb_cls,
-  //               &kresp,
-  //               kd);
+  struct DONAU_CharityGetHandle *cgh = cls;
+  const json_t *j = resp_obj;
+  struct DONAU_GetCharityResponse gcresp = {
+    .hr.reply = j,
+    .hr.http_status = (unsigned int) response_code
+  };
+
+  cgh->job = NULL;
+  switch (response_code)
+  {
+  case 0:
+    gcresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+    break;
+  case MHD_HTTP_OK:
+    if (GNUNET_OK !=
+        handle_charity_get_ok (j,
+                                cgh))
+    {
+      gcresp.hr.http_status = 0;
+      gcresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+    }
+    break;
+  case MHD_HTTP_BAD_REQUEST:
+    /* This should never happen, either us or the donau is buggy
+       (or API version conflict); just pass JSON reply to the application */
+    gcresp.hr.ec = TALER_JSON_get_error_code (j);
+    gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    /* Nothing really to verify, this should never
+       happen, we should pass the JSON reply to the application */
+    gcresp.hr.ec = TALER_JSON_get_error_code (j);
+    gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+    break;
+  case MHD_HTTP_INTERNAL_SERVER_ERROR:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    gcresp.hr.ec = TALER_JSON_get_error_code (j);
+    gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+    break;
+  default:
+    /* unexpected response code */
+    GNUNET_break_op (0);
+    gcresp.hr.ec = TALER_JSON_get_error_code (j);
+    gcresp.hr.hint = TALER_JSON_get_error_hint (j);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u/%d for GET %s\n",
+                (unsigned int) response_code,
+                (int) gcresp.hr.ec,
+                cgh->url);
+    break;
+  }
+  if (NULL != cgh->cb)
+  {
+    cgh->cb (cgh->cb_cls,
+             &gcresp);
+    cgh->cb = NULL;
+  }
   DONAU_charity_get_cancel (cgh);
 }
 
@@ -167,8 +229,9 @@ struct DONAU_CharityGetHandle *
 DONAU_charity_get (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const struct DONAU_BearerToken bearer,
   const uint64_t id,
+  const struct DONAU_BearerToken bearer, //TODO: check authorization
+  struct GNUNET_TIME_Relative timeout,
   DONAU_GetCharityResponseCallback cb,
   void *cb_cls)
 {
@@ -178,18 +241,26 @@ DONAU_charity_get (
   TALER_LOG_DEBUG ("Connecting to the donau (%s)\n",
                    url);
   cgh = GNUNET_new (struct DONAU_CharityGetHandle);
-  cgh->donau_url = GNUNET_strdup (url);
-  cgh->cert_cb = cb;
-  cgh->cert_cb_cls = cb_cls;
-  char arg_str[sizeof (struct DONAU_DonationUnitHashP) * 2 + 32];
-  char id_str[sizeof (struct DONAU_DonationUnitHashP) * 2];
+  cgh->url = GNUNET_strdup (url);
+  cgh->cb = cb;
+  cgh->charity_id = id;
+  cgh->cb_cls = cb_cls;
+  char arg_str[sizeof (id) * 2 + 32];
+  char id_str[sizeof (id) * 2];
   char *end;
+  char timeout_str[32];
 
   end = GNUNET_STRINGS_data_to_string (&id,
                                        sizeof (id),
                                        id_str,
                                        sizeof (id_str));
   *end = '\0';
+  GNUNET_snprintf (timeout_str,
+                  sizeof (timeout_str),
+                  "%llu",
+                  (unsigned long long)
+                  (timeout.rel_value_us
+                  / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us));
   GNUNET_snprintf (arg_str,
                   sizeof (arg_str),
                   "charities/%s",
@@ -197,6 +268,11 @@ DONAU_charity_get (
   cgh->url = TALER_url_join (url,
                              arg_str,
                              NULL);
+  if (NULL == cgh->url)
+  {
+    GNUNET_free (cgh);
+    return NULL;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Requesting a charity with URL `%s'.\n",
               cgh->url);
@@ -204,30 +280,13 @@ DONAU_charity_get (
   if (NULL == eh)
   {
     GNUNET_break (0);
-    GNUNET_free (cgh->donau_url);
     GNUNET_free (cgh->url);
     GNUNET_free (cgh);
     return NULL;
   }
-  GNUNET_break (CURLE_OK ==
-                curl_easy_setopt (eh,
-                                  CURLOPT_VERBOSE,
-                                  0));
-  GNUNET_break (CURLE_OK ==
-                curl_easy_setopt (eh,
-                                  CURLOPT_TIMEOUT,
-                                  120 /* seconds */));
-  // GNUNET_assert (CURLE_OK ==
-  //                curl_easy_setopt (eh,
-  //                                  CURLOPT_HEADERFUNCTION,
-  //                                  &header_cb));
-  GNUNET_assert (CURLE_OK ==
-                 curl_easy_setopt (eh,
-                                   CURLOPT_HEADERDATA,
-                                   cgh));
-  cgh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
+  cgh->job = GNUNET_CURL_job_add (ctx,
                                                eh,
-                                               &charity_completed_cb,
+                                               &handle_charity_get_finished,
                                                cgh);
   return cgh;
 }
@@ -241,7 +300,6 @@ DONAU_charity_get_cancel (
     GNUNET_CURL_job_cancel (cgh->job);
     cgh->job = NULL;
   }
-  GNUNET_free (cgh->donau_url);
   GNUNET_free (cgh->url);
   GNUNET_free (cgh);
 }
\ No newline at end of file
diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c
index 0135810..77e8058 100644
--- a/src/lib/donau_api_handle.c
+++ b/src/lib/donau_api_handle.c
@@ -452,7 +452,7 @@ keys_completed_cb (void *cls,
   struct DONAU_KeysResponse kresp = {
     .hr.reply = j,
     .hr.http_status = (unsigned int) response_code,
-    .details.ok.compat = DONAU_VC_PROTOCOL_ERROR,
+    .details.ok.compat = DONAU_VC_PROTOCOL_ERROR
   };
 
   gkh->job = NULL;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]