gnunet-svn
[Top][All Lists]
Advanced

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



reply via email to

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