From 362bf0c5bd2270ed6a54dfbdfd83702dca892797 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 20 Jul 2021 19:33:59 +0200 Subject: -workshop refactoring --- src/backend/Makefile.am | 2 + src/backend/taler-merchant-httpd.c | 17 ++- src/backend/taler-merchant-httpd.h | 6 + src/backend/taler-merchant-httpd_helper.c | 106 +++++++++++++++ src/backend/taler-merchant-httpd_helper.h | 50 +++++++ ...ler-merchant-httpd_private-patch-instances-ID.c | 146 +++++++-------------- .../taler-merchant-httpd_private-post-instances.c | 76 ++--------- 7 files changed, 234 insertions(+), 169 deletions(-) create mode 100644 src/backend/taler-merchant-httpd_helper.c create mode 100644 src/backend/taler-merchant-httpd_helper.h (limited to 'src/backend') diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index b25b8d3d..da825d3b 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -27,6 +27,8 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_get-orders-ID.h \ taler-merchant-httpd_get-tips-ID.c \ taler-merchant-httpd_get-tips-ID.h \ + taler-merchant-httpd_helper.c \ + taler-merchant-httpd_helper.h \ taler-merchant-httpd_private-get-tips.c \ taler-merchant-httpd_private-get-tips.h \ taler-merchant-httpd_private-get-tips-ID.c \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index bfc0337e..861b5f47 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -69,6 +69,10 @@ #include "taler-merchant-httpd_statics.h" #include "taler-merchant-httpd_templating.h" +/** + * Fixme: document. + */ +#define INSTANCE_STALENESS GNUNET_TIME_UNIT_MINUTES /** * Backlog for listen operation on unix-domain sockets. @@ -908,6 +912,8 @@ struct TMH_MerchantInstance * TMH_lookup_instance (const char *instance_id) { struct GNUNET_HashCode h_instance; + struct TMH_MerchantInstance *mi; + struct GNUNET_TIME_Relative age; if (NULL == instance_id) instance_id = "default"; @@ -920,8 +926,14 @@ TMH_lookup_instance (const char *instance_id) instance_id); /* We're fine if that returns NULL, the calling routine knows how to handle that */ - return GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map, - &h_instance); + mi = GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map, + &h_instance); + age = GNUNET_TIME_absolute_get_duration (mi->staleness); + if (age.rel_value_us > INSTANCE_STALENESS.rel_value_us) + { + // FIXME: referesh from DB + } + return mi; } @@ -2038,6 +2050,7 @@ add_instance_cb (void *cls, else mi->deleted = true; mi->merchant_pub = *merchant_pub; + mi->staleness = GNUNET_TIME_absolute_get (); for (unsigned int i = 0; i +*/ +/** + * @file taler-merchant-httpd_helper.c + * @brief shared logic for various handlers + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include +#include "taler-merchant-httpd_helper.h" + +/** + * check @a payto_uris for well-formedness + * + * @param payto_uris JSON array of payto URIs (presumably) + * @return true if they are all valid URIs (and this is an array of strings) + */ +bool +TMH_payto_uri_array_valid (const json_t *payto_uris) +{ + bool payto_ok = true; + + if (! json_is_array (payto_uris)) + { + GNUNET_break_op (0); + payto_ok = false; + } + else + { + unsigned int len = json_array_size (payto_uris); + + for (unsigned int i = 0; ij_wire = json_pack ("{s:s, s:o}", + "payto_uri", payto_uri, + "salt", GNUNET_JSON_from_data_auto (&salt)); + GNUNET_assert (NULL != wm->j_wire); + /* This also tests for things like the IBAN being malformed */ + GNUNET_assert (GNUNET_OK == + TALER_JSON_merchant_wire_signature_hash (wm->j_wire, + &wm->h_wire)); + wm->wire_method + = TALER_payto_get_method (payto_uri); + GNUNET_assert (NULL != wm->wire_method); /* checked earlier */ + wm->active = true; + return wm; +} diff --git a/src/backend/taler-merchant-httpd_helper.h b/src/backend/taler-merchant-httpd_helper.h new file mode 100644 index 00000000..5f478c18 --- /dev/null +++ b/src/backend/taler-merchant-httpd_helper.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2021 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ + +/** + * @file taler-merchant-httpd_helper.h + * @brief helpers for shared logic + * @author Florian Dold + * @author Benedikt Mueller + * @author Christian Grothoff + */ +#ifndef TALER_EXCHANGE_HTTPD_HELPER_H +#define TALER_EXCHANGE_HTTPD_HELPER_H + + +#include "taler-merchant-httpd.h" + +/** + * check @a payto_uris for well-formedness + * + * @param payto_uris JSON array of payto URIs (presumably) + * @return true if they are all valid URIs (and this is an array of strings) + */ +bool +TMH_payto_uri_array_valid (const json_t *payto_uris); + + +/** + * Setup new wire method for the given @ payto_uri. + * + * @param payto_uri already validated payto URI + * @return new wire method object, never fails + */ +struct TMH_WireMethod * +TMH_setup_wire_account (const char *payto_uri); + + +#endif diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c index 0a839a3a..8b0917e7 100644 --- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c @@ -24,6 +24,7 @@ */ #include "platform.h" #include "taler-merchant-httpd_private-patch-instances-ID.h" +#include "taler-merchant-httpd_helper.h" #include @@ -74,12 +75,12 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, &is.address), GNUNET_JSON_spec_json ("jurisdiction", &is.jurisdiction), - TALER_JSON_spec_amount ("default_max_deposit_fee", - &is.default_max_deposit_fee), TALER_JSON_spec_amount ("default_max_wire_fee", &is.default_max_wire_fee), GNUNET_JSON_spec_uint32 ("default_wire_fee_amortization", &is.default_wire_fee_amortization), + TALER_JSON_spec_amount ("default_max_deposit_fee", + &is.default_max_deposit_fee), TALER_JSON_spec_relative_time ("default_wire_transfer_delay", &is.default_wire_transfer_delay), TALER_JSON_spec_relative_time ("default_pay_delay", @@ -87,6 +88,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, GNUNET_JSON_spec_end () }; enum GNUNET_DB_QueryStatus qs; + bool committed = false; GNUNET_assert (NULL != mi); { @@ -100,7 +102,19 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, ? MHD_YES : MHD_NO; } - if (! json_is_array (payto_uris)) + if ((0 != strcasecmp (is.default_max_deposit_fee.currency, + TMH_currency)) || + (0 != strcasecmp (is.default_max_wire_fee.currency, + TMH_currency))) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_GENERIC_CURRENCY_MISMATCH, + NULL); + } + if (! TMH_payto_uri_array_valid (payto_uris)) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PAYTO_URI_MALFORMED, @@ -119,18 +133,6 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, free_wm (wm); } } - if ((0 != strcasecmp (is.default_max_deposit_fee.currency, - TMH_currency)) || - (0 != strcasecmp (is.default_max_wire_fee.currency, - TMH_currency))) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_GENERIC_CURRENCY_MISMATCH, - NULL); - } if (GNUNET_OK != TMH_db->start (TMH_db->cls, "PATCH /instances")) @@ -199,31 +201,12 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, { const char *str = json_string_value (json_array_get (payto_uris, i)); - if (NULL == str) - { - GNUNET_break_op (0); - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - GNUNET_assert (NULL == wm_head); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PAYTO_URI_MALFORMED, - NULL); - } if (0 == strcasecmp (uri, str)) { - if (NULL != matches[i]) - { - GNUNET_break (0); - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - GNUNET_assert (NULL == wm_head); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PAYTO_URI_MALFORMED, - str); - } + /* our own existing payto URIs should be unique, that is no + duplicates in the list, so we cannot match twice */ + GNUNET_assert (NULL == matches[i]); matches[i] = wm; matched = true; break; @@ -239,6 +222,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, uri); wm->deleting = true; qs = TMH_db->inactivate_account (TMH_db->cls, + mi->settings.id, &wm->h_wire); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { @@ -262,6 +246,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, if (! wm->active) { qs = TMH_db->activate_account (TMH_db->cls, + mi->settings.id, &wm->h_wire); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { @@ -281,51 +266,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding NEW account `%s'\n", ad.payto_uri); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, - &ad.salt, - sizeof (ad.salt)); - wm = GNUNET_new (struct TMH_WireMethod); - wm->j_wire = json_pack ("{s:s, s:o}", - "payto_uri", ad.payto_uri, - "salt", GNUNET_JSON_from_data_auto (&ad.salt)); - GNUNET_assert (NULL != wm->j_wire); - wm->wire_method - = TALER_payto_get_method (ad.payto_uri); - if (NULL == wm->wire_method) - { - GNUNET_break_op (0); - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - json_decref (wm->j_wire); - GNUNET_free (wm); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PAYTO_URI_MALFORMED, - ad.payto_uri); - - } - /* This also tests for things like the IBAN being malformed */ - if (GNUNET_OK != - TALER_JSON_merchant_wire_signature_hash (wm->j_wire, - &wm->h_wire)) - { - GNUNET_break_op (0); - free_wm (wm); - while (NULL != (wm = wm_head)) - { - GNUNET_CONTAINER_DLL_remove (wm_head, - wm_tail, - wm); - free_wm (wm); - } - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PAYTO_URI_MALFORMED, - ad.payto_uri); - } - wm->active = true; + wm = TMH_setup_wire_account (ad.payto_uri); GNUNET_CONTAINER_DLL_insert (wm_head, wm_tail, wm); @@ -349,10 +290,31 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, retry: if (GNUNET_DB_STATUS_SOFT_ERROR == qs) continue; + if (qs >= 0) + committed = true; break; } /* for(... MAX_RETRIES) */ giveup: - if (0 > qs) + /* Deactivate existing wire methods that were removed above */ + for (struct TMH_WireMethod *wm = mi->wm_head; + NULL != wm; + wm = wm->next) + { + /* We did not flip the 'active' bits earlier because the + DB transaction could still fail. Now it is time to update our + runtime state. */ + GNUNET_assert (! (wm->deleting & wm->enabling)); + if (committed) + { + if (wm->deleting) + wm->active = false; + if (wm->enabling) + wm->active = true; + } + wm->deleting = false; + wm->enabling = false; + } + if (! committed) { struct TMH_WireMethod *wm; @@ -369,22 +331,6 @@ giveup: TALER_EC_GENERIC_DB_COMMIT_FAILED, NULL); } - /* Deactivate existing wire methods that were removed above */ - for (struct TMH_WireMethod *wm = mi->wm_head; - NULL != wm; - wm = wm->next) - { - /* We did not flip the 'active' bits earlier because the - DB transaction could still fail. Now it is time to update our - runtime state. */ - GNUNET_assert (! (wm->deleting & wm->enabling)); - if (wm->deleting) - wm->active = false; - if (wm->enabling) - wm->active = true; - wm->deleting = false; - wm->enabling = false; - } /* Update our 'settings' */ GNUNET_free (mi->settings.name); @@ -400,6 +346,8 @@ giveup: { struct TMH_WireMethod *wm; + /* Note: this _could_ be done more efficiently if + someone wrote a GNUNET_CONTAINER_DLL_merge()... */ while (NULL != (wm = wm_head)) { GNUNET_CONTAINER_DLL_remove (wm_head, diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c index f9df3d39..71739c3d 100644 --- a/src/backend/taler-merchant-httpd_private-post-instances.c +++ b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -24,6 +24,7 @@ */ #include "platform.h" #include "taler-merchant-httpd_private-post-instances.h" +#include "taler-merchant-httpd_helper.h" #include #include @@ -234,56 +235,11 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, } /* check payto_uris for well-formedness */ - { - bool payto_ok = true; - - if (! json_is_array (payto_uris)) - { - GNUNET_break_op (0); - payto_ok = false; - } - else - { - unsigned int len = json_array_size (payto_uris); - - for (unsigned int i = 0; ij_wire = json_pack ("{s:O, s:o}", - "payto_uri", payto_uri, - "salt", GNUNET_JSON_from_data_auto (&salt)); - GNUNET_assert (NULL != wm->j_wire); - /* This also tests for things like the IBAN being malformed */ - GNUNET_assert (GNUNET_OK == - TALER_JSON_merchant_wire_signature_hash (wm->j_wire, - &wm->h_wire)); - wm->wire_method - = TALER_payto_get_method (json_string_value (payto_uri)); - GNUNET_assert (NULL != wm->wire_method); /* checked earlier */ - wm->active = true; + + wm = TMH_setup_wire_account (json_string_value (payto_uri)); GNUNET_CONTAINER_DLL_insert (wm_head, wm_tail, wm); -- cgit v1.2.3