summaryrefslogtreecommitdiff
path: root/src/reducer
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-21 18:55:19 +0100
committerChristian Grothoff <christian@grothoff.org>2022-01-21 18:55:19 +0100
commit77ccde74a92c64f5fb4d164b67effd26e244c123 (patch)
treed5a1426d6e0ba478fef01bc5c10d8cf6e4bfad7d /src/reducer
parent37d1d112520f0b42c3e50d262ea139f25d093fbc (diff)
downloadanastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.tar.gz
anastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.tar.bz2
anastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.zip
-implement provider_sync transition
Diffstat (limited to 'src/reducer')
-rw-r--r--src/reducer/anastasis_api_recovery_redux.c321
1 files changed, 220 insertions, 101 deletions
diff --git a/src/reducer/anastasis_api_recovery_redux.c b/src/reducer/anastasis_api_recovery_redux.c
index 791ed9f..86f05e4 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -1889,6 +1889,221 @@ select_challenge (json_t *state,
/**
+ * Main data structure for sync_providers().
+ */
+struct MasterSync;
+
+
+/**
+ * Data structure for one provider we are syncing /config with.
+ */
+struct SyncEntry
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct SyncEntry *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct SyncEntry *prev;
+
+ /**
+ * Sync operation we are part of.
+ */
+ struct MasterSync *ms;
+
+ /**
+ * Redux action for this provider.
+ */
+ struct ANASTASIS_ReduxAction *ra;
+};
+
+/**
+ * Main data structure for sync_providers().
+ */
+struct MasterSync
+{
+ /**
+ * Our own sync action we expose externally.
+ */
+ struct ANASTASIS_ReduxAction ra;
+ /**
+ * Head of DLL with entries per provider.
+ */
+ struct SyncEntry *se_head;
+ /**
+ * Tail of DLL with entries per provider.
+ */
+ struct SyncEntry *se_tail;
+
+ /**
+ * Function to call with the result.
+ */
+ ANASTASIS_ActionCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Free @a cls data structure.
+ *
+ * @param[in] cls data structure to free, must be a `struct MasterSync *`
+ */
+static void
+clean_sync (void *cls)
+{
+ struct MasterSync *ms = cls;
+ struct SyncEntry *se;
+
+ while (NULL != (se = ms->se_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (ms->se_head,
+ ms->se_tail,
+ se);
+ se->ra->cleanup (se->ra->cleanup_cls);
+ GNUNET_free (se);
+ }
+ GNUNET_free (ms);
+}
+
+
+/**
+ * Function called when we have made progress on any of the
+ * providers we are trying to sync with.
+ *
+ * @param cls closure
+ * @param error error code, #TALER_EC_NONE if @a new_bs is the new successful state
+ * @param new_state the new state of the operation (client should json_incref() to keep an alias)
+ */
+static void
+sync_progress (void *cls,
+ enum TALER_ErrorCode error,
+ json_t *new_state)
+{
+ struct SyncEntry *se = cls;
+ struct MasterSync *ms = se->ms;
+
+ ms->cb (ms->cb_cls,
+ error,
+ new_state);
+ clean_sync (ms);
+}
+
+
+/**
+ * Check if we have information on all providers involved in
+ * a recovery procedure, and if not, try to obtain it. Upon
+ * success, call @a cb with the updated provider status data.
+ *
+ * @param[in] state we are in
+ * @param arguments our arguments with the solution
+ * @param cb functiont o call with the new state
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel challenge selection step
+ */
+static struct ANASTASIS_ReduxAction *
+sync_providers (json_t *state,
+ const json_t *arguments,
+ ANASTASIS_ActionCallback cb,
+ void *cb_cls)
+{
+ json_t *rd;
+ json_t *cs_arr;
+ struct MasterSync *ms;
+
+ rd = json_object_get (state,
+ "recovery_document");
+ if (NULL == rd)
+ {
+ GNUNET_break (0);
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "'recovery_document' missing");
+ return NULL;
+ }
+ cs_arr = json_object_get (rd,
+ "cs");
+ if (! json_is_array (cs_arr))
+ {
+ GNUNET_break_op (0);
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "'recovery_document' must be an array");
+ return NULL;
+ }
+ ms = GNUNET_new (struct MasterSync);
+ ms->cb = cb;
+ ms->cb_cls = cb_cls;
+ {
+ json_t *cs;
+ unsigned int n_index;
+
+ json_array_foreach (cs_arr, n_index, cs)
+ {
+ const char *provider_url;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("url",
+ &provider_url),
+ GNUNET_JSON_spec_end ()
+ };
+ struct ANASTASIS_CRYPTO_ProviderSaltP salt;
+ struct SyncEntry *se;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (cs,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "'recovery_document' missing");
+ clean_sync (ms);
+ return NULL;
+ }
+ if (GNUNET_OK ==
+ ANASTASIS_reducer_lookup_salt_ (state,
+ provider_url,
+ &salt))
+ continue; /* provider already ready */
+ se = GNUNET_new (struct SyncEntry);
+ se->ms = ms;
+ GNUNET_CONTAINER_DLL_insert (ms->se_head,
+ ms->se_tail,
+ se);
+ se->ra = ANASTASIS_REDUX_add_provider_to_state_ (provider_url,
+ state,
+ &sync_progress,
+ se);
+ }
+ }
+ if (NULL == ms->se_head)
+ {
+ /* everything already synced */
+ clean_sync (ms);
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
+ "already in sync");
+ return NULL;
+ }
+ ms->ra.cleanup = &clean_sync;
+ ms->ra.cleanup_cls = ms;
+ return &ms->ra;
+}
+
+
+/**
* The user pressed "back" during challenge solving.
* Transition back to selecting another challenge.
*
@@ -2014,104 +2229,6 @@ return_no_policy (struct PolicyDownloadEntry *pd,
/**
- * Determine recovery @a cost of solving a challenge of type @a type
- * at @a provider_url by inspecting @a state.
- *
- * @param state the state to inspect
- * @param provider_url the provider to lookup config info from
- * @param type the method to lookup the cost of
- * @param[out] cost the recovery cost to return
- * @param[out] ec set to the error code
- * @return #GNUNET_OK on success, #GNUNET_NO if not found, #GNUNET_SYSERR on state error
- */
-static enum GNUNET_GenericReturnValue
-lookup_cost (const json_t *state,
- const char *provider_url,
- const char *type,
- struct TALER_Amount *cost,
- enum TALER_ErrorCode *ec)
-{
- const json_t *providers;
- const json_t *provider;
- const json_t *methods;
-
- *ec = TALER_EC_NONE;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Looking up cost for provider `%s' and method `%s'\n",
- provider_url,
- type);
- providers = json_object_get (state,
- "authentication_providers");
- if (NULL == providers)
- {
- *ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- provider = json_object_get (providers,
- provider_url);
- if (NULL == provider)
- {
- *ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (provider,
- "http_status")))
- {
- json_t *eco;
-
- eco = json_object_get (provider,
- "error_code");
- if (NULL != eco)
- *ec = json_integer_value (eco);
- else
- *ec = TALER_EC_ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG;
- return GNUNET_NO;
- }
- methods = json_object_get (provider,
- "methods");
- if ( (NULL == methods) ||
- (! json_is_array (methods)) )
- {
- *ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- {
- size_t index;
- json_t *method;
-
- json_array_foreach (methods, index, method) {
- const char *t;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("type",
- &t),
- TALER_JSON_spec_amount_any ("usage_fee",
- cost),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (method,
- spec,
- NULL, NULL))
- {
- GNUNET_break (0);
- *ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
- continue;
- }
- if (0 == strcmp (t,
- type))
- return GNUNET_OK;
- }
- }
- return GNUNET_NO; /* not found */
-}
-
-
-/**
* Callback which passes back the recovery document and its possible
* policies. Also passes back the version of the document for the user
* to check.
@@ -2177,9 +2294,6 @@ policy_lookup_cb (void *cls,
struct ANASTASIS_Challenge *c = ri->cs[i];
const struct ANASTASIS_ChallengeDetails *cd;
json_t *cj;
- struct TALER_Amount cost;
- enum GNUNET_GenericReturnValue ret;
- enum TALER_ErrorCode ec;
cd = ANASTASIS_challenge_get_details (c);
cj = GNUNET_JSON_PACK (
@@ -2491,6 +2605,11 @@ ANASTASIS_recovery_action_ (json_t *state,
},
{
ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING,
+ "sync_providers",
+ &sync_providers
+ },
+ {
+ ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING,
"poll",
&poll_challenges
},