diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-01-21 18:55:19 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-01-21 18:55:19 +0100 |
commit | 77ccde74a92c64f5fb4d164b67effd26e244c123 (patch) | |
tree | d5a1426d6e0ba478fef01bc5c10d8cf6e4bfad7d /src/reducer/anastasis_api_recovery_redux.c | |
parent | 37d1d112520f0b42c3e50d262ea139f25d093fbc (diff) | |
download | anastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.tar.gz anastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.tar.bz2 anastasis-77ccde74a92c64f5fb4d164b67effd26e244c123.zip |
-implement provider_sync transition
Diffstat (limited to 'src/reducer/anastasis_api_recovery_redux.c')
-rw-r--r-- | src/reducer/anastasis_api_recovery_redux.c | 321 |
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 }, |