[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.