[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: async state management
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: async state management |
Date: |
Wed, 14 Oct 2020 14:47:03 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new 51dfaef async state management
51dfaef is described below
commit 51dfaef6f270751f3486015ca2af9846094bcd85
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Oct 14 14:47:00 2020 +0200
async state management
---
src/include/anastasis_service.h | 55 +-----
src/lib/anastasis_api_config.c | 46 +++++
src/lib/anastasis_api_redux.c | 403 ++++++++++++++++++++++------------------
3 files changed, 275 insertions(+), 229 deletions(-)
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 823694f..30b5b86 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -248,6 +248,12 @@ typedef void
const struct TALER_Amount *annual_fee);
+/**
+ * @brief A Config Operation Handle
+ */
+struct ANASTASIS_ConfigOperation;
+
+
struct ANASTASIS_ConfigOperation *
ANASTASIS_get_config (struct GNUNET_CURL_Context *ctx,
const char *base_url,
@@ -259,55 +265,6 @@ void
ANASTASIS_config_cancel (struct ANASTASIS_ConfigOperation *co);
-/**
- * @brief A Contract Operation Handle
- */
-struct ANASTASIS_ConfigOperation
-{
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Reference to the execution context.
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * The callback to pass the backend response to
- */
- ANASTASIS_ConfigCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Cost.
- */
- struct TALER_Amount cost;
-
- /**
- * Supported methods.
- */
- json_t *methods;
-
- /**
- * Currency of the cost;
- */
- const char *currency;
-
- // FIXME add configs
-};
-
-
typedef void
(*ANASTASIS_SaltCallback)(void *cls,
unsigned int http_status,
diff --git a/src/lib/anastasis_api_config.c b/src/lib/anastasis_api_config.c
index ef69a69..e1834bf 100644
--- a/src/lib/anastasis_api_config.c
+++ b/src/lib/anastasis_api_config.c
@@ -32,6 +32,52 @@
#include "anastasis_api_curl_defaults.h"
+struct ANASTASIS_ConfigOperation
+{
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * The callback to pass the backend response to
+ */
+ ANASTASIS_ConfigCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Cost.
+ */
+ struct TALER_Amount cost;
+
+ /**
+ * Supported methods.
+ */
+ json_t *methods;
+
+ /**
+ * Currency of the cost;
+ */
+ const char *currency;
+
+ // FIXME add configs
+};
+
+
/**
* Function called when we're done processing the
* HTTP /config request.
diff --git a/src/lib/anastasis_api_redux.c b/src/lib/anastasis_api_redux.c
index dab178c..7b80b0e 100644
--- a/src/lib/anastasis_api_redux.c
+++ b/src/lib/anastasis_api_redux.c
@@ -29,10 +29,37 @@
#include "anastasis_api_redux.h"
/**
- * Server information
+ * How long do we wait at most for a /config reply from an Anastasis provider.
+ * 60s is very generous, given the tiny bandwidth required, even for the most
+ * remote locations.
*/
-struct ServerInfo
+#define CONFIG_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+
+struct SelectCountryHandle;
+
+/**
+ * State for a "get config" operation.
+ */
+struct ConfigRequest
{
+
+ struct ConfigRequest *next;
+
+ struct ConfigRequest *prev;
+
+ struct SelectCountryHandle *sch;
+
+ /**
+ * Obtained status code.
+ */
+ unsigned int http_status;
+
+ /**
+ * The /config GET operation handle.
+ */
+ struct ANASTASIS_ConfigOperation *co;
+
/**
* URL of the anastasis backend.
*/
@@ -53,11 +80,6 @@ struct ServerInfo
*/
char *backend_currency;
- /**
- * supported methods of the anastasis backend.
- */
- json_t *backend_methods;
-
/**
* insurance of the anastasis backend.
*/
@@ -67,77 +89,55 @@ struct ServerInfo
* cost of using the anastasis backend.
*/
struct TALER_Amount backend_cost;
-};
-/**
- * State for a "get config" CMD.
- */
-struct ConfigState
-{
/**
- * Expected status code.
+ * Supported methods.
*/
- unsigned int http_status;
+ json_t *backend_methods;
- /**
- * The /config GET operation handle.
- */
- struct ANASTASIS_ConfigOperation *co;
+ struct GNUNET_SCHEDULER_Task *tt;
- /**
- * Reference to a ServerInfo.
- */
- struct ServerInfo *server;
+};
+
+
+struct SelectCountryHandle
+{
+ struct ConfigRequest *cr_head;
+
+ struct ConfigRequest *cr_tail;
/**
* Current state
*/
json_t *state;
- /**
- * Supported methods.
- */
- json_t *methods;
-
/**
* Function to call if config request was successful.
*/
ANASTASIS_ActionCallback cb;
+
+ void *cb_cls;
};
+
/**
* Curl context for communication with taler backend
*/
struct GNUNET_CURL_Context *curl_ctx;
-/**
- * Information about the servers.
- */
-static struct ServerInfo *servers;
-
-/**
- * Amount of servers.
- */
-static unsigned int servers_length = 0;
-
/**
* JSON containing country specific identity attributes to ask the user for.
*/
const json_t *redux_id_attr;
-/**
- * Currency of chosen country
- */
-const char *currency;
-
/**
* Callback function FIXME: Description.
*
- * @param state FIXME: Description
- * @param arguments FIXME: Description
- * @param cb FIXME: Description
- * @param cb_cls FIXME: Description
+ * @param state FIXME: Description
+ * @param arguments FIXME: Description
+ * @param cb FIXME: Description
+ * @param cb_cls FIXME: Description
*/
typedef void
(*DispatchHandler)(json_t *state,
@@ -146,6 +146,135 @@ typedef void
void *cb_cls);
+static void
+free_config_request (struct ConfigRequest *cr)
+{
+ if (NULL != cr->co)
+ ANASTASIS_get_config_cancel (cr->co);
+ if (NULL != cr->tt)
+ GNUNET_SCHEDULER_cancel (cr->tt);
+ GNUNET_free (cr->backend_currency);
+ json_decref (cr->backend_methods);
+ GNUNET_free (cr);
+}
+
+
+static void
+free_select_country (void *cls)
+{
+ struct SelectCountryHandle *sch = cls;
+ struct ConfigRequest *cr;
+
+ while (NULL != (cr = sch->cr_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (sch->cr_head,
+ sch->cr_tail,
+ cr);
+ free_config_request (cr);
+ }
+ json_decref (sch->state);
+ GNUNET_free (sch);
+}
+
+
+static void
+add_config_to_state (struct ConfigRequest *cr,
+ json_t *state)
+{
+ json_t *method;
+ size_t index;
+ json_t *methods_list = json_object_get (state, "authentication_methods");
+ json_t *provider_list = json_object_get (state, "authentication_providers");
+
+ GNUNET_assert (NULL != provider_list);
+ json_array_foreach (cr->backend_methods, index, method)
+ {
+ const char *method_type = json_string_value (json_object_get (method,
+ "method"));
+ json_t *ma;
+ json_t *prov;
+
+ if (NULL == (ma = json_object_get (provider_list,
+ method_type)))
+ {
+ GNUNET_assert (0 ==
+ json_object_set_new (methods_list,
+ method_type,
+ ma = json_object ()));
+ }
+ prov = json_pack ("{s:o}",
+ "method_cost",
+ json_object_get (method,
+ "cost"));
+ GNUNET_assert (0 == json_object_set_new (ma,
+ cr->backend_id,
+ prov));
+ prov = json_pack ("{s:o, s:s, s:s}",
+ // FIXME: add insurance here...
+ "annual_cost",
+ TALER_JSON_from_amount (&cr->backend_cost),
+ "provider_url",
+ cr->backend_url,
+ "provider_name",
+ cr->backend_name);
+ GNUNET_assert (0 == json_object_set_new (ma,
+ cr->backend_id,
+ prov));
+ }
+}
+
+
+static void
+conclude_select_country (struct SelectCountryHandle *sch)
+{
+ struct ConfigRequest *cr;
+ const char *currency;
+
+ /* Are we waiting for more /config requests to complete? */
+ for (cr = sch->cr_head; NULL != cr; cr = cr->next)
+ if (NULL != cr->co)
+ return;
+ currency = json_string_value (json_object_get (cs->state,
+ "currency"));
+ GNUNET_assert (0 == json_object_set_new (state,
+ "authentication_methods",
+ json_object ()));
+ GNUNET_assert (0 == json_object_set_new (state,
+ "authentication_providers",
+ json_object ()));
+ while (NULL != (cr = sch->cr_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (sch->cr_head,
+ sch->cr_tail,
+ cr);
+ if (0 != strcmp (cr->backend_currency,
+ currency))
+ {
+ free_config_request (cr);
+ continue;
+ }
+ add_config_to_state (cr,
+ cs->state);
+ }
+ sch->cb (NULL,
+ ANASTASIS_EC_NONE,
+ cs->state);
+ free_select_country (sch);
+}
+
+
+static void
+config_request_timeout (void *cls)
+{
+ struct ConfigRequest *cr = cls;
+
+ cr->tt = NULL;
+ ANASTASIS_get_config_cancel (cr->co);
+ cr->co = NULL;
+ conclude_select_country (cr->sch);
+}
+
+
/**
* Function called with the results of a #ANASTASIS_get_config().
*
@@ -161,110 +290,24 @@ config_cb (void *cls,
const char *conf_currency,
const struct TALER_Amount *annual_fee)
{
- struct ConfigState *cs = cls;
+ struct ConfigRequest *cr = cls;
+ struct SelectCountryHandle *sch = cr->sch;
- cs->co = NULL;
+ cr->co = NULL;
+ GNUNET_SCHEDULER_cancel (cr->tt);
+ cr->tt = NULL;
+ cr->http_status = http_status;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"At %s:%d url is %s\n", __FILE__, __LINE__,
cs->server->backend_url);
- if (http_status != cs->http_status)
+ if (MHD_HTTP_OK == http_status)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u in %s:%u\n",
- http_status,
- __FILE__,
- __LINE__);
- return;
- }
- cs->server->backend_methods = json_incref ((json_t *) methods);
- cs->server->backend_cost = *annual_fee;
- cs->server->backend_currency = GNUNET_malloc (strlen (conf_currency) + 1);
- GNUNET_strlcpy (cs->server->backend_currency,
- conf_currency,
- strlen (conf_currency) + 1);
-
- if (0 != strcmp (cs->server->backend_currency,
- json_string_value (json_object_get (cs->state,
- "currency"))))
- return;
- {
- json_t *method;
- size_t index;
- json_t *config = json_object ();
- GNUNET_assert (NULL != config);
- json_t *provider_list = json_array ();
- GNUNET_assert (NULL != provider_list);
- json_t *method_arr = json_object_get (methods, "methods");
- GNUNET_assert (NULL != method_arr);
- GNUNET_assert (0 == json_object_set_new (config,
- "provider",
- json_string (
- cs->server->backend_id)));
-
- json_array_foreach (method_arr, index, method)
- {
- json_t *method_type = json_object_get (method, "method");
- GNUNET_assert (NULL != method_type);
- json_t *provider_method = json_object ();
- GNUNET_assert (NULL != provider_method);
- json_t *provider_id = json_object ();
- GNUNET_assert (NULL != provider_id);
- json_t *method_data = json_object ();
- GNUNET_assert (NULL != method_data);
- json_t *provider_arr = json_array ();
- GNUNET_assert (NULL != provider_arr);
-
- GNUNET_assert (0 == json_object_set_new (method_data,
- "method_cost",
- json_object_get (method,
- "cost")));
- GNUNET_assert (0 == json_object_set_new (method_data,
- "annual_cost",
- TALER_JSON_from_amount (
- &cs->server->backend_cost)));
- GNUNET_assert (0 == json_object_set_new (provider_id,
- cs->server->backend_id,
- method_data));
- GNUNET_assert (0 == json_array_append_new (provider_arr,
- provider_id));
- GNUNET_assert (0 == json_object_set_new (provider_method,
- json_string_value (method_type),
- provider_arr));
-
- GNUNET_assert (0 == json_object_set_new (config,
- "config",
- provider_method));
- }
- for (unsigned int i = 0; i < servers_length; i++)
- {
- if (NULL == servers[i].backend_currency)
- continue;
- if (0 == strcmp (servers[i].backend_currency,
- json_string_value (json_object_get (cs->state,
- "currency"))))
- {
- json_t *provider = json_object ();
- GNUNET_assert (NULL != provider);
- GNUNET_assert (0 == json_object_set_new (provider,
- "provider_id",
- json_string (
- servers[i].backend_id)));
- GNUNET_assert (0 == json_object_set_new (provider,
- "provider_url",
- json_string (
- servers[i].backend_url)));
- GNUNET_assert (0 == json_array_append_new (provider_list,
- provider));
- }
- }
- GNUNET_assert (0 == json_object_set_new (config,
- "provider_list",
- provider_list));
- cs->cb (NULL,
- ANASTASIS_EC_NONE,
- config);
- json_decref (cs->state);
+ cr->backend_methods = json_incref ((json_t *) methods);
+ cr->backend_cost = *annual_fee;
+ cr->backend_currency = GNUNET_strdup (conf_currency);
+ // FIXME: set cr->backend_insurance?
}
+ conclude_select_country (sch);
}
@@ -455,7 +498,11 @@ select_country (json_t *state,
const json_t *provider_list;
char *dn;
json_error_t error;
- json_t *country = json_object_get (arguments, "country_code");
+ json_t *country;
+ const char *currency;
+
+ country = json_object_get (arguments,
+ "country_code");
GNUNET_assert (NULL != country);
currency = json_string_value (json_object_get (arguments,
"currency"));
@@ -464,7 +511,8 @@ select_country (json_t *state,
GNUNET_assert (NULL != s_mode);
GNUNET_assert (GNUNET_SYSERR !=
redux_id_attr_init (json_string_value (country)));
- root = json_object_get (redux_id_attr, "required_attributes");
+ root = json_object_get (redux_id_attr,
+ "required_attributes");
GNUNET_assert (NULL != root);
GNUNET_assert (0 ==
json_object_set_new (
@@ -517,14 +565,20 @@ select_country (json_t *state,
// get configs from providers
{
+ struct SelectCountryHandle *sch;
size_t index;
json_t *provider;
json_t *provider_arr = json_object_get (provider_list,
"anastasis_provider");
+ sch = GNUNET_new (struct SelectCountryHandle);
+ sch->cb = cb;
+ sch->cb_cls = cb_cls;
+ sch->state = state;
json_array_foreach (provider_arr, index, provider)
{
- struct ServerInfo *server = GNUNET_new (struct ServerInfo);
+ struct ConfigRequest *cr = GNUNET_new (struct ConfigRequest);
+
const char *url = json_string_value (json_object_get (provider,
"provider_url"));
const char *provider_name = json_string_value (json_object_get (provider,
@@ -533,42 +587,31 @@ select_country (json_t *state,
"provider_id"));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Url is: %s\n", url);
- server->backend_url = GNUNET_malloc (strlen (url) + 1);
- GNUNET_strlcpy (server->backend_url,
- url,
- strlen (url) + 1);
- server->backend_name = GNUNET_malloc (strlen (provider_name) + 1);
- GNUNET_strlcpy (server->backend_name,
- provider_name,
- strlen (provider_name) + 1);
- server->backend_id = GNUNET_malloc (strlen (provider_id) + 1);
- GNUNET_strlcpy (server->backend_id,
- provider_id,
- strlen (provider_id) + 1);
- GNUNET_array_append (servers, servers_length, *server);
- }
-
- for (unsigned int i = 0; i < servers_length; i++)
- {
- struct ConfigState *cs = GNUNET_new (struct ConfigState);
- cs->server = &servers[i];
- cs->http_status = MHD_HTTP_OK;
- cs->state = json_deep_copy (state);
- cs->cb = cb;
- cs->co = ANASTASIS_get_config (curl_ctx,
- servers[i].backend_url,
- config_cb,
- cs);
- if (NULL == cs->co)
+ cr->backend_url = GNUNET_strdup (url);
+ cr->backend_name = GNUNET_strdup (provider_name);
+ cr->backend_id = GNUNET_strdup (provider_id);
+ cr->sch = sch;
+ GNUNET_CONTAINER_DLL_insert (sch->cr_head,
+ sch->cr_tail,
+ cr);
+ cr->co = ANASTASIS_get_config (curl_ctx,
+ cr->backend_url,
+ &config_cb,
+ cr);
+ if (NULL == cr->co)
+ {
+ GNUNET_break (0);
+ }
+ else
{
- /** FIXME: Error handling */
+ cr->tt = GNUNET_SCHEDULER_add_delayed (CONFIG_TIMEOUT,
+ &config_request_timeout,
+ cr);
}
}
+ conclude_select_country (sch);
+ // FIXME: wrap: return sch; + free_select_country();
}
-
- cb (cb_cls,
- ANASTASIS_EC_NONE,
- state);
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-anastasis] branch master updated: async state management,
gnunet <=
- [taler-anastasis] branch master updated: async state management, gnunet, 2020/10/14
- [taler-anastasis] branch master updated: async state management, gnunet, 2020/10/14
- [taler-anastasis] branch master updated: async state management, gnunet, 2020/10/14
- [taler-anastasis] branch master updated: async state management, gnunet, 2020/10/14
- [taler-anastasis] branch master updated: async state management, gnunet, 2020/10/14