From 661bd552f0c2f6ba77860dae633322ddaf19bd6d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 31 Jul 2023 18:32:20 +0200 Subject: future-proof API --- src/include/anastasis_service.h | 188 ++++++++++++++++------ src/lib/anastasis_meta.c | 10 +- src/lib/anastasis_recovery.c | 14 +- src/reducer/anastasis_api_redux.c | 39 +++-- src/restclient/anastasis_api_config.c | 52 +++--- src/restclient/anastasis_api_policy_lookup.c | 23 ++- src/restclient/anastasis_api_policy_meta_lookup.c | 22 +-- src/testing/testing_api_cmd_config.c | 12 +- src/testing/testing_api_cmd_policy_lookup.c | 10 +- 9 files changed, 226 insertions(+), 144 deletions(-) diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h index ba55314..2f30a8b 100644 --- a/src/include/anastasis_service.h +++ b/src/include/anastasis_service.h @@ -51,51 +51,82 @@ struct ANASTASIS_AuthorizationMethodConfig */ struct ANASTASIS_Config { - /** - * Protocol version supported by the server. - */ - const char *version; /** - * Business name of the anastasis provider. + * HTTP status returned. */ - const char *business_name; + unsigned int http_status; /** - * Array of authorization methods supported by the server. + * Taler-specific error code, #TALER_EC_NONE on success. */ - const struct ANASTASIS_AuthorizationMethodConfig *methods; + enum TALER_ErrorCode ec; /** - * Length of the @e methods array. + * Full response in JSON, if provided. */ - unsigned int methods_length; + const json_t *response; /** - * Maximum size of an upload in megabytes. + * Details depending on @e http_status. */ - uint32_t storage_limit_in_megabytes; + union + { - /** - * Annual fee for an account / policy upload. - */ - struct TALER_Amount annual_fee; + /** + * Details on #MHD_HTTP_OK. + */ + struct + { - /** - * Fee for a truth upload. - */ - struct TALER_Amount truth_upload_fee; + /** + * Protocol version supported by the server. + */ + const char *version; - /** - * Maximum legal liability for data loss covered by the - * provider. - */ - struct TALER_Amount liability_limit; + /** + * Business name of the anastasis provider. + */ + const char *business_name; - /** - * Provider salt. - */ - struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt; + /** + * Array of authorization methods supported by the server. + */ + const struct ANASTASIS_AuthorizationMethodConfig *methods; + + /** + * Length of the @e methods array. + */ + unsigned int methods_length; + + /** + * Maximum size of an upload in megabytes. + */ + uint32_t storage_limit_in_megabytes; + + /** + * Annual fee for an account / policy upload. + */ + struct TALER_Amount annual_fee; + + /** + * Fee for a truth upload. + */ + struct TALER_Amount truth_upload_fee; + + /** + * Maximum legal liability for data loss covered by the + * provider. + */ + struct TALER_Amount liability_limit; + + /** + * Provider salt. + */ + struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt; + } ok; + + } details; }; @@ -107,12 +138,10 @@ struct ANASTASIS_Config * the server provided an acceptable response. * * @param cls closure - * @param http_status the HTTP status * @param acfg configuration obtained, NULL if we could not parse it */ typedef void (*ANASTASIS_ConfigCallback)(void *cls, - unsigned int http_status, const struct ANASTASIS_Config *acfg); @@ -185,15 +214,45 @@ struct ANASTASIS_MetaDownloadDetails { /** - * Version-sorted array of meta data we downloaded. + * HTTP status returned. + */ + unsigned int http_status; + + /** + * Taler-specific error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response in JSON, if provided. */ - const struct ANASTASIS_MetaDataEntry *metas; + const json_t *response; /** - * Number of entries in @e metas. + * Details depending on @e http_status. */ - size_t metas_length; + union + { + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + + /** + * Version-sorted array of meta data we downloaded. + */ + const struct ANASTASIS_MetaDataEntry *metas; + + /** + * Number of entries in @e metas. + */ + size_t metas_length; + + } ok; + + } details; }; @@ -201,13 +260,11 @@ struct ANASTASIS_MetaDownloadDetails * Callback to process a GET /policy/$POL/meta request * * @param cls closure - * @param http_status HTTP status code for this request * @param dd the response details */ typedef void (*ANASTASIS_PolicyMetaLookupCallback) ( void *cls, - unsigned int http_status, const struct ANASTASIS_MetaDownloadDetails *dd); @@ -247,30 +304,57 @@ ANASTASIS_policy_meta_lookup_cancel ( */ struct ANASTASIS_DownloadDetails { - /** - * Signature (already verified). - */ - struct ANASTASIS_AccountSignatureP sig; /** - * Hash over @e policy and @e policy_size. + * HTTP status returned. */ - struct GNUNET_HashCode curr_policy_hash; + unsigned int http_status; /** - * The backup we downloaded. + * Taler-specific error code, #TALER_EC_NONE on success. */ - const void *policy; + enum TALER_ErrorCode ec; /** - * Number of bytes in @e backup. + * Details depending on @e http_status. */ - size_t policy_size; + union + { + + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + + /** + * Signature (already verified). + */ + struct ANASTASIS_AccountSignatureP sig; + + /** + * Hash over @e policy and @e policy_size. + */ + struct GNUNET_HashCode curr_policy_hash; + + /** + * The backup we downloaded. + */ + const void *policy; + + /** + * Number of bytes in @e backup. + */ + size_t policy_size; + + /** + * Policy version returned by the service. + */ + uint32_t version; + } ok; + + } details; - /** - * Policy version returned by the service. - */ - uint32_t version; }; @@ -284,12 +368,10 @@ struct ANASTASIS_PolicyLookupOperation; * Callback to process a GET /policy request * * @param cls closure - * @param http_status HTTP status code for this request * @param dd the response details */ typedef void (*ANASTASIS_PolicyLookupCallback) (void *cls, - unsigned int http_status, const struct ANASTASIS_DownloadDetails *dd); diff --git a/src/lib/anastasis_meta.c b/src/lib/anastasis_meta.c index 7812f6b..ae20db5 100644 --- a/src/lib/anastasis_meta.c +++ b/src/lib/anastasis_meta.c @@ -55,20 +55,17 @@ struct ANASTASIS_VersionCheck * Function called with results from a GET /policy/$POL/meta request * * @param cls closure with the `struct ANASTASIS_VersionCheck *` - * @param http_status HTTP status code for this request * @param dd the response details */ static void meta_cb ( void *cls, - unsigned int http_status, const struct ANASTASIS_MetaDownloadDetails *dd) { struct ANASTASIS_VersionCheck *vc = cls; vc->plm = NULL; - if ( (MHD_HTTP_OK != http_status) || - (NULL == dd) ) + if (MHD_HTTP_OK != dd->http_status) { vc->mpc (vc->mpc_cls, 0, @@ -78,9 +75,10 @@ meta_cb ( ANASTASIS_recovery_get_versions_cancel (vc); return; } - for (size_t i = 0; imetas_length; i++) + for (size_t i = 0; idetails.ok.metas_length; i++) { - const struct ANASTASIS_MetaDataEntry *meta = &dd->metas[i]; + const struct ANASTASIS_MetaDataEntry *meta + = &dd->details.ok.metas[i]; const char *secret_name = NULL; const struct GNUNET_HashCode *eph; void *dec; diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c index f94e946..0364b5a 100644 --- a/src/lib/anastasis_recovery.c +++ b/src/lib/anastasis_recovery.c @@ -612,12 +612,10 @@ ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c) * Function called with the results of a #ANASTASIS_policy_lookup() * * @param cls closure - * @param http_status HTTp status code. * @param dd details about the lookup operation */ static void policy_lookup_cb (void *cls, - unsigned int http_status, const struct ANASTASIS_DownloadDetails *dd) { struct ANASTASIS_Recovery *r = cls; @@ -629,7 +627,7 @@ policy_lookup_cb (void *cls, json_t *recovery_document; r->plo = NULL; - switch (http_status) + switch (dd->http_status) { case MHD_HTTP_OK: break; @@ -661,7 +659,7 @@ policy_lookup_cb (void *cls, default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u in %s:%u\n", - http_status, + dd->http_status, __FILE__, __LINE__); r->csc (r->csc_cls, @@ -671,7 +669,7 @@ policy_lookup_cb (void *cls, ANASTASIS_recovery_abort (r); return; } - if (NULL == dd->policy) + if (NULL == dd->details.ok.policy) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No recovery data available"); @@ -683,8 +681,8 @@ policy_lookup_cb (void *cls, return; } ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id, - dd->policy, - dd->policy_size, + dd->details.ok.policy, + dd->details.ok.policy_size, &plaintext, &size_plaintext); if (size_plaintext < sizeof (uint32_t)) @@ -801,7 +799,7 @@ policy_lookup_cb (void *cls, } } - r->ri.version = dd->version; + r->ri.version = dd->details.ok.version; r->ri.cs_len = json_array_size (esc_methods); r->ri.dps_len = json_array_size (dec_policies); r->ri.dps = GNUNET_new_array (r->ri.dps_len, diff --git a/src/reducer/anastasis_api_redux.c b/src/reducer/anastasis_api_redux.c index 31a389b..4b5ad7b 100644 --- a/src/reducer/anastasis_api_redux.c +++ b/src/reducer/anastasis_api_redux.c @@ -599,12 +599,10 @@ retry_config (void *cls); * Function called with the results of a #ANASTASIS_get_config(). * * @param cls closure - * @param http_status HTTP status of the request * @param acfg anastasis configuration */ static void config_cb (void *cls, - unsigned int http_status, const struct ANASTASIS_Config *acfg) { struct ConfigRequest *cr = cls; @@ -615,23 +613,23 @@ config_cb (void *cls, GNUNET_SCHEDULER_cancel (cr->tt); cr->tt = NULL; } - cr->http_status = http_status; - if (MHD_HTTP_OK != http_status) + cr->http_status = acfg->http_status; + if (MHD_HTTP_OK != acfg->http_status) { - if (0 == http_status) + if (0 == acfg->http_status) cr->ec = TALER_EC_ANASTASIS_GENERIC_PROVIDER_UNREACHABLE; else cr->ec = TALER_EC_ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED; } - if ( (MHD_HTTP_OK == http_status) && + if ( (MHD_HTTP_OK == acfg->http_status) && (NULL == acfg) ) { cr->http_status = MHD_HTTP_NOT_FOUND; cr->ec = TALER_EC_ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED; } - else if (NULL != acfg) + else { - if (0 == acfg->storage_limit_in_megabytes) + if (0 == acfg->details.ok.storage_limit_in_megabytes) { cr->http_status = 0; cr->ec = TALER_EC_ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG; @@ -640,27 +638,28 @@ config_cb (void *cls, { cr->ec = TALER_EC_NONE; GNUNET_free (cr->business_name); - cr->business_name = GNUNET_strdup (acfg->business_name); + cr->business_name = GNUNET_strdup (acfg->details.ok.business_name); for (unsigned int i = 0; imethods_length; i++) GNUNET_free (cr->methods[i].type); GNUNET_free (cr->methods); - cr->methods = GNUNET_new_array (acfg->methods_length, + cr->methods = GNUNET_new_array (acfg->details.ok.methods_length, struct AuthorizationMethodConfig); - for (unsigned int i = 0; imethods_length; i++) + for (unsigned int i = 0; idetails.ok.methods_length; i++) { - cr->methods[i].type = GNUNET_strdup (acfg->methods[i].type); - cr->methods[i].usage_fee = acfg->methods[i].usage_fee; + cr->methods[i].type = GNUNET_strdup (acfg->details.ok.methods[i].type); + cr->methods[i].usage_fee = acfg->details.ok.methods[i].usage_fee; } - cr->methods_length = acfg->methods_length; - cr->storage_limit_in_megabytes = acfg->storage_limit_in_megabytes; - cr->annual_fee = acfg->annual_fee; - cr->truth_upload_fee = acfg->truth_upload_fee; - cr->liability_limit = acfg->liability_limit; - cr->provider_salt = acfg->provider_salt; + cr->methods_length = acfg->details.ok.methods_length; + cr->storage_limit_in_megabytes = + acfg->details.ok.storage_limit_in_megabytes; + cr->annual_fee = acfg->details.ok.annual_fee; + cr->truth_upload_fee = acfg->details.ok.truth_upload_fee; + cr->liability_limit = acfg->details.ok.liability_limit; + cr->provider_salt = acfg->details.ok.provider_salt; } } notify_waiting (cr); - if (MHD_HTTP_OK != http_status) + if (MHD_HTTP_OK != acfg->http_status) { cr->backoff = GNUNET_TIME_STD_BACKOFF (cr->backoff); GNUNET_assert (NULL == cr->tt); diff --git a/src/restclient/anastasis_api_config.c b/src/restclient/anastasis_api_config.c index 215d224..f82cd9e 100644 --- a/src/restclient/anastasis_api_config.c +++ b/src/restclient/anastasis_api_config.c @@ -86,6 +86,10 @@ handle_config_finished (void *cls, { struct ANASTASIS_ConfigOperation *co = cls; const json_t *json = response; + struct ANASTASIS_Config acfg = { + .http_status = response_code, + .response = json + }; co->job = NULL; switch (response_code) @@ -99,27 +103,26 @@ handle_config_finished (void *cls, case MHD_HTTP_OK: { const char *name; - struct ANASTASIS_Config acfg; const json_t *methods; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("name", &name), GNUNET_JSON_spec_string ("business_name", - &acfg.business_name), + &acfg.details.ok.business_name), GNUNET_JSON_spec_string ("version", - &acfg.version), + &acfg.details.ok.version), GNUNET_JSON_spec_array_const ("methods", &methods), GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes", - &acfg.storage_limit_in_megabytes), + &acfg.details.ok.storage_limit_in_megabytes), TALER_JSON_spec_amount_any ("annual_fee", - &acfg.annual_fee), + &acfg.details.ok.annual_fee), TALER_JSON_spec_amount_any ("truth_upload_fee", - &acfg.truth_upload_fee), + &acfg.details.ok.truth_upload_fee), TALER_JSON_spec_amount_any ("liability_limit", - &acfg.liability_limit), + &acfg.details.ok.liability_limit), GNUNET_JSON_spec_fixed_auto ("provider_salt", - &acfg.provider_salt), + &acfg.details.ok.provider_salt), GNUNET_JSON_spec_end () }; @@ -132,14 +135,16 @@ handle_config_finished (void *cls, json_dumpf (json, stderr, JSON_INDENT (2)); - response_code = 0; + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } if (0 != strcmp (name, "anastasis")) { GNUNET_JSON_parse_free (spec); - response_code = 0; + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } { @@ -148,7 +153,7 @@ handle_config_finished (void *cls, unsigned int current; char dummy; - if (3 != sscanf (acfg.version, + if (3 != sscanf (acfg.details.ok.version, "%u:%u:%u%c", ¤t, &revision, @@ -156,7 +161,8 @@ handle_config_finished (void *cls, &dummy)) { GNUNET_break_op (0); - response_code = 0; + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_VERSION_MALFORMED; break; } if ( (ANASTASIS_PROTOCOL_CURRENT < current) && @@ -164,7 +170,8 @@ handle_config_finished (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Provider protocol version too new\n"); - response_code = 0; + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_VERSION_MALFORMED; break; } if ( (ANASTASIS_PROTOCOL_CURRENT > current) && @@ -173,16 +180,18 @@ handle_config_finished (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Provider protocol version too old\n"); GNUNET_break_op (0); - response_code = 0; + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_VERSION_MALFORMED; break; } } - acfg.methods_length = json_array_size (methods); + acfg.details.ok.methods_length = json_array_size (methods); { struct ANASTASIS_AuthorizationMethodConfig mcfg[GNUNET_NZL ( - acfg.methods_length)]; + acfg.details.ok. + methods_length)]; - for (unsigned int i = 0; iurl); co->cb (co->cb_cls, - MHD_HTTP_OK, &acfg); ANASTASIS_config_cancel (co); return; @@ -236,8 +245,7 @@ handle_config_finished (void *cls, } end: co->cb (co->cb_cls, - response_code, - NULL); + &acfg); ANASTASIS_config_cancel (co); } diff --git a/src/restclient/anastasis_api_policy_lookup.c b/src/restclient/anastasis_api_policy_lookup.c index 42db90d..b3132ef 100644 --- a/src/restclient/anastasis_api_policy_lookup.c +++ b/src/restclient/anastasis_api_policy_lookup.c @@ -106,6 +106,9 @@ handle_policy_lookup_finished (void *cls, size_t data_size) { struct ANASTASIS_PolicyLookupOperation *plo = cls; + struct ANASTASIS_DownloadDetails dd = { + .http_status = response_code + }; plo->job = NULL; switch (response_code) @@ -117,7 +120,6 @@ handle_policy_lookup_finished (void *cls, break; case MHD_HTTP_OK: { - struct ANASTASIS_DownloadDetails dd; struct ANASTASIS_UploadSignaturePS usp = { .purpose.purpose = htonl (TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD), .purpose.size = htonl (sizeof (usp)), @@ -133,18 +135,17 @@ handle_policy_lookup_finished (void *cls, &plo->account_pub.pub)) { GNUNET_break_op (0); - response_code = 0; + dd.http_status = 0; + dd.ec = -1; // FIXME: needs new code in Gana! break; } /* Success, call callback with all details! */ - memset (&dd, 0, sizeof (dd)); - dd.sig = plo->account_sig; - dd.curr_policy_hash = usp.new_recovery_data_hash; - dd.policy = data; - dd.policy_size = data_size; - dd.version = plo->version; + dd.details.ok.sig = plo->account_sig; + dd.details.ok.curr_policy_hash = usp.new_recovery_data_hash; + dd.details.ok.policy = data; + dd.details.ok.policy_size = data_size; + dd.details.ok.version = plo->version; plo->cb (plo->cb_cls, - response_code, &dd); plo->cb = NULL; ANASTASIS_policy_lookup_cancel (plo); @@ -167,12 +168,10 @@ handle_policy_lookup_finished (void *cls, "Unexpected response code %u\n", (unsigned int) response_code); GNUNET_break (0); - response_code = 0; break; } plo->cb (plo->cb_cls, - response_code, - NULL); + &dd); plo->cb = NULL; ANASTASIS_policy_lookup_cancel (plo); } diff --git a/src/restclient/anastasis_api_policy_meta_lookup.c b/src/restclient/anastasis_api_policy_meta_lookup.c index 3d1482f..cf381fd 100644 --- a/src/restclient/anastasis_api_policy_meta_lookup.c +++ b/src/restclient/anastasis_api_policy_meta_lookup.c @@ -90,6 +90,10 @@ handle_policy_meta_lookup_finished (void *cls, { struct ANASTASIS_PolicyMetaLookupOperation *plo = cls; const json_t *json = response; + struct ANASTASIS_MetaDownloadDetails mdd = { + .http_status = response_code, + .response = json + }; plo->job = NULL; switch (response_code) @@ -116,10 +120,6 @@ handle_policy_meta_lookup_finished (void *cls, { struct ANASTASIS_MetaDataEntry metas[GNUNET_NZL (mlen)]; void *md[GNUNET_NZL (mlen)]; - struct ANASTASIS_MetaDownloadDetails mdd = { - .metas = metas, - .metas_length = mlen - }; size_t off = 0; const char *label; const json_t *val; @@ -127,6 +127,8 @@ handle_policy_meta_lookup_finished (void *cls, memset (md, 0, sizeof (md)); + mdd.details.ok.metas = metas; + mdd.details.ok.metas_length = mlen; json_object_foreach ((json_t *) json, label, val) @@ -148,6 +150,8 @@ handle_policy_meta_lookup_finished (void *cls, &dummy)) { GNUNET_break (0); + mdd.http_status = 0; + mdd.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } if (GNUNET_OK != @@ -156,6 +160,8 @@ handle_policy_meta_lookup_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); + mdd.http_status = 0; + mdd.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } metas[off].version = (uint32_t) ver; @@ -165,13 +171,13 @@ handle_policy_meta_lookup_finished (void *cls, if (off < mlen) { GNUNET_break (0); - response_code = 0; + mdd.http_status = 0; + mdd.ec = TALER_EC_GENERIC_REPLY_MALFORMED; for (size_t i = 0; icb (plo->cb_cls, - response_code, &mdd); for (size_t i = 0; icb (plo->cb_cls, - response_code, - NULL); + &mdd); plo->cb = NULL; ANASTASIS_policy_meta_lookup_cancel (plo); } diff --git a/src/testing/testing_api_cmd_config.c b/src/testing/testing_api_cmd_config.c index 7b0dbca..069200b 100644 --- a/src/testing/testing_api_cmd_config.c +++ b/src/testing/testing_api_cmd_config.c @@ -61,29 +61,25 @@ struct ConfigState * Function called with the results of a #ANASTASIS_get_config(). * * @param cls closure - * @param http_status HTTP status of the request * @param config config from the server */ static void config_cb (void *cls, - unsigned int http_status, const struct ANASTASIS_Config *config) { struct ConfigState *ss = cls; ss->so = NULL; - if (http_status != ss->http_status) + if (config->http_status != ss->http_status) { TALER_TESTING_unexpected_status (ss->is, - http_status, + config->http_status, ss->http_status); } - if (NULL == config) + if (GNUNET_OK == config->http_status) { - TALER_TESTING_interpreter_fail (ss->is); - return; + ss->provider_salt = config->details.ok.provider_salt; } - ss->provider_salt = config->provider_salt; TALER_TESTING_interpreter_next (ss->is); } diff --git a/src/testing/testing_api_cmd_policy_lookup.c b/src/testing/testing_api_cmd_policy_lookup.c index e8c4983..58c7ddb 100644 --- a/src/testing/testing_api_cmd_policy_lookup.c +++ b/src/testing/testing_api_cmd_policy_lookup.c @@ -72,27 +72,25 @@ struct PolicyLookupState * Function called with the results of a #ANASTASIS_policy_lookup(). * * @param cls closure - * @param http_status HTTP status of the request * @param dd details about the lookup operation */ static void policy_lookup_cb (void *cls, - unsigned int http_status, const struct ANASTASIS_DownloadDetails *dd) { struct PolicyLookupState *pls = cls; pls->plo = NULL; - if (http_status != pls->http_status) + if (dd->http_status != pls->http_status) { TALER_TESTING_unexpected_status (pls->is, - http_status, + dd->http_status, pls->http_status); } if (NULL != pls->upload_reference) { - if ( (MHD_HTTP_OK == http_status) && - (0 != GNUNET_memcmp (&dd->curr_policy_hash, + if ( (MHD_HTTP_OK == dd->http_status) && + (0 != GNUNET_memcmp (&dd->details.ok.curr_policy_hash, pls->upload_hash)) ) { GNUNET_break (0); -- cgit v1.2.3