diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-02-09 20:05:25 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-02-09 20:05:38 +0100 |
commit | 49bbea1c6bbc64f48ccffa6595acbde204c2e867 (patch) | |
tree | 60cfa2fd371b4d6d101175c4a08428bf1e15b6c6 /src/backend | |
parent | 231d1b19d14e8aba67795e3d147a58331bafc9aa (diff) | |
download | merchant-49bbea1c6bbc64f48ccffa6595acbde204c2e867.tar.gz merchant-49bbea1c6bbc64f48ccffa6595acbde204c2e867.tar.bz2 merchant-49bbea1c6bbc64f48ccffa6595acbde204c2e867.zip |
remove reserve/rewards
Diffstat (limited to 'src/backend')
24 files changed, 4 insertions, 3784 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 2fe09eec..9ece7912 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -28,14 +28,8 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_exchanges.c taler-merchant-httpd_exchanges.h \ taler-merchant-httpd_get-orders-ID.c \ taler-merchant-httpd_get-orders-ID.h \ - taler-merchant-httpd_get-rewards-ID.c \ - taler-merchant-httpd_get-rewards-ID.h \ taler-merchant-httpd_helper.c \ taler-merchant-httpd_helper.h \ - taler-merchant-httpd_private-get-rewards.c \ - taler-merchant-httpd_private-get-rewards.h \ - taler-merchant-httpd_private-get-rewards-ID.c \ - taler-merchant-httpd_private-get-rewards-ID.h \ taler-merchant-httpd_mhd.c \ taler-merchant-httpd_mhd.h \ taler-merchant-httpd_private-delete-account-ID.c \ @@ -50,8 +44,6 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-delete-orders-ID.h \ taler-merchant-httpd_private-delete-otp-devices-ID.c \ taler-merchant-httpd_private-delete-otp-devices-ID.h \ - taler-merchant-httpd_private-delete-reserves-ID.c \ - taler-merchant-httpd_private-delete-reserves-ID.h \ taler-merchant-httpd_private-delete-templates-ID.c \ taler-merchant-httpd_private-delete-templates-ID.h \ taler-merchant-httpd_private-delete-token-families-SLUG.c \ @@ -82,10 +74,6 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-get-otp-devices.h \ taler-merchant-httpd_private-get-otp-devices-ID.c \ taler-merchant-httpd_private-get-otp-devices-ID.h \ - taler-merchant-httpd_private-get-reserves.c \ - taler-merchant-httpd_private-get-reserves.h \ - taler-merchant-httpd_private-get-reserves-ID.c \ - taler-merchant-httpd_private-get-reserves-ID.h \ taler-merchant-httpd_private-get-transfers.c \ taler-merchant-httpd_private-get-transfers.h \ taler-merchant-httpd_private-get-templates.c \ @@ -134,10 +122,6 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-post-otp-devices.h \ taler-merchant-httpd_private-post-products-ID-lock.c \ taler-merchant-httpd_private-post-products-ID-lock.h \ - taler-merchant-httpd_private-post-reserves.c \ - taler-merchant-httpd_private-post-reserves.h \ - taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c \ - taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h \ taler-merchant-httpd_private-post-templates.c \ taler-merchant-httpd_private-post-templates.h \ taler-merchant-httpd_private-post-token-families.c \ @@ -156,14 +140,10 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_post-orders-ID-paid.h \ taler-merchant-httpd_post-orders-ID-refund.c \ taler-merchant-httpd_post-orders-ID-refund.h \ - taler-merchant-httpd_post-rewards-ID-pickup.c \ - taler-merchant-httpd_post-rewards-ID-pickup.h \ taler-merchant-httpd_post-using-templates.c \ taler-merchant-httpd_post-using-templates.h \ taler-merchant-httpd_qr.c \ taler-merchant-httpd_qr.h \ - taler-merchant-httpd_reserves.c \ - taler-merchant-httpd_reserves.h \ taler-merchant-httpd_spa.c \ taler-merchant-httpd_spa.h \ taler-merchant-httpd_statics.c \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 608a00a6..42cf08ee 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -31,7 +31,6 @@ #include "taler-merchant-httpd_config.h" #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_get-orders-ID.h" -#include "taler-merchant-httpd_get-rewards-ID.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_private-delete-account-ID.h" #include "taler-merchant-httpd_private-delete-instances-ID.h" @@ -39,7 +38,6 @@ #include "taler-merchant-httpd_private-delete-products-ID.h" #include "taler-merchant-httpd_private-delete-orders-ID.h" #include "taler-merchant-httpd_private-delete-otp-devices-ID.h" -#include "taler-merchant-httpd_private-delete-reserves-ID.h" #include "taler-merchant-httpd_private-delete-templates-ID.h" #include "taler-merchant-httpd_private-delete-token-families-SLUG.h" #include "taler-merchant-httpd_private-delete-transfers-ID.h" @@ -55,10 +53,6 @@ #include "taler-merchant-httpd_private-get-orders-ID.h" #include "taler-merchant-httpd_private-get-otp-devices.h" #include "taler-merchant-httpd_private-get-otp-devices-ID.h" -#include "taler-merchant-httpd_private-get-reserves.h" -#include "taler-merchant-httpd_private-get-reserves-ID.h" -#include "taler-merchant-httpd_private-get-rewards-ID.h" -#include "taler-merchant-httpd_private-get-rewards.h" #include "taler-merchant-httpd_private-get-templates.h" #include "taler-merchant-httpd_private-get-templates-ID.h" #include "taler-merchant-httpd_private-get-token-families.h" @@ -83,8 +77,6 @@ #include "taler-merchant-httpd_private-post-orders-ID-refund.h" #include "taler-merchant-httpd_private-post-products.h" #include "taler-merchant-httpd_private-post-products-ID-lock.h" -#include "taler-merchant-httpd_private-post-reserves.h" -#include "taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h" #include "taler-merchant-httpd_private-post-templates.h" #include "taler-merchant-httpd_private-post-token-families.h" #include "taler-merchant-httpd_private-post-transfers.h" @@ -95,8 +87,6 @@ #include "taler-merchant-httpd_post-orders-ID-pay.h" #include "taler-merchant-httpd_post-using-templates.h" #include "taler-merchant-httpd_post-orders-ID-refund.h" -#include "taler-merchant-httpd_post-rewards-ID-pickup.h" -#include "taler-merchant-httpd_reserves.h" #include "taler-merchant-httpd_spa.h" #include "taler-merchant-httpd_statics.h" @@ -405,13 +395,10 @@ do_shutdown (void *cls) { (void) cls; TMH_force_orders_resume (); - TMH_force_reward_resume (); TMH_force_ac_resume (); TMH_force_pc_resume (); TMH_force_kyc_resume (); - TMH_force_rc_resume (); TMH_force_gorc_resume (); - TMH_force_reward_pickup_resume (); TMH_force_wallet_get_order_resume (); TMH_force_wallet_refund_order_resume (); { @@ -421,7 +408,6 @@ do_shutdown (void *cls) if (NULL != mhd) MHD_stop_daemon (mhd); } - TMH_RESERVES_done (); if (NULL != instance_eh) { TMH_db->event_listen_cancel (instance_eh); @@ -1034,73 +1020,6 @@ url_handler (void *cls, .allow_deleted_instance = true, .handler = &TMH_private_delete_orders_ID }, - /* POST /reserves: */ - { - .url_prefix = "/reserves", - .method = MHD_HTTP_METHOD_POST, - .handler = &TMH_private_post_reserves, - /* the body should be pretty small, allow 1 MB of upload - to set a conservative bound for sane wallets */ - .max_upload = 1024 * 1024 - }, - /* DELETE /reserves/$ID: */ - { - .url_prefix = "/reserves/", - .have_id_segment = true, - .allow_deleted_instance = true, - .method = MHD_HTTP_METHOD_DELETE, - .handler = &TMH_private_delete_reserves_ID - }, - /* POST /reserves/$ID/authorize-reward: */ - { - .url_prefix = "/reserves/", - .url_suffix = "authorize-reward", - .have_id_segment = true, - .method = MHD_HTTP_METHOD_POST, - .handler = &TMH_private_post_reserves_ID_authorize_reward, - /* the body should be pretty small, allow 1 MB of upload - to set a conservative bound for sane wallets */ - .max_upload = 1024 * 1024 - }, - /* POST /rewards: */ - { - .url_prefix = "/rewards", - .method = MHD_HTTP_METHOD_POST, - .handler = &TMH_private_post_rewards, - /* the body should be pretty small, allow 1 MB of upload - to set a conservative bound for sane wallets */ - .max_upload = 1024 * 1024 - }, - /* GET /rewards: */ - { - .url_prefix = "/rewards", - .allow_deleted_instance = true, - .method = MHD_HTTP_METHOD_GET, - .handler = &TMH_private_get_rewards - }, - /* GET /rewards/$ID: */ - { - .url_prefix = "/rewards/", - .method = MHD_HTTP_METHOD_GET, - .allow_deleted_instance = true, - .have_id_segment = true, - .handler = &TMH_private_get_rewards_ID - }, - /* GET /reserves: */ - { - .url_prefix = "/reserves", - .allow_deleted_instance = true, - .method = MHD_HTTP_METHOD_GET, - .handler = &TMH_private_get_reserves - }, - /* GET /reserves/$ID: */ - { - .url_prefix = "/reserves/", - .allow_deleted_instance = true, - .have_id_segment = true, - .method = MHD_HTTP_METHOD_GET, - .handler = &TMH_private_get_reserves_ID - }, /* POST /transfers: */ { .url_prefix = "/transfers", @@ -1463,26 +1382,6 @@ url_handler (void *cls, .have_id_segment = true, .handler = &TMH_get_orders_ID }, - /* GET /rewards/$ID: */ - { - .url_prefix = "/rewards/", - .method = MHD_HTTP_METHOD_GET, - .allow_deleted_instance = true, - .have_id_segment = true, - .handler = &TMH_get_rewards_ID - }, - /* POST /rewards/$ID/pickup: */ - { - .url_prefix = "/rewards/", - .method = MHD_HTTP_METHOD_POST, - .have_id_segment = true, - .allow_deleted_instance = true, - .url_suffix = "pickup", - .handler = &TMH_post_rewards_ID_pickup, - /* wallet may give us many coins to sign, allow 1 MB of upload - to set a conservative bound for sane wallets */ - .max_upload = 1024 * 1024 - }, /* GET /static/ *: */ { .url_prefix = "/static/", @@ -2385,8 +2284,6 @@ run (void *cls, load_instances (NULL, NULL, 0); - /* start watching reserves */ - TMH_RESERVES_init (); fh = TALER_MHD_bind (cfg, "merchant", &port); diff --git a/src/backend/taler-merchant-httpd_config.c b/src/backend/taler-merchant-httpd_config.c index 3c318b1a..784bdcf9 100644 --- a/src/backend/taler-merchant-httpd_config.c +++ b/src/backend/taler-merchant-httpd_config.c @@ -42,7 +42,7 @@ * #MERCHANT_PROTOCOL_CURRENT and #MERCHANT_PROTOCOL_AGE in * merchant_api_config.c! */ -#define MERCHANT_PROTOCOL_VERSION "8:1:4" +#define MERCHANT_PROTOCOL_VERSION "8:2:0" /** diff --git a/src/backend/taler-merchant-httpd_get-rewards-ID.c b/src/backend/taler-merchant-httpd_get-rewards-ID.c deleted file mode 100644 index e1232735..00000000 --- a/src/backend/taler-merchant-httpd_get-rewards-ID.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of TALER - (C) 2014-2023 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_get-rewards-ID.c - * @brief implementation of GET /rewards/$ID - * @author Marcello Stanisci - * @author Christian Grothoff - */ -#include "platform.h" -#include <jansson.h> -#include <taler/taler_signatures.h> -#include <taler/taler_json_lib.h> -#include <taler/taler_templating_lib.h> -#include "taler-merchant-httpd_get-rewards-ID.h" -#include "taler-merchant-httpd_helper.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_qr.h" - - -char * -TMH_make_taler_reward_uri (struct MHD_Connection *con, - const struct TALER_RewardIdentifierP *reward_id, - const char *instance_id) -{ - struct GNUNET_Buffer buf = { 0 }; - - GNUNET_assert (NULL != instance_id); - GNUNET_assert (NULL != reward_id); - if (GNUNET_OK != - TMH_taler_uri_by_connection (con, - "reward", - instance_id, - &buf)) - { - GNUNET_break (0); - return NULL; - } - /* Ensure previous part is slash-terminated */ - GNUNET_buffer_write_path (&buf, - ""); - GNUNET_buffer_write_data_encoded (&buf, - reward_id, - sizeof (*reward_id)); - return GNUNET_buffer_reap_str (&buf); -} - - -char * -TMH_make_reward_status_url (struct MHD_Connection *con, - const struct TALER_RewardIdentifierP *reward_id, - const char *instance_id) -{ - struct GNUNET_Buffer buf; - - GNUNET_assert (NULL != instance_id); - GNUNET_assert (NULL != reward_id); - if (GNUNET_OK != - TMH_base_url_by_connection (con, - instance_id, - &buf)) - { - GNUNET_break (0); - return NULL; - } - GNUNET_buffer_write_path (&buf, - "rewards/"); - GNUNET_buffer_write_data_encoded (&buf, - reward_id, - sizeof (*reward_id)); - return GNUNET_buffer_reap_str (&buf); -} - - -MHD_RESULT -TMH_get_rewards_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TALER_RewardIdentifierP reward_id; - enum GNUNET_DB_QueryStatus qs; - struct TALER_Amount total_authorized; - struct TALER_Amount total_picked_up; - struct GNUNET_TIME_Timestamp expiration; - char *exchange_url; - char *next_url; - struct TALER_ReservePrivateKeyP reserve_priv; - - (void) rh; - if (GNUNET_OK != - GNUNET_CRYPTO_hash_from_string (hc->infix, - &reward_id.hash)) - { - /* reward_id has wrong encoding */ - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - hc->infix); - } - - TMH_db->preflight (TMH_db->cls); - qs = TMH_db->lookup_reward (TMH_db->cls, - hc->instance->settings.id, - &reward_id, - &total_authorized, - &total_picked_up, - &expiration, - &exchange_url, - &next_url, - &reserve_priv); - if (0 > qs) - { - /* single, read-only SQL statements should never cause - serialization problems */ - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); - /* Always report on hard error as well to enable diagnostics */ - GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Unknown reward id given: `%s'\n", - hc->infix); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN, - hc->infix); - } - - /* Build response */ - { - struct TALER_Amount remaining; - MHD_RESULT ret; - - GNUNET_break (0 <= - TALER_amount_subtract (&remaining, - &total_authorized, - &total_picked_up)); - if (TMH_MHD_test_html_desired (connection)) - { - char *qr; - char *uri; - char *reward_status_url; - - uri = TMH_make_taler_reward_uri (connection, - &reward_id, - hc->instance->settings.id); - reward_status_url = TMH_make_reward_status_url (connection, - &reward_id, - hc->instance->settings.id); - qr = TMH_create_qrcode (uri); - if (NULL == qr) - { - GNUNET_break (0); - GNUNET_free (uri); - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_ALLOCATION_FAILURE, - "during QR code generation"); - } - else - { - json_t *context; - - context = GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("remaining_reward", - &remaining), - GNUNET_JSON_pack_string ("taler_reward_uri", - uri), - GNUNET_JSON_pack_string ("next_url", - next_url), - GNUNET_JSON_pack_string ("taler_reward_qrcode_svg", - qr)); - ret = TALER_TEMPLATING_reply (connection, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) - ? MHD_HTTP_GONE - : MHD_HTTP_OK, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) - ? "depleted_reward" - : "offer_reward", - hc->instance->settings.id, - uri, - context); - json_decref (context); - } - GNUNET_free (reward_status_url); - GNUNET_free (uri); - GNUNET_free (qr); - } - else - { - ret = TALER_MHD_REPLY_JSON_PACK ( - connection, - TALER_amount_is_zero (&remaining) - ? MHD_HTTP_GONE - : MHD_HTTP_OK, - GNUNET_JSON_pack_string ("exchange_url", - exchange_url), - GNUNET_JSON_pack_string ("next_url", - next_url), - TALER_JSON_pack_amount ("reward_amount", - &remaining), - GNUNET_JSON_pack_timestamp ("expiration", - expiration)); - } - GNUNET_free (exchange_url); - GNUNET_free (next_url); - return ret; - } -} - - -/* end of taler-merchant-httpd_get-rewards-ID.c */ diff --git a/src/backend/taler-merchant-httpd_get-rewards-ID.h b/src/backend/taler-merchant-httpd_get-rewards-ID.h deleted file mode 100644 index 29a3c122..00000000 --- a/src/backend/taler-merchant-httpd_get-rewards-ID.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - This file is part of TALER - (C) 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_get-rewards-ID.h - * @brief implementation of GET /rewards/$ID - * @author Marcello Stanisci - */ -#ifndef TALER_MERCHANT_HTTPD_GET_REWARDS_ID_H -#define TALER_MERCHANT_HTTPD_GET_REWARDS_ID_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - -/** - * Create a taler://reward/ URI for the given @a con and @a reward_id - * and @a instance_id. - * - * @param con HTTP connection - * @param reward_id the reward id - * @param instance_id instance, may be "default" - * @return corresponding taler://reward/ URI, or NULL on missing "host" - */ -char * -TMH_make_taler_reward_uri (struct MHD_Connection *con, - const struct TALER_RewardIdentifierP *reward_id, - const char *instance_id); - -/** - * Create a http(s):// URL for the given @a con and @a reward_id - * and @a instance_id. - * - * @param con HTTP connection - * @param reward_id the reward id - * @param instance_id instance, may be "default" - * @return corresponding taler://reward/ URI, or NULL on missing "host" - */ -char * -TMH_make_reward_status_url (struct MHD_Connection *con, - const struct TALER_RewardIdentifierP *reward_id, - const char *instance_id); - -/** - * Handle a GET "/rewards/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_get_rewards_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.c b/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.c deleted file mode 100644 index cd8d03a6..00000000 --- a/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* - This file is part of TALER - (C) 2017-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_post-rewards-ID-pickup.c - * @brief implementation of a POST /rewards/ID/pickup handler - * @author Christian Grothoff - */ -#include "platform.h" -#include <microhttpd.h> -#include <jansson.h> -#include <taler/taler_json_lib.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_signatures.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_helper.h" -#include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_post-rewards-ID-pickup.h" - - -/** - * How often do we retry on serialization errors? - */ -#define MAX_RETRIES 3 - -/** - * How long do we give the exchange operation to complete withdrawing - * all of the planchets? - */ -#define EXCHANGE_TIMEOUT GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_SECONDS, 45) - - -/** - * Active pickup operations. - */ -struct PickupContext; - - -/** - * Handle for an individual planchet we are processing for a reward. - */ -struct PlanchetOperation -{ - /** - * Active pickup operation this planchet belongs with. - */ - struct PickupContext *pc; - - /** - * Kept in a DLL. - */ - struct PlanchetOperation *prev; - - /** - * Kept in a DLL. - */ - struct PlanchetOperation *next; - - /** - * Find operation (while active), later NULL. - */ - struct TMH_EXCHANGES_KeysOperation *fo; - - /** - * Withdraw handle (NULL while @e fo is active). - */ - struct TALER_EXCHANGE_BatchWithdraw2Handle *w2h; - - /** - * Details about the planchet for withdrawing. - */ - struct TALER_PlanchetDetail pd; - - /** - * Offset of this planchet in the original request. - */ - unsigned int offset; -}; - - -/** - * Active pickup operations. - */ -struct PickupContext -{ - /** - * Kept in a DLL. - */ - struct PickupContext *next; - - /** - * Kept in a DLL. - */ - struct PickupContext *prev; - - /** - * The connection. - */ - struct MHD_Connection *connection; - - /** - * Request context. - */ - struct TMH_HandlerContext *hc; - - /** - * Base URL of the exchange we withdraw from. - */ - char *exchange_url; - - /** - * Timeout task. - */ - struct GNUNET_SCHEDULER_Task *tt; - - /** - * Head of DLL of exchange operations on planchets. - */ - struct PlanchetOperation *po_head; - - /** - * Tail of DLL of exchange operations on planchets. - */ - struct PlanchetOperation *po_tail; - - /** - * HTTP response to return (set on errors). - */ - struct MHD_Response *response; - - /** - * Find operation (while active), later NULL. - */ - struct TMH_EXCHANGES_KeysOperation *fo; - - /** - * Which reserve are we draining? - */ - struct TALER_ReservePrivateKeyP reserve_priv; - - /** - * Which reward is being picked up? - */ - struct TALER_RewardIdentifierP reward_id; - - /** - * What is the ID of the pickup operation? (Basically a - * hash over the key inputs). - */ - struct TALER_PickupIdentifierP pickup_id; - - /** - * Array of our planchets. - */ - struct TALER_PlanchetDetail *planchets; - - /** - * Length of the @e planchets array. - */ - unsigned int planchets_length; - - /** - * HTTP status to use (set on errors). - */ - unsigned int http_status; - - /** - * Total amount requested in the pick up operation. Computed by - * totaling up the amounts of all the @e planchets. - */ - struct TALER_Amount total_requested; - - /** - * True if @e total_requested has been initialized. - */ - bool tr_initialized; - - /** - * Should we generate a DB notification at the end for the pickup? Used to - * wake up long pollers upon reward pickup. Not done transactionally as there - * are potentially several coins individually added to the DB as - * transactions, and doing a notification per coin would be excessive. - * (And missing an event in the very rare case where our process fails - * hard between a DB operation and generating an HTTP reply is not a problem - * in this case.) However, if we in the future do group all DB transactions - * into one larger transaction, the notification should become part of it. - */ - bool do_notify; -}; - - -/** - * Head of DLL. - */ -static struct PickupContext *pc_head; - -/** - * Tail of DLL. - */ -static struct PickupContext *pc_tail; - - -/** - * Stop all ongoing operations associated with @a pc. - */ -static void -stop_operations (struct PickupContext *pc) -{ - struct PlanchetOperation *po; - - if (NULL != pc->tt) - { - GNUNET_SCHEDULER_cancel (pc->tt); - pc->tt = NULL; - } - if (NULL != pc->fo) - { - TMH_EXCHANGES_keys4exchange_cancel (pc->fo); - pc->fo = NULL; - } - while (NULL != (po = pc->po_head)) - { - if (NULL != po->fo) - { - TMH_EXCHANGES_keys4exchange_cancel (po->fo); - po->fo = NULL; - } - if (NULL != po->w2h) - { - TALER_EXCHANGE_batch_withdraw2_cancel (po->w2h); - po->w2h = NULL; - } - GNUNET_CONTAINER_DLL_remove (pc->po_head, - pc->po_tail, - po); - GNUNET_free (po); - } -} - - -/** - * Function called to clean up. - * - * @param cls a `struct PickupContext *` to clean up - */ -static void -pick_context_cleanup (void *cls) -{ - struct PickupContext *pc = cls; - - if (pc->do_notify) - { - struct TMH_RewardPickupEventP reward_eh = { - .header.size = htons (sizeof (reward_eh)), - .header.type = htons (TALER_DBEVENT_MERCHANT_REWARD_PICKUP), - .reward_id = pc->reward_id - }; - - GNUNET_CRYPTO_hash (pc->hc->instance->settings.id, - strlen (pc->hc->instance->settings.id), - &reward_eh.h_instance); - TMH_db->event_notify (TMH_db->cls, - &reward_eh.header, - NULL, - 0); - } - stop_operations (pc); /* should not be any... */ - for (unsigned int i = 0; i<pc->planchets_length; i++) - TALER_planchet_detail_free (&pc->planchets[i]); - GNUNET_array_grow (pc->planchets, - pc->planchets_length, - 0); - GNUNET_free (pc->exchange_url); - GNUNET_free (pc); -} - - -void -TMH_force_reward_pickup_resume () -{ - struct PickupContext *nxt; - - for (struct PickupContext *pc = pc_head; - NULL != pc; - pc = nxt) - { - nxt = pc->next; - stop_operations (pc); - GNUNET_CONTAINER_DLL_remove (pc_head, - pc_tail, - pc); - MHD_resume_connection (pc->connection); - } -} - - -/** - * Callbacks of this type are used to serve the result of submitting a - * withdraw request to a exchange without the (un)blinding factor. - * We persist the result in the database and, if we were the last - * planchet operation, resume HTTP processing. - * - * @param cls closure with a `struct PlanchetOperation *` - * @param w2r response data - */ -static void -withdraw_cb (void *cls, - const struct TALER_EXCHANGE_BatchWithdraw2Response *w2r) -{ - struct PlanchetOperation *po = cls; - const struct TALER_EXCHANGE_HttpResponse *hr = &w2r->hr; - struct PickupContext *pc = po->pc; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_CONTAINER_DLL_remove (pc->po_head, - pc->po_tail, - po); - TMH_db->preflight (TMH_db->cls); - if (MHD_HTTP_OK != hr->http_status) - { - GNUNET_free (po); - stop_operations (pc); - pc->http_status = MHD_HTTP_BAD_GATEWAY; - pc->response = - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec (TALER_EC_MERCHANT_REWARD_PICKUP_EXCHANGE_ERROR), - TMH_pack_exchange_reply (hr)); - GNUNET_CONTAINER_DLL_remove (pc_head, - pc_tail, - pc); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - GNUNET_assert (1 == w2r->details.ok.blind_sigs_length); - qs = TMH_db->insert_pickup_blind_signature (TMH_db->cls, - &pc->pickup_id, - po->offset, - &w2r->details.ok.blind_sigs[0]); - GNUNET_free (po); - if (qs < 0) - { - stop_operations (pc); - pc->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; - pc->response = TALER_MHD_make_error ( - TALER_EC_GENERIC_DB_STORE_FAILED, - "blind signature"); - GNUNET_CONTAINER_DLL_remove (pc_head, - pc_tail, - pc); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - pc->do_notify = true; - if (NULL != pc->po_head) - return; /* More pending */ - stop_operations (pc); /* stops timeout job */ - GNUNET_CONTAINER_DLL_remove (pc_head, - pc_tail, - pc); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ -} - - -/** - * Function called with the result of a #TMH_EXCHANGES_keys4exchange() - * operation as part of a withdraw objective. If the exchange is ready, - * withdraws the planchet from the exchange. - * - * @param cls closure, with our `struct PlanchetOperation *` - * @param keys keys for the exchange - * @param exchange representation of the exchange - */ -static void -do_withdraw (void *cls, - struct TALER_EXCHANGE_Keys *keys, - struct TMH_Exchange *exchange) -{ - struct PlanchetOperation *po = cls; - struct PickupContext *pc = po->pc; - - (void) exchange; - po->fo = NULL; - TMH_db->preflight (TMH_db->cls); - if (NULL == keys) - { - stop_operations (pc); - GNUNET_CONTAINER_DLL_remove (pc->po_head, - pc->po_tail, - po); - GNUNET_free (po); - pc->http_status = MHD_HTTP_GATEWAY_TIMEOUT; - pc->response = TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec ( - TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT)); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - /* FIXME: actually use *batch* withdraw instead of - doing this coin-by-coin non-sense */ - po->w2h = TALER_EXCHANGE_batch_withdraw2 (TMH_curl_ctx, - pc->exchange_url, - keys, - &pc->reserve_priv, - 1, - &po->pd, - &withdraw_cb, - po); -} - - -/** - * Withdraw @a planchet from @a exchange_url for @a pc operation at planchet - * @a offset. Sets up the respective operation and adds it @a pc's operation - * list. Once the operation is complete, the resulting blind signature is - * committed to the merchant's database. If all planchet operations are - * completed, the HTTP processing is resumed. - * - * @param[in,out] pc a pending pickup operation that includes @a planchet - * @param planchet details about the coin to pick up - * @param offset offset of @a planchet in the list, needed to process the reply - */ -static void -try_withdraw (struct PickupContext *pc, - const struct TALER_PlanchetDetail *planchet, - unsigned int offset) -{ - struct PlanchetOperation *po; - - TMH_db->preflight (TMH_db->cls); - po = GNUNET_new (struct PlanchetOperation); - po->pc = pc; - po->pd = *planchet; - po->offset = offset; - po->fo = TMH_EXCHANGES_keys4exchange (pc->exchange_url, - false, - &do_withdraw, - po); - GNUNET_assert (NULL != po->fo); - GNUNET_CONTAINER_DLL_insert (pc->po_head, - pc->po_tail, - po); -} - - -/** - * Handle timeout for pickup. - * - * @param cls a `struct PickupContext *` - */ -static void -do_timeout (void *cls) -{ - struct PickupContext *pc = cls; - - pc->tt = NULL; - stop_operations (pc); - pc->http_status = MHD_HTTP_GATEWAY_TIMEOUT; - pc->response = TALER_MHD_make_error ( - TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT, - NULL); - GNUNET_CONTAINER_DLL_remove (pc_head, - pc_tail, - pc); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ -} - - -/** - * Function called with the result of a #TMH_EXCHANGES_keys4exchange() - * operation as part of a withdraw objective. Here, we initialize - * the "total_requested" amount by adding up the cost of the planchets - * provided by the client. - * - * @param cls closure, with our `struct PickupContext *` - * @param keys the keys of the exchange - * @param exchange representation of the exchange - */ -static void -compute_total_requested (void *cls, - struct TALER_EXCHANGE_Keys *keys, - struct TMH_Exchange *exchange) -{ - struct PickupContext *pc = cls; - bool have_request = false; - - (void) exchange; - pc->fo = NULL; - stop_operations (pc); /* stops timeout job */ - if (NULL == keys) - { - pc->http_status = MHD_HTTP_GATEWAY_TIMEOUT; - pc->response = TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec ( - TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE)); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - for (unsigned int i = 0; i<pc->planchets_length; i++) - { - struct TALER_PlanchetDetail *pd = &pc->planchets[i]; - const struct TALER_EXCHANGE_DenomPublicKey *dpk; - - dpk = TALER_EXCHANGE_get_denomination_key_by_hash (keys, - &pd->denom_pub_hash); - if (NULL == dpk) - { - pc->http_status = MHD_HTTP_CONFLICT; - pc->response = - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec ( - TALER_EC_MERCHANT_REWARD_PICKUP_DENOMINATION_UNKNOWN)); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - if (have_request) - { - if (GNUNET_YES != - TALER_amount_cmp_currency (&pc->total_requested, - &dpk->value)) - { - pc->http_status = MHD_HTTP_BAD_REQUEST; - pc->response = - TALER_MHD_make_error (TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, - "Must not mix currencies when picking up rewards"); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - if (0 > - TALER_amount_add (&pc->total_requested, - &pc->total_requested, - &dpk->value)) - { - pc->http_status = MHD_HTTP_BAD_REQUEST; - pc->response = - TALER_MHD_make_error (TALER_EC_MERCHANT_REWARD_PICKUP_SUMMATION_FAILED, - "Could not add up values to compute pickup total"); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - } - else - { - pc->total_requested = dpk->value; - have_request = true; - } - } - if (! have_request) - { - pc->http_status = MHD_HTTP_BAD_REQUEST; - pc->response = - TALER_MHD_make_error (TALER_EC_MERCHANT_REWARD_PICKUP_SUMMATION_FAILED, - "Empty request array not allowed"); - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - return; - } - pc->tr_initialized = true; - MHD_resume_connection (pc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ -} - - -/** - * The reward lookup operation failed. Generate an error response based on the @a qs. - * - * @param connection connection to generate error for - * @param qs DB status to base error creation on - * @return MHD result code - */ -static MHD_RESULT -reply_lookup_reward_failed (struct MHD_Connection *connection, - enum GNUNET_DB_QueryStatus qs) -{ - unsigned int response_code; - enum TALER_ErrorCode ec; - - TMH_db->rollback (TMH_db->cls); - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - ec = TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN; - response_code = MHD_HTTP_NOT_FOUND; - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - ec = TALER_EC_GENERIC_DB_SOFT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - case GNUNET_DB_STATUS_HARD_ERROR: - ec = TALER_EC_GENERIC_DB_COMMIT_FAILED; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - default: - GNUNET_break (0); - ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - } - return TALER_MHD_reply_with_error (connection, - response_code, - ec, - NULL); -} - - -MHD_RESULT -TMH_post_rewards_ID_pickup (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct PickupContext *pc = hc->ctx; - char *next_url; - struct TALER_Amount total_authorized; - struct TALER_Amount total_picked_up; - struct TALER_Amount total_remaining; - struct GNUNET_TIME_Timestamp expiration; - enum GNUNET_DB_QueryStatus qs; - unsigned int num_retries; - - if (NULL == pc) - { - const json_t *planchets; - json_t *planchet; - size_t index; - - pc = GNUNET_new (struct PickupContext); - hc->ctx = pc; - hc->cc = &pick_context_cleanup; - pc->hc = hc; - GNUNET_assert (NULL != hc->infix); - if (GNUNET_OK != - GNUNET_CRYPTO_hash_from_string (hc->infix, - &pc->reward_id.hash)) - { - /* reward_id has wrong encoding */ - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - hc->infix); - } - - { - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("planchets", - &planchets), - GNUNET_JSON_spec_end () - }; - { - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - hc->request_body, - spec); - if (GNUNET_OK != res) - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - } - GNUNET_array_grow (pc->planchets, - pc->planchets_length, - json_array_size (planchets)); - json_array_foreach (planchets, index, planchet) { - struct TALER_PlanchetDetail *pd = &pc->planchets[index]; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", - &pd->denom_pub_hash), - TALER_JSON_spec_blinded_planchet ("coin_ev", - &pd->blinded_planchet), - GNUNET_JSON_spec_end () - }; - { - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - planchet, - spec); - if (GNUNET_OK != res) - { - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - } - } - { - struct GNUNET_HashContext *hc; - - hc = GNUNET_CRYPTO_hash_context_start (); - GNUNET_CRYPTO_hash_context_read (hc, - &pc->reward_id, - sizeof (pc->reward_id)); - for (unsigned int i = 0; i<pc->planchets_length; i++) - { - struct TALER_PlanchetDetail *pd = &pc->planchets[i]; - - GNUNET_CRYPTO_hash_context_read (hc, - &pd->denom_pub_hash, - sizeof (pd->denom_pub_hash)); - TALER_blinded_planchet_hash_ (&pd->blinded_planchet, - hc); - } - GNUNET_CRYPTO_hash_context_finish (hc, - &pc->pickup_id.hash); - } - } - - if (NULL != pc->response) - { - MHD_RESULT ret; - - ret = MHD_queue_response (connection, - pc->http_status, - pc->response); - pc->response = NULL; - return ret; - } - - if (! pc->tr_initialized) - { - char *next_url; - - qs = TMH_db->lookup_reward (TMH_db->cls, - hc->instance->settings.id, - &pc->reward_id, - &total_authorized, - &total_picked_up, - &expiration, - &pc->exchange_url, - &next_url, - &pc->reserve_priv); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return reply_lookup_reward_failed (connection, - qs); - GNUNET_free (next_url); - MHD_suspend_connection (connection); - pc->connection = connection; - pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT, - &do_timeout, - pc); - pc->fo = TMH_EXCHANGES_keys4exchange (pc->exchange_url, - false, - &compute_total_requested, - pc); - return MHD_YES; - } - - - TMH_db->preflight (TMH_db->cls); - num_retries = 0; -RETRY: - num_retries++; - if (num_retries > MAX_RETRIES) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_SOFT_FAILURE, - NULL); - } - if (GNUNET_OK != - TMH_db->start (TMH_db->cls, - "pickup reward")) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_START_FAILED, - NULL); - } - { - struct TALER_BlindedDenominationSignature sigs[ - GNUNET_NZL (pc->planchets_length)]; - - memset (sigs, - 0, - sizeof (sigs)); - GNUNET_free (pc->exchange_url); - qs = TMH_db->lookup_pickup (TMH_db->cls, - hc->instance->settings.id, - &pc->reward_id, - &pc->pickup_id, - &pc->exchange_url, - &pc->reserve_priv, - pc->planchets_length, - sigs); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Lookup pickup `%s' resulted in %d\n", - GNUNET_h2s (&pc->pickup_id.hash), - qs); - if (qs > GNUNET_DB_STATUS_SUCCESS_ONE_RESULT) - qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - bool rollback = false; - - for (unsigned int i = 0; i< pc->planchets_length; i++) - { - if (NULL != sigs[i].blinded_sig) - continue; - if (! rollback) - { - TMH_db->rollback (TMH_db->cls); - MHD_suspend_connection (connection); - GNUNET_CONTAINER_DLL_insert (pc_head, - pc_tail, - pc); - pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT, - &do_timeout, - pc); - rollback = true; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Lookup pickup `%s' initiated withdraw #%u\n", - GNUNET_h2s (&pc->pickup_id.hash), - i); - try_withdraw (pc, - &pc->planchets[i], - i); - } - if (rollback) - return MHD_YES; - /* we got _all_ signatures, can continue! */ - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) - { - unsigned int response_code; - enum TALER_ErrorCode ec; - - TMH_db->rollback (TMH_db->cls); - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - { - json_t *blind_sigs; - - blind_sigs = json_array (); - GNUNET_assert (NULL != blind_sigs); - for (unsigned int i = 0; i<pc->planchets_length; i++) - { - GNUNET_assert (0 == - json_array_append_new ( - blind_sigs, - GNUNET_JSON_PACK ( - TALER_JSON_pack_blinded_denom_sig ("blind_sig", - &sigs[i])))); - TALER_blinded_denom_sig_free (&sigs[i]); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ("blind_sigs", - blind_sigs)); - } - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - goto RETRY; - case GNUNET_DB_STATUS_HARD_ERROR: - ec = TALER_EC_GENERIC_DB_FETCH_FAILED; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - default: - GNUNET_break (0); - ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - } - return TALER_MHD_reply_with_error (connection, - response_code, - ec, - NULL); - } - } - GNUNET_free (pc->exchange_url); - qs = TMH_db->lookup_reward (TMH_db->cls, - hc->instance->settings.id, - &pc->reward_id, - &total_authorized, - &total_picked_up, - &expiration, - &pc->exchange_url, - &next_url, - &pc->reserve_priv); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - { - TMH_db->rollback (TMH_db->cls); - goto RETRY; - } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - { - TMH_db->rollback (TMH_db->cls); - return reply_lookup_reward_failed (connection, - qs); - } - GNUNET_free (next_url); - if (GNUNET_TIME_absolute_is_past (expiration.abs_time)) - { - TMH_db->rollback (TMH_db->cls); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_GONE, - TALER_EC_MERCHANT_REWARD_PICKUP_HAS_EXPIRED, - hc->infix); - } - if (GNUNET_OK != - TALER_amount_cmp_currency (&total_authorized, - &total_picked_up)) - { - /* This could theoretically happen if the exchange changed - its currency between us approving the reward - and the client then picks it up with the new - exchange currency. And of course the backend - would have had to get the new /keys of the - exchange already as well. Very theoretical case. */ - GNUNET_break_op (0); - TMH_db->rollback (TMH_db->cls); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, - "picked up amount does not use same currency as authorized amount"); - } - if (0 > - TALER_amount_subtract (&total_remaining, - &total_authorized, - &total_picked_up)) - { - GNUNET_break_op (0); - TMH_db->rollback (TMH_db->cls); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "picked up amount exceeds authorized amount"); - } - - if (0 > - TALER_amount_cmp (&total_remaining, - &pc->total_requested)) - { - /* total_remaining < pc->total_requested */ - GNUNET_break_op (0); - TMH_db->rollback (TMH_db->cls); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_MERCHANT_REWARD_PICKUP_AMOUNT_EXCEEDS_REWARD_REMAINING, - hc->infix); - } - - GNUNET_assert (0 < - TALER_amount_add (&total_picked_up, - &total_picked_up, - &pc->total_requested)); - qs = TMH_db->insert_pickup (TMH_db->cls, - hc->instance->settings.id, - &pc->reward_id, - &total_picked_up, - &pc->pickup_id, - &pc->total_requested); - if (qs < 0) - { - TMH_db->rollback (TMH_db->cls); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - goto RETRY; - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "pickup"); - } - qs = TMH_db->commit (TMH_db->cls); - if (qs < 0) - { - TMH_db->rollback (TMH_db->cls); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - goto RETRY; - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_COMMIT_FAILED, - NULL); - } - MHD_suspend_connection (connection); - GNUNET_CONTAINER_DLL_insert (pc_head, - pc_tail, - pc); - pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT, - &do_timeout, - pc); - for (unsigned int i = 0; i<pc->planchets_length; i++) - { - try_withdraw (pc, - &pc->planchets[i], - i); - } - return MHD_YES; -} diff --git a/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.h b/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.h deleted file mode 100644 index ea929e51..00000000 --- a/src/backend/taler-merchant-httpd_post-rewards-ID-pickup.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of TALER - (C) 2017 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_post-rewards-ID-pickup.h - * @brief headers for POST /rewards/ID/pickup handler - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_POST_REWARDS_ID_PICKUP_H -#define TALER_MERCHANT_HTTPD_POST_REWARDS_ID_PICKUP_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - - -/** - * We are shutting down, force resuming all suspended pickup operations. - */ -void -TMH_force_reward_pickup_resume (void); - - -/** - * Manages a POST /rewards/$ID/pickup call, checking that the reward is authorized, - * and if so, returning the blind signatures. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_post_rewards_ID_pickup (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - - -#endif diff --git a/src/backend/taler-merchant-httpd_private-delete-reserves-ID.c b/src/backend/taler-merchant-httpd_private-delete-reserves-ID.c deleted file mode 100644 index b6daf9e6..00000000 --- a/src/backend/taler-merchant-httpd_private-delete-reserves-ID.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - This file is part of TALER - (C) 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-delete-reserves-ID.c - * @brief implement DELETE /reserves/$ID - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler-merchant-httpd_private-delete-reserves-ID.h" -#include <taler/taler_json_lib.h> - - -/** - * Handle a DELETE "/reserves/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_delete_reserves_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TMH_MerchantInstance *mi = hc->instance; - enum GNUNET_DB_QueryStatus qs; - struct TALER_ReservePublicKeyP reserve_pub; - const char *purge; - - (void) rh; - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (hc->infix, - strlen (hc->infix), - &reserve_pub, - sizeof (reserve_pub))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, - hc->infix); - } - purge = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "purge"); - GNUNET_assert (NULL != mi); - if ( (NULL != purge) && - (0 == strcasecmp (purge, - "yes")) ) - qs = TMH_db->purge_reserve (TMH_db->cls, - mi->settings.id, - &reserve_pub); - else - qs = TMH_db->delete_reserve (TMH_db->cls, - mi->settings.id, - &reserve_pub); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - NULL); - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_SOFT_FAILURE, - "Serialization error for single SQL statement"); - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_PRIVATE_DELETE_RESERVES_NO_SUCH_RESERVE, - hc->infix); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - return TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); - } - GNUNET_assert (0); - return MHD_NO; -} - - -/* end of taler-merchant-httpd_private-delete-reserves-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-delete-reserves-ID.h b/src/backend/taler-merchant-httpd_private-delete-reserves-ID.h deleted file mode 100644 index 9180767f..00000000 --- a/src/backend/taler-merchant-httpd_private-delete-reserves-ID.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2019, 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-delete-reserves-ID.h - * @brief implement DELETE /reserves/$ID/ - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_RESERVES_ID_H -#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_RESERVES_ID_H - -#include "taler-merchant-httpd.h" - - -/** - * Handle a DELETE "/reserves/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_delete_reserves_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -/* end of taler-merchant-httpd_private-delete-reserves-ID.h */ -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c deleted file mode 100644 index a9855379..00000000 --- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - This file is part of TALER - (C) 2018, 2020, 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-reserves-ID.c - * @brief implement GET /reserves/$RESERVE_PUB endpoint - * @author Christian Grothoff - */ -#include "platform.h" -#include <jansson.h> -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_helper.h" -#include "taler-merchant-httpd_private-get-reserves-ID.h" - - -/** - * Closure for handle_reserve_details(). - */ -struct GetReserveContext -{ - /** - * Connection we are handling. - */ - struct MHD_Connection *connection; - - /** - * Value to return from the callback. - */ - MHD_RESULT res; - - /** - * Should we return details about rewards? - */ - bool rewards; -}; - - -/** - * Callback with reserve details. - * - * @param cls closure with a `struct GetReserveContext` - * @param creation_time time when the reserve was setup - * @param expiration_time time when the reserve will be closed by the exchange - * @param merchant_initial_amount initial amount that the merchant claims to have filled the - * reserve with - * @param exchange_initial_amount initial amount that the exchange claims to have received - * @param picked_up_amount total of rewards that were picked up from this reserve - * @param committed_amount total of rewards that the merchant committed to, but that were not - * picked up yet - * @param active true if the reserve is still active (we have the private key) - * @param master_pub master public key of the exchange - * @param exchange_url URL of the exchange, NULL if not active - * @param rewards_length length of the @a rewards array - * @param rewards information about the rewards created by this reserve - */ -static void -handle_reserve_details ( - void *cls, - struct GNUNET_TIME_Timestamp creation_time, - struct GNUNET_TIME_Timestamp expiration_time, - const struct TALER_Amount *merchant_initial_amount, - const struct TALER_Amount *exchange_initial_amount, - const struct TALER_Amount *picked_up_amount, - const struct TALER_Amount *committed_amount, - bool active, - const struct TALER_MasterPublicKeyP *master_pub, - const char *exchange_url, - unsigned int rewards_length, - const struct TALER_MERCHANTDB_RewardDetails *rewards) -{ - struct GetReserveContext *ctx = cls; - json_t *rewards_json; - json_t *accounts; - - if (NULL != rewards) - { - rewards_json = json_array (); - GNUNET_assert (NULL != rewards_json); - for (unsigned int i = 0; i<rewards_length; i++) - { - GNUNET_assert (0 == - json_array_append_new ( - rewards_json, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("reward_id", - &rewards[i].reward_id), - TALER_JSON_pack_amount ("total_amount", - &rewards[i].total_amount), - GNUNET_JSON_pack_string ("reason", - rewards[i].reason)))); - } - } - else - { - rewards_json = NULL; - } - accounts = TMH_exchange_accounts_by_method (master_pub, - NULL); - ctx->res = TALER_MHD_REPLY_JSON_PACK ( - ctx->connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_timestamp ("creation_time", - creation_time), - GNUNET_JSON_pack_timestamp ("expiration_time", - expiration_time), - TALER_JSON_pack_amount ("merchant_initial_amount", - merchant_initial_amount), - TALER_JSON_pack_amount ("exchange_initial_amount", - exchange_initial_amount), - TALER_JSON_pack_amount ("pickup_amount", - picked_up_amount), - TALER_JSON_pack_amount ("committed_amount", - committed_amount), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_array_steal ("rewards", - rewards_json)), - GNUNET_JSON_pack_bool ("active", - active), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("exchange_url", - exchange_url)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_array_steal ("accounts", - accounts))); -} - - -/** - * Manages a GET /reserves/$RESERVE_PUB call. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_reserves_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TALER_ReservePublicKeyP reserve_pub; - bool rewards; - - (void) rh; - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (hc->infix, - strlen (hc->infix), - &reserve_pub, - sizeof (reserve_pub))) - { - /* reward_id has wrong encoding */ - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - hc->infix); - } - { - const char *tstr; - - tstr = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "rewards"); - rewards = (NULL != tstr) - ? 0 == strcasecmp (tstr, "yes") - : false; - } - { - struct GetReserveContext ctx = { - .connection = connection, - .rewards = rewards - }; - enum GNUNET_DB_QueryStatus qs; - - TMH_db->preflight (TMH_db->cls); - qs = TMH_db->lookup_reserve (TMH_db->cls, - hc->instance->settings.id, - &reserve_pub, - rewards, - &handle_reserve_details, - &ctx); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - { - unsigned int response_code; - enum TALER_ErrorCode ec; - - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - ec = TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN; - response_code = MHD_HTTP_NOT_FOUND; - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - ec = TALER_EC_GENERIC_DB_SOFT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - case GNUNET_DB_STATUS_HARD_ERROR: - ec = TALER_EC_GENERIC_DB_FETCH_FAILED; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - default: - GNUNET_break (0); - ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - } - return TALER_MHD_reply_with_error (connection, - response_code, - ec, - hc->infix); - } - return ctx.res; - } -} - - -/* end of taler-merchant-httpd_private-get-reserves-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.h b/src/backend/taler-merchant-httpd_private-get-reserves-ID.h deleted file mode 100644 index 83ea48ee..00000000 --- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of TALER - (C) 2017 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-reserves-ID.h - * @brief headers for /reward-query handler - * @author Florian Dold - */ -#ifndef TALER_MERCHANT_HTTPD_GET_RESERVES_ID_H -#define TALER_MERCHANT_HTTPD_GET_RESERVES_ID_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - -/** - * Manages a GET /reserves/$RESERVE_PUB call. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_reserves_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-reserves.c b/src/backend/taler-merchant-httpd_private-get-reserves.c deleted file mode 100644 index 6621ffb4..00000000 --- a/src/backend/taler-merchant-httpd_private-get-reserves.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - This file is part of TALER - (C) 2019-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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-reserves.c - * @brief implement GET /reserves - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_json_lib.h> -#include "taler-merchant-httpd_private-get-reserves.h" - - -/** - * Add reserve details to our JSON array. - * - * @param cls a `json_t *` JSON array to build - * @param reserve_pub public key of the reserve - * @param creation_time time when the reserve was setup - * @param expiration_time time when the reserve will be closed by the exchange - * @param merchant_initial_amount initial amount that the merchant claims to have filled the - * reserve with - * @param exchange_initial_amount initial amount that the exchange claims to have received - * @param pickup_amount total of tips that were picked up from this reserve - * @param committed_amount total of tips that the merchant committed to, but that were not - * picked up yet - * @param active true if the reserve is still active (we have the private key) - */ -static void -add_reserve (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Timestamp creation_time, - struct GNUNET_TIME_Timestamp expiration_time, - const struct TALER_Amount *merchant_initial_amount, - const struct TALER_Amount *exchange_initial_amount, - const struct TALER_Amount *pickup_amount, - const struct TALER_Amount *committed_amount, - bool active) -{ - json_t *pa = cls; - - GNUNET_assert (0 == - json_array_append_new ( - pa, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("reserve_pub", - reserve_pub), - GNUNET_JSON_pack_timestamp ("creation_time", - creation_time), - GNUNET_JSON_pack_timestamp ("expiration_time", - expiration_time), - TALER_JSON_pack_amount ("merchant_initial_amount", - merchant_initial_amount), - TALER_JSON_pack_amount ("exchange_initial_amount", - exchange_initial_amount), - TALER_JSON_pack_amount ("pickup_amount", - pickup_amount), - TALER_JSON_pack_amount ("committed_amount", - committed_amount), - GNUNET_JSON_pack_bool ("active", - active)))); -} - - -/** - * Handle a GET "/reserves" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_reserves (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - json_t *ra; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Timestamp created_after - = GNUNET_TIME_UNIT_ZERO_TS; - enum TALER_EXCHANGE_YesNoAll active; - enum TALER_EXCHANGE_YesNoAll failures; - - (void) rh; - if (! (TALER_arg_to_yna (connection, - "active", - TALER_EXCHANGE_YNA_ALL, - &active)) ) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "active"); - } - - if (! (TALER_arg_to_yna (connection, - "failures", - TALER_EXCHANGE_YNA_ALL, - &failures)) ) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "failures"); - } - - ra = json_array (); - GNUNET_assert (NULL != ra); - qs = TMH_db->lookup_reserves (TMH_db->cls, - hc->instance->settings.id, - created_after, - active, - failures, - &add_reserve, - ra); - if (0 > qs) - { - GNUNET_break (0); - json_decref (ra); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "reserves"); - } - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ("reserves", - ra)); -} - - -/* end of taler-merchant-httpd_private-get-reserves.c */ diff --git a/src/backend/taler-merchant-httpd_private-get-reserves.h b/src/backend/taler-merchant-httpd_private-get-reserves.h deleted file mode 100644 index 705f0761..00000000 --- a/src/backend/taler-merchant-httpd_private-get-reserves.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2019, 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-reserves.h - * @brief implement GET /reserves - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_RESERVES_H -#define TALER_MERCHANT_HTTPD_PRIVATE_GET_RESERVES_H - -#include "taler-merchant-httpd.h" - - -/** - * Handle a GET "/reserves" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_reserves (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -/* end of taler-merchant-httpd_private-get-reserves.h */ -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-rewards-ID.c b/src/backend/taler-merchant-httpd_private-get-rewards-ID.c deleted file mode 100644 index a20be319..00000000 --- a/src/backend/taler-merchant-httpd_private-get-rewards-ID.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - This file is part of TALER - (C) 2017-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_get-rewards-ID.c - * @brief implementation of a GET /rewards/ID handler - * @author Christian Grothoff - */ -#include "platform.h" -#include <microhttpd.h> -#include <jansson.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_json_lib.h> -#include <taler/taler_signatures.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_exchanges.h" - - -/** - * Information we keep per /kyc request. - */ -struct RewardContext -{ - /** - * Stored in a DLL. - */ - struct RewardContext *next; - - /** - * Stored in a DLL. - */ - struct RewardContext *prev; - - /** - * Connection we are handling. - */ - struct MHD_Connection *connection; - - /** - * Our handler context. - */ - struct TMH_HandlerContext *hc; - - /** - * Database event we are waiting on to be resuming. - */ - struct GNUNET_DB_EventHandler *eh; - - /** - * Response to return, NULL if we don't have one yet. - */ - struct MHD_Response *response; - - /** - * When does this request time out? - */ - struct GNUNET_TIME_Absolute timeout; - - /** - * ID of the reward being queried. - */ - struct TALER_RewardIdentifierP reward_id; - - /** - * Minimum reward amount picked up we should return to the - * client. - */ - struct TALER_Amount min_amount; - - /** - * #GNUNET_NO if the @e connection was not suspended, - * #GNUNET_YES if the @e connection was suspended, - * #GNUNET_SYSERR if @e connection was resumed to as - * part of #MH_force_pc_resume during shutdown. - */ - enum GNUNET_GenericReturnValue suspended; - - /** - * Is the "pickups" argument set to "yes"? - */ - bool fpu; - - /** - * True if @e min_amount was provided. - */ - bool have_min_amount; -}; - - -/** - * Head of DLL. - */ -static struct RewardContext *tc_head; - -/** - * Tail of DLL. - */ -static struct RewardContext *tc_tail; - - -void -TMH_force_reward_resume () -{ - for (struct RewardContext *tc = tc_head; - NULL != tc; - tc = tc->next) - { - if (GNUNET_YES == tc->suspended) - { - tc->suspended = GNUNET_SYSERR; - MHD_resume_connection (tc->connection); - } - } -} - - -/** - * Custom cleanup routine for a `struct RewardContext`. - * - * @param cls the `struct RewardContext` to clean up. - */ -static void -reward_context_cleanup (void *cls) -{ - struct RewardContext *tc = cls; - - if (NULL != tc->response) - { - MHD_destroy_response (tc->response); - tc->response = NULL; - } - if (NULL != tc->eh) - { - TMH_db->event_listen_cancel (tc->eh); - tc->eh = NULL; - } - GNUNET_CONTAINER_DLL_remove (tc_head, - tc_tail, - tc); - GNUNET_free (tc); -} - - -/** - * We have received a trigger from the database - * that we should (possibly) resume the request. - * - * @param cls a `struct RewardContext` to resume - * @param extra usually NULL - * @param extra_size number of bytes in @a extra - */ -static void -resume_by_event (void *cls, - const void *extra, - size_t extra_size) -{ - struct RewardContext *tc = cls; - - (void) extra; - (void) extra_size; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Resuming request %p by trigger\n", - tc); - if (GNUNET_NO == tc->suspended) - return; /* duplicate event is possible */ - tc->suspended = GNUNET_NO; - GNUNET_CONTAINER_DLL_remove (tc_head, - tc_tail, - tc); - MHD_resume_connection (tc->connection); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ -} - - -MHD_RESULT -TMH_private_get_rewards_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct RewardContext *tc = hc->ctx; - struct TALER_Amount total_authorized; - struct TALER_Amount total_picked_up; - char *reason; - struct GNUNET_TIME_Timestamp expiration; - struct TALER_ReservePublicKeyP reserve_pub; - unsigned int pickups_length = 0; - struct TALER_MERCHANTDB_PickupDetails *pickups = NULL; - enum GNUNET_DB_QueryStatus qs; - json_t *pickups_json = NULL; - - (void) rh; - if (NULL == tc) - { - tc = GNUNET_new (struct RewardContext); - hc->ctx = tc; - hc->cc = &reward_context_cleanup; - GNUNET_CONTAINER_DLL_insert (tc_head, - tc_tail, - tc); - tc->connection = connection; - tc->hc = hc; - GNUNET_assert (NULL != hc->infix); - if (GNUNET_OK != - GNUNET_CRYPTO_hash_from_string (hc->infix, - &tc->reward_id.hash)) - { - /* reward_id has wrong encoding */ - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - hc->infix); - } - { - const char *pstr; - - pstr = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "pickups"); - tc->fpu = (NULL != pstr) - ? 0 == strcasecmp (pstr, "yes") - : false; - } - { - const char *min_amount; - - min_amount = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "min_amount"); - if (NULL != min_amount) - { - if (GNUNET_OK != - TALER_string_to_amount (min_amount, - &tc->min_amount)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "min_amount"); - } - tc->have_min_amount = true; - } - } - TALER_MHD_parse_request_timeout (connection, - &tc->timeout); - if (! GNUNET_TIME_absolute_is_future (tc->timeout)) - { - struct TMH_RewardPickupEventP reward_eh = { - .header.size = htons (sizeof (reward_eh)), - .header.type = htons (TALER_DBEVENT_MERCHANT_REWARD_PICKUP), - .reward_id = tc->reward_id - }; - - GNUNET_CRYPTO_hash (hc->instance->settings.id, - strlen (hc->instance->settings.id), - &reward_eh.h_instance); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Subscribing to payment triggers for %p\n", - tc); - tc->eh = TMH_db->event_listen ( - TMH_db->cls, - &reward_eh.header, - GNUNET_TIME_absolute_get_remaining (tc->timeout), - &resume_by_event, - tc); - } - } - - GNUNET_assert (GNUNET_YES != tc->suspended); - TMH_db->preflight (TMH_db->cls); - qs = TMH_db->lookup_reward_details (TMH_db->cls, - hc->instance->settings.id, - &tc->reward_id, - tc->fpu, - &total_authorized, - &total_picked_up, - &reason, - &expiration, - &reserve_pub, - &pickups_length, - &pickups); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - { - unsigned int response_code; - enum TALER_ErrorCode ec; - - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - ec = TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN; - response_code = MHD_HTTP_NOT_FOUND; - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - ec = TALER_EC_GENERIC_DB_SOFT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - case GNUNET_DB_STATUS_HARD_ERROR: - ec = TALER_EC_GENERIC_DB_COMMIT_FAILED; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - default: - GNUNET_break (0); - ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - } - return TALER_MHD_reply_with_error (connection, - response_code, - ec, - NULL); - } - /* do not allow timeout above reward expiration */ - tc->timeout = GNUNET_TIME_absolute_min (tc->timeout, - expiration.abs_time); - if ( (NULL != tc->eh) && - (GNUNET_TIME_absolute_is_future (tc->timeout)) && - (tc->have_min_amount) && - (GNUNET_YES == - TALER_amount_cmp_currency (&tc->min_amount, - &total_picked_up)) && - (1 == TALER_amount_cmp (&tc->min_amount, - &total_picked_up)) ) - { - MHD_suspend_connection (connection); - tc->suspended = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suspending REWARD request handling as pickup is below threshold requested by client\n"); - GNUNET_array_grow (pickups, - pickups_length, - 0); - GNUNET_free (reason); - return MHD_YES; - } - if (tc->fpu) - { - pickups_json = json_array (); - GNUNET_assert (NULL != pickups_json); - for (unsigned int i = 0; i<pickups_length; i++) - { - GNUNET_assert (0 == - json_array_append_new ( - pickups_json, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("pickup_id", - &pickups[i].pickup_id), - GNUNET_JSON_pack_uint64 ("num_planchets", - pickups[i].num_planchets), - TALER_JSON_pack_amount ("requested_amount", - &pickups[i].requested_amount)))); - } - } - GNUNET_array_grow (pickups, - pickups_length, - 0); - { - MHD_RESULT ret; - - ret = TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - TALER_JSON_pack_amount ("total_authorized", - &total_authorized), - TALER_JSON_pack_amount ("total_picked_up", - &total_picked_up), - GNUNET_JSON_pack_string ("reason", - reason), - GNUNET_JSON_pack_timestamp ("expiration", - expiration), - GNUNET_JSON_pack_data_auto ("reserve_pub", - &reserve_pub), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_array_steal ("pickups", - pickups_json))); - GNUNET_free (reason); - return ret; - } -} diff --git a/src/backend/taler-merchant-httpd_private-get-rewards-ID.h b/src/backend/taler-merchant-httpd_private-get-rewards-ID.h deleted file mode 100644 index fc9cc9ae..00000000 --- a/src/backend/taler-merchant-httpd_private-get-rewards-ID.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of TALER - (C) 2017, 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_get-rewards-ID.h - * @brief headers for GET /rewards/ID handler - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_REWARDS_ID_H -#define TALER_MERCHANT_HTTPD_PRIVATE_GET_REWARDS_ID_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - - -/** - * Force wake-up of all suspended rewardping long-pollers. - */ -void -TMH_force_reward_resume (void); - - -/** - * Manages a GET /rewards/$ID call, returning the status of the reward. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_rewards_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - - -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-rewards.c b/src/backend/taler-merchant-httpd_private-get-rewards.c deleted file mode 100644 index 2ced8316..00000000 --- a/src/backend/taler-merchant-httpd_private-get-rewards.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - This file is part of TALER - (C) 2020-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-rewards.c - * @brief implementation of a GET /private/rewards handler - * @author Jonathan Buchanan - */ -#include "platform.h" -#include "taler-merchant-httpd_private-get-rewards.h" -#include <taler/taler_json_lib.h> - -/** - * Add reward details to our JSON array. - * - * @param[in,out] cls a `json_t *` JSON array to build - * @param row_id row number of the reward - * @param reward_id ID of the reward - * @param amount the amount of the reward - */ -static void -add_reward (void *cls, - uint64_t row_id, - struct TALER_RewardIdentifierP reward_id, - struct TALER_Amount amount) -{ - json_t *pa = cls; - - GNUNET_assert (0 == - json_array_append_new ( - pa, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_uint64 ("row_id", - row_id), - GNUNET_JSON_pack_data_auto ("reward_id", - &reward_id), - TALER_JSON_pack_amount ("reward_amount", - &amount)))); -} - - -MHD_RESULT -TMH_private_get_rewards (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - json_t *pa; - enum GNUNET_DB_QueryStatus qs; - enum TALER_EXCHANGE_YesNoAll expired; - uint64_t offset; - int64_t limit; - - (void) rh; - if (! (TALER_arg_to_yna (connection, - "expired", - TALER_EXCHANGE_YNA_NO, - &expired)) ) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "expired"); - { - const char *limit_str; - - limit_str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "limit"); - if (NULL == limit_str) - { - limit = -20; - } - else - { - char dummy[2]; - long long ll; - - if (1 != - sscanf (limit_str, - "%lld%1s", - &ll, - dummy)) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "limit"); - limit = (uint64_t) ll; - } - } - { - const char *offset_str; - - offset_str = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "offset"); - if (NULL == offset_str) - { - if (limit > 0) - offset = 0; - else - offset = INT64_MAX; - } - else - { - char dummy[2]; - unsigned long long ull; - - if (1 != - sscanf (offset_str, - "%llu%1s", - &ull, - dummy)) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "offset"); - offset = (uint64_t) ull; - } - } - - pa = json_array (); - GNUNET_assert (NULL != pa); - qs = TMH_db->lookup_rewards (TMH_db->cls, - hc->instance->settings.id, - expired, - limit, - offset, - &add_reward, - pa); - - if (0 > qs) - { - GNUNET_break (0); - json_decref (pa); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "rewards"); - } - - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_array_steal ("rewards", - pa)); -} diff --git a/src/backend/taler-merchant-httpd_private-get-rewards.h b/src/backend/taler-merchant-httpd_private-get-rewards.h deleted file mode 100644 index 67b3bc52..00000000 --- a/src/backend/taler-merchant-httpd_private-get-rewards.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-rewards.h - * @brief headers for GET /private/rewards handler - * @author Jonathan Buchanan - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_REWARDS_H -#define TALER_MERCHANT_HTTPD_PRIVATE_GET_REWARDS_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - - -/** - * Manages a GET /private/rewards call. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_rewards (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - - -#endif diff --git a/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c b/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c deleted file mode 100644 index 0d102a2b..00000000 --- a/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - This file is part of TALER - (C) 2014-2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c - * @brief implement API for authorizing rewards to be paid to visitors - * @author Christian Grothoff - */ -#include "platform.h" -#include <jansson.h> -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_get-rewards-ID.h" -#include "taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h" - - -/** - * Handle a "reward-authorize" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @param reserve_pub reserve to use, or NULL for "any" - * @return MHD result code - */ -static MHD_RESULT -authorize_reward (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc, - const struct TALER_ReservePublicKeyP *reserve_pub) -{ - enum TALER_ErrorCode ec; - struct GNUNET_TIME_Timestamp expiration; - struct TALER_RewardIdentifierP reward_id; - const char *justification; - const char *next_url; - struct TALER_Amount amount; - { - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("amount", - &amount), - GNUNET_JSON_spec_string ("justification", - &justification), - GNUNET_JSON_spec_string ("next_url", - &next_url), - GNUNET_JSON_spec_end () - }; - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - hc->request_body, - spec); - if (GNUNET_YES != res) - { - GNUNET_break_op (0); - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - } - TMH_db->preflight (TMH_db->cls); - ec = TMH_db->authorize_reward (TMH_db->cls, - hc->instance->settings.id, - reserve_pub, - &amount, - justification, - next_url, - &reward_id, - &expiration); - /* handle errors */ - if (TALER_EC_NONE != ec) - { - unsigned int http_status; - - switch (ec) - { - case TALER_EC_MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_INSUFFICIENT_FUNDS: - http_status = MHD_HTTP_PRECONDITION_FAILED; - break; - case TALER_EC_MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_EXPIRED: - http_status = MHD_HTTP_GONE; - break; - case TALER_EC_MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_UNKNOWN: - http_status = MHD_HTTP_SERVICE_UNAVAILABLE; - break; - case TALER_EC_MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_NOT_FOUND: - http_status = MHD_HTTP_NOT_FOUND; - break; - default: - http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; - break; - } - - return TALER_MHD_reply_with_error (connection, - http_status, - ec, - NULL); - } - - /* generate success response */ - { - char *taler_reward_uri; - char *reward_status_url; - struct GNUNET_CRYPTO_HashAsciiEncoded hash_enc; - MHD_RESULT res; - - GNUNET_CRYPTO_hash_to_enc (&reward_id.hash, - &hash_enc); - taler_reward_uri = TMH_make_taler_reward_uri (connection, - &reward_id, - hc->instance->settings.id); - if (NULL == taler_reward_uri) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MISSING, - "host"); - } - reward_status_url = TMH_make_reward_status_url (connection, - &reward_id, - hc->instance->settings.id); - GNUNET_assert (NULL != reward_status_url); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero (expiration.abs_time)); - res = TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_string ("reward_id", - (const char *) hash_enc.encoding), - GNUNET_JSON_pack_string ("taler_reward_uri", - taler_reward_uri), - GNUNET_JSON_pack_string ("reward_status_url", - reward_status_url), - GNUNET_JSON_pack_timestamp ("reward_expiration", - expiration)); - GNUNET_free (taler_reward_uri); - GNUNET_free (reward_status_url); - return res; - } -} - - -MHD_RESULT -TMH_private_post_reserves_ID_authorize_reward (const struct - TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TALER_ReservePublicKeyP reserve_pub; - - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (hc->infix, - strlen (hc->infix), - &reserve_pub, - sizeof (reserve_pub))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, - hc->infix); - } - return authorize_reward (rh, - connection, - hc, - &reserve_pub); -} - - -MHD_RESULT -TMH_private_post_rewards (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - return authorize_reward (rh, - connection, - hc, - NULL); -} - - -/* end of taler-merchant-httpd_private-post-reserves-ID-authorize-reward.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h b/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h deleted file mode 100644 index 12c94b1c..00000000 --- a/src/backend/taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of TALER - (C) 2017, 2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h - * @brief headers for /reserves/ID/reward-authorize - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_RESERVES_ID_AUTHORIZE_REWARD_H -#define TALER_MERCHANT_HTTPD_PRIVATE_POST_RESERVES_ID_AUTHORIZE_REWARD_H -#include <microhttpd.h> -#include "taler-merchant-httpd.h" - - -/** - * Handle a "/reserves/$ID/reward-authorize" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_post_reserves_ID_authorize_reward (const struct - TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - - -/** - * Handle a POST "/rewards" request. - * Here the client does not specify the reserve public key, so we - * are free to pick "any" available reserve. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_post_rewards (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - - -#endif diff --git a/src/backend/taler-merchant-httpd_private-post-reserves.c b/src/backend/taler-merchant-httpd_private-post-reserves.c deleted file mode 100644 index 4d1ea3c9..00000000 --- a/src/backend/taler-merchant-httpd_private-post-reserves.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - This file is part of TALER - (C) 2021-2023 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 General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-post-reserves.c - * @brief implementing POST /reserves request handling - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_private-post-reserves.h" -#include "taler-merchant-httpd_helper.h" -#include "taler-merchant-httpd_reserves.h" -#include <taler/taler_json_lib.h> - - -/** - * How long to wait before giving up processing with the exchange? - */ -#define EXCHANGE_GENERIC_TIMEOUT (GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_SECONDS, \ - 15)) - - -/** - * Information we keep for an individual call to the POST /reserves handler. - */ -struct PostReserveContext -{ - - /** - * Stored in a DLL. - */ - struct PostReserveContext *next; - - /** - * Stored in a DLL. - */ - struct PostReserveContext *prev; - - /** - * Array with @e coins_cnt coins we are despositing. - */ - struct DepositConfirmation *dc; - - /** - * MHD connection to return to - */ - struct MHD_Connection *connection; - - /** - * Details about the client's request. - */ - struct TMH_HandlerContext *hc; - - /** - * URL of the exchange. - */ - const char *exchange_url; - - /** - * Wire method the client wants to use for the payment. - */ - const char *wire_method; - - /** - * Array of accounts that could be used. - */ - json_t *accounts; - - /** - * Handle for contacting the exchange for /keys. - */ - struct TMH_EXCHANGES_KeysOperation *fo; - - /** - * Master public key of the exchange matching - * @e exchange_url. - */ - struct TALER_MasterPublicKeyP master_pub; - - /** - * Initial balance of the reserve. - */ - struct TALER_Amount initial_balance; - - /** - * When will the reserve expire. - */ - struct GNUNET_TIME_Timestamp reserve_expiration; - - /** - * Which HTTP status should we return? - */ - unsigned int http_status; - - /** - * Which error code should we return? - */ - enum TALER_ErrorCode ec; - - /** - * Did we suspend @a connection and are thus in - * the #rc_head DLL (#GNUNET_YES). Set to - * #GNUNET_NO if we are not suspended, and to - * #GNUNET_SYSERR if we should close the connection - * without a response due to shutdown. - */ - enum GNUNET_GenericReturnValue suspended; - - /** - * True if we already force reloaded /keys. - */ - bool force_reload; -}; - - -/** - * Stored in a DLL. - */ -static struct PostReserveContext *rc_head; - -/** - * Stored in a DLL. - */ -static struct PostReserveContext *rc_tail; - - -/** - * Force all post reserve contexts to be resumed as we are about - * to shut down MHD. - */ -void -TMH_force_rc_resume () -{ - struct PostReserveContext *rcn; - - for (struct PostReserveContext *rc = rc_head; - NULL != rc; - rc = rcn) - { - rcn = rc->next; - if (GNUNET_YES == rc->suspended) - { - rc->suspended = GNUNET_SYSERR; - MHD_resume_connection (rc->connection); - GNUNET_CONTAINER_DLL_remove (rc_head, - rc_tail, - rc); - } - if (NULL != rc->fo) - { - TMH_EXCHANGES_keys4exchange_cancel (rc->fo); - rc->fo = NULL; - } - } -} - - -/** - * Custom cleanup routine for a `struct PostReserveContext`. - * - * @param cls the `struct PostReserveContext` to clean up. - */ -static void -reserve_context_cleanup (void *cls) -{ - struct PostReserveContext *rc = cls; - - if (NULL != rc->fo) - { - TMH_EXCHANGES_keys4exchange_cancel (rc->fo); - rc->fo = NULL; - } - GNUNET_assert (GNUNET_YES != rc->suspended); - json_decref (rc->accounts); - GNUNET_free (rc); -} - - -/** - * Resume request handling. - * - * @param[in,out] rc request to resume - */ -static void -resume_request (struct PostReserveContext *rc) -{ - rc->suspended = GNUNET_NO; - MHD_resume_connection (rc->connection); - GNUNET_CONTAINER_DLL_remove (rc_head, - rc_tail, - rc); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ -} - - -/** - * Function called with the result of a #TMH_EXCHANGES_keys4exchange() - * operation. - * - * @param cls closure with our `struct PostReserveContext *` - * @param keys exchange keys - * @param exchange representation of the exchange - */ -static void -handle_exchange (void *cls, - struct TALER_EXCHANGE_Keys *keys, - struct TMH_Exchange *exchange) -{ - struct PostReserveContext *rc = cls; - - rc->fo = NULL; - if (NULL == keys) - { - GNUNET_break_op (0); - rc->ec = TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE; - rc->http_status = MHD_HTTP_GATEWAY_TIMEOUT; - resume_request (rc); - return; - } - if (! keys->rewards_allowed) - { - if (! rc->force_reload) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Forcing %s/keys reload (rewards not allowed)\n", - rc->exchange_url); - rc->force_reload = true; - rc->fo = TMH_EXCHANGES_keys4exchange (rc->exchange_url, - true, - &handle_exchange, - rc); - return; - } - rc->ec = TALER_EC_MERCHANT_PRIVATE_POST_RESERVES_REWARDS_NOT_ALLOWED; - rc->http_status = MHD_HTTP_CONFLICT; - resume_request (rc); - return; - } - rc->master_pub = keys->master_pub; - rc->reserve_expiration - = GNUNET_TIME_relative_to_timestamp (keys->reserve_closing_delay); - rc->accounts = TMH_exchange_accounts_by_method ( - &rc->master_pub, - rc->wire_method); - if ( (NULL == rc->accounts) || - (0 == json_array_size (rc->accounts)) ) - { - if (! rc->force_reload) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Forcing %s/keys reload (no accounts)\n", - rc->exchange_url); - rc->force_reload = true; - rc->fo = TMH_EXCHANGES_keys4exchange (rc->exchange_url, - true, - &handle_exchange, - rc); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Wire method `%s' not supported\n", - rc->wire_method); - rc->ec = TALER_EC_MERCHANT_PRIVATE_POST_RESERVES_UNSUPPORTED_WIRE_METHOD; - rc->http_status = MHD_HTTP_CONFLICT; - resume_request (rc); - return; - } - resume_request (rc); -} - - -MHD_RESULT -TMH_private_post_reserves (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct PostReserveContext *rc = hc->ctx; - struct TMH_MerchantInstance *mi = hc->instance; - - GNUNET_assert (NULL != mi); - if (NULL == rc) - { - rc = GNUNET_new (struct PostReserveContext); - rc->connection = connection; - rc->hc = hc; - hc->ctx = rc; - hc->cc = &reserve_context_cleanup; - - { - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_web_url ("exchange_url", - &rc->exchange_url), - GNUNET_JSON_spec_string ("wire_method", - &rc->wire_method), - TALER_JSON_spec_amount_any ("initial_balance", - &rc->initial_balance), - GNUNET_JSON_spec_end () - }; - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - hc->request_body, - spec); - if (GNUNET_OK != res) - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - rc->fo = TMH_EXCHANGES_keys4exchange (rc->exchange_url, - false, - &handle_exchange, - rc); - rc->suspended = GNUNET_YES; - GNUNET_CONTAINER_DLL_insert (rc_head, - rc_tail, - rc); - MHD_suspend_connection (connection); - return MHD_YES; - } - if (GNUNET_SYSERR == rc->suspended) - return MHD_NO; /* we are in shutdown */ - if (TALER_EC_NONE != rc->ec) - { - return TALER_MHD_reply_with_error (connection, - rc->http_status, - rc->ec, - NULL); - } - GNUNET_assert (GNUNET_NO == rc->suspended); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - rc->reserve_expiration.abs_time)); - { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_ReservePrivateKeyP reserve_priv; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_CRYPTO_eddsa_key_create (&reserve_priv.eddsa_priv); - GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv.eddsa_priv, - &reserve_pub.eddsa_pub); - qs = TMH_db->insert_reserve (TMH_db->cls, - mi->settings.id, - &reserve_priv, - &reserve_pub, - &rc->master_pub, - rc->exchange_url, - &rc->initial_balance, - rc->reserve_expiration); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); - TMH_RESERVES_check (mi->settings.id, - rc->exchange_url, - &reserve_pub, - &rc->initial_balance); - if (qs < 0) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "reserve"); - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_data_auto ("reserve_pub", - &reserve_pub), - GNUNET_JSON_pack_array_incref ("accounts", - rc->accounts)); - } -} - - -/* end of taler-merchant-httpd_private-post-reserves.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-reserves.h b/src/backend/taler-merchant-httpd_private-post-reserves.h deleted file mode 100644 index ca06fe2f..00000000 --- a/src/backend/taler-merchant-httpd_private-post-reserves.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of TALER - (C) 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-post-reserves.h - * @brief implementing POST /reserves request handling - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_RESERVES_H -#define TALER_MERCHANT_HTTPD_PRIVATE_POST_RESERVES_H -#include "taler-merchant-httpd.h" - -/** - * Force all post reserve contexts to be resumed as we are about - * to shut down MHD. - */ -void -TMH_force_rc_resume (); - - -/** - * Generate a reserve entry in our inventory. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_post_reserves (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_reserves.c b/src/backend/taler-merchant-httpd_reserves.c deleted file mode 100644 index 31dec87f..00000000 --- a/src/backend/taler-merchant-httpd_reserves.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - This file is part of TALER - (C) 2020, 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_reserves.c - * @brief logic for initially tracking a reserve's status - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_json_lib.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_reserves.h" - -/** - * How long do we keep the long-poller open? - * Not very long here, as if the money has not - * yet arrived, there is a fair chance that it'll - * take much longer, and in that case we rather - * enter into the delay created by try_later(). - */ -#define LONGPOLL_DELAY GNUNET_TIME_UNIT_MINUTES - -/** - * Our representation of a reserve that we are (still) checking the status of. - */ -struct Reserve -{ - - /** - * Kept in a DLL. - */ - struct Reserve *next; - - /** - * Kept in a DLL. - */ - struct Reserve *prev; - - /** - * Reserve's public key. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Amount the merchant expects to see in the reserve initially. - * We log a warning if there is a mismatch. - */ - struct TALER_Amount expected_amount; - - /** - * URL of the exchange hosting this reserve. - */ - char *exchange_url; - - /** - * Instance this reserve belongs with. - */ - char *instance_id; - - /** - * Task scheduled waiting for a timeout for this reserve. - */ - struct GNUNET_SCHEDULER_Task *tt; - - /** - * Get operation with the exchange. - */ - struct TALER_EXCHANGE_ReservesGetHandle *gh; - - /** - * How long do we wait before trying this reserve again? - */ - struct GNUNET_TIME_Relative delay; - -}; - - -/** - * Head of DLL of pending reserves. - */ -static struct Reserve *reserves_head; - -/** - * Tail of DLL of pending reserves. - */ -static struct Reserve *reserves_tail; - - -/** - * Function called to probe a reserve now. - * - * @param cls a `struct Reserve` to query - */ -static void -try_now (void *cls); - - -/** - * Free reserve data structure. - * - * @param r reserve to free - */ -static void -free_reserve (struct Reserve *r) -{ - GNUNET_CONTAINER_DLL_remove (reserves_head, - reserves_tail, - r); - if (NULL != r->gh) - { - TALER_EXCHANGE_reserves_get_cancel (r->gh); - r->gh = NULL; - } - if (NULL != r->tt) - { - GNUNET_SCHEDULER_cancel (r->tt); - r->tt = NULL; - } - GNUNET_free (r->exchange_url); - GNUNET_free (r->instance_id); - GNUNET_free (r); -} - - -/** - * Schedule a job to probe a reserve later again. - * - * @param r reserve to try again later - */ -static void -try_later (struct Reserve *r) -{ - /* minimum delay is the #LONGPOLL_DELAY */ - r->delay = GNUNET_TIME_relative_max (LONGPOLL_DELAY, - r->delay); - /* STD_BACKOFF has a maximum of 15 minutes */ - r->delay = GNUNET_TIME_STD_BACKOFF (r->delay); - r->tt = GNUNET_SCHEDULER_add_delayed (r->delay, - &try_now, - r); -} - - -/** - * Callbacks of this type are used to serve the result of submitting a - * reserve status request to a exchange. - * - * @param cls closure with a `struct Reserve *` - * @param rs HTTP response data - */ -static void -reserve_cb (void *cls, - const struct TALER_EXCHANGE_ReserveSummary *rs) -{ - struct Reserve *r = cls; - enum GNUNET_DB_QueryStatus qs; - - r->gh = NULL; - if (MHD_HTTP_OK != rs->hr.http_status) - { - try_later (r); - return; - } - if (GNUNET_OK != - TALER_amount_cmp_currency (&r->expected_amount, - &rs->details.ok.balance)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Reserve currency disagreement: exchange `%s' has %s, expected %s\n", - r->exchange_url, - rs->details.ok.balance.currency, - r->expected_amount.currency); - free_reserve (r); - return; - } - if (0 != - TALER_amount_cmp (&r->expected_amount, - &rs->details.ok.balance)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Reserve initial balance disagreement: exchange `%s' received `%s'\n", - r->exchange_url, - TALER_amount2s (&rs->details.ok.balance)); - } - qs = TMH_db->activate_reserve (TMH_db->cls, - r->instance_id, - &r->reserve_pub, - &rs->details.ok.balance); - if (qs <= 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to commit reserve activation to database (%d)\n", - (int) qs); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Reserve activated with initial balance %s\n", - TALER_amount2s (&rs->details.ok.balance)); - } - free_reserve (r); -} - - -/** - * Function called to probe a reserve now. - * - * @param cls a `struct Reserve` to query - */ -static void -try_now (void *cls) -{ - struct Reserve *r = cls; - - r->tt = NULL; - r->gh = TALER_EXCHANGE_reserves_get (TMH_curl_ctx, - r->exchange_url, - &r->reserve_pub, - LONGPOLL_DELAY, - &reserve_cb, - r); - if (NULL == r->gh) - { - try_later (r); - return; - } -} - - -/** - * Function called with information about a reserve that we need - * to check the status from at the exchange to see if/when it has - * been filled (and with what amount). - * - * @param cls closure, NULL - * @param instance_id for which instance is this reserve - * @param exchange_url base URL of the exchange at which the reserve lives - * @param reserve_pub public key of the reserve - * @param expected_amount how much do we expect to see in the reserve - */ -static void -add_reserve (void *cls, - const char *instance_id, - const char *exchange_url, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *expected_amount) -{ - struct Reserve *r; - - (void) cls; - r = GNUNET_new (struct Reserve); - r->exchange_url = GNUNET_strdup (exchange_url); - r->instance_id = GNUNET_strdup (instance_id); - r->reserve_pub = *reserve_pub; - r->expected_amount = *expected_amount; - GNUNET_CONTAINER_DLL_insert (reserves_head, - reserves_tail, - r); - try_now (r); -} - - -void -TMH_RESERVES_init (void) -{ - TMH_db->lookup_pending_reserves (TMH_db->cls, - &add_reserve, - NULL); -} - - -void -TMH_RESERVES_check (const char *instance_id, - const char *exchange_url, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *expected_amount) -{ - add_reserve (NULL, - instance_id, - exchange_url, - reserve_pub, - expected_amount); -} - - -void -TMH_RESERVES_done (void) -{ - while (NULL != reserves_head) - free_reserve (reserves_head); -} - - -/* end of taler-merchant-httpd_reserves.c */ diff --git a/src/backend/taler-merchant-httpd_reserves.h b/src/backend/taler-merchant-httpd_reserves.h deleted file mode 100644 index af4133b1..00000000 --- a/src/backend/taler-merchant-httpd_reserves.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of TALER - (C) 2020 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_reserves.h - * @brief logic for initially tracking a reserve's status - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_RESERVES_H -#define TALER_MERCHANT_HTTPD_RESERVES_H - -#include <jansson.h> -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> -#include <taler/taler_exchange_service.h> -#include "taler-merchant-httpd.h" - - -/** - * Load information about reserves and start querying reserve status. - * Must be called after the database is available. - */ -void -TMH_RESERVES_init (void); - - -/** - * Add a reserve to the list of reserves to check. - * - * @param instance_id which instance is the reserve for - * @param exchange_url URL of the exchange with the reserve - * @param reserve_pub public key of the reserve to check - * @param expected_amount amount the merchant expects to see initially in the reserve - */ -void -TMH_RESERVES_check (const char *instance_id, - const char *exchange_url, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *expected_amount); - - -/** - * Stop checking reserve status. - */ -void -TMH_RESERVES_done (void); - - -#endif diff --git a/src/backend/taler-merchant-wirewatch.c b/src/backend/taler-merchant-wirewatch.c index 77428da3..e1605bc1 100644 --- a/src/backend/taler-merchant-wirewatch.c +++ b/src/backend/taler-merchant-wirewatch.c @@ -342,7 +342,8 @@ credit_cb ( { case 0: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid HTTP response from bank\n"); + "Invalid HTTP response (HTTP status: 0, %d) from bank\n", + ec); w->delay = GNUNET_TIME_STD_BACKOFF (w->delay); break; case MHD_HTTP_OK: @@ -443,6 +444,7 @@ credit_cb ( = GNUNET_TIME_relative_max (w->bank_timeout, GNUNET_TIME_UNIT_SECONDS); w->delay = GNUNET_TIME_STD_BACKOFF (w->delay); + break; default: /* Something went wrong, try again, but with back-off */ w->delay = GNUNET_TIME_STD_BACKOFF (w->delay); |