diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_get-reserves.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_get-reserves.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/src/backend/taler-merchant-httpd_get-reserves.c b/src/backend/taler-merchant-httpd_get-reserves.c deleted file mode 100644 index e104e089..00000000 --- a/src/backend/taler-merchant-httpd_get-reserves.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - This file is part of TALER - (C) 2018--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 backend/taler-merchant-httpd_tip-reserve-helper.c - * @brief helper functions to check the status of a tipping reserve - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler-merchant-httpd_tip-reserve-helper.h" - - -/** - * Head of active ctr context DLL. - */ -static struct TMH_CheckTipReserve *ctr_head; - -/** - * Tail of active ctr context DLL. - */ -static struct TMH_CheckTipReserve *ctr_tail; - - -/** - * Resume connection underlying @a ctr. - * - * @param ctr what to resume - */ -static void -resume_ctr (struct TMH_CheckTipReserve *ctr) -{ - GNUNET_assert (GNUNET_YES == ctr->suspended); - GNUNET_CONTAINER_DLL_remove (ctr_head, - ctr_tail, - ctr); - MHD_resume_connection (ctr->connection); - TMH_trigger_daemon (); /* we resumed, kick MHD */ -} - - -/** - * Resume the given context and send the given response. Stores the response - * in the @a ctr and signals MHD to resume the connection. Also ensures MHD - * runs immediately. - * - * @param ctr tip reserve query helper context - * @param response_code response code to use - * @param response response data to send back - */ -static void -resume_with_response (struct TMH_CheckTipReserve *ctr, - unsigned int response_code, - struct MHD_Response *response) -{ - ctr->response_code = response_code; - ctr->response = response; - resume_ctr (ctr); - ctr->suspended = GNUNET_NO; -} - - -/** - * Function called with the result of the /reserve/status request - * for the tipping reserve. Update our database balance with the - * result. - * - * @param cls closure with a `struct TMH_CheckTipReserve *' - * @param hr HTTP response details - * @param balance current balance in the reserve, NULL on error - * @param history_length number of entries in the transaction history, 0 on error - * @param history detailed transaction history, NULL on error - */ -static void -handle_status (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_Amount *balance, - unsigned int history_length, - const struct TALER_EXCHANGE_ReserveHistory *history) -{ - struct TMH_CheckTipReserve *ctr = cls; - - ctr->rsh = NULL; - ctr->reserve_expiration = GNUNET_TIME_UNIT_ZERO_ABS; - if (MHD_HTTP_NOT_FOUND == hr->http_status) - { - resume_with_response ( - ctr, - MHD_HTTP_SERVICE_UNAVAILABLE, - TALER_MHD_make_json_pack ( - "{s:I, s:I, s:s, s:I, s:O}", - "code", (json_int_t) TALER_EC_TIP_QUERY_RESERVE_UNKNOWN_TO_EXCHANGE, - "exchange_http_status", hr->http_status, - "hint", "tipping reserve unknown at exchange", - "exchange_code", hr->ec, - "exchange_reply", hr->reply)); - return; - } - if (MHD_HTTP_OK != hr->http_status) - { - GNUNET_break_op (0); - resume_with_response ( - ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_json_pack ( - "{s:I, s:I, s:s, s:I, s:O}", - "code", (json_int_t) TALER_EC_TIP_QUERY_RESERVE_HISTORY_FAILED, - "exchange_http_status", hr->http_status, - "hint", "exchange failed to provide reserve history", - "exchange_code", (json_int_t) hr->ec, - "exchange_reply", hr->reply)); - return; - } - - if (0 == history_length) - { - GNUNET_break_op (0); - resume_with_response (ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_FAILED_EMPTY, - "Exchange returned empty reserve history")); - return; - } - - { - unsigned int found = UINT_MAX; - - for (unsigned int i = 0; i<history_length; i++) - if (TALER_EXCHANGE_RTT_CREDIT == history[i].type) - found = i; - if (UINT_MAX == found) - { - GNUNET_break_op (0); - resume_with_response (ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_INVALID_NO_DEPOSIT, - "Exchange returned invalid reserve history")); - return; - } - - if (0 != strcasecmp (TMH_currency, - history[found].amount.currency)) - { - GNUNET_break_op (0); - resume_with_response (ctr, - MHD_HTTP_SERVICE_UNAVAILABLE, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_CURRENCY_MISMATCH, - "Exchange currency unexpected")); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_amount_get_zero (history[found].amount.currency, - &ctr->amount_withdrawn)); - } - - if (GNUNET_YES == ctr->none_authorized) - ctr->amount_authorized = ctr->amount_withdrawn; /* aka zero */ - ctr->amount_deposited = ctr->amount_withdrawn; /* aka zero */ - - /* Update DB based on status! */ - for (unsigned int i = 0; i<history_length; i++) - { - const struct TALER_EXCHANGE_ReserveHistory *hi = &history[i]; - - switch (hi->type) - { - case TALER_EXCHANGE_RTT_CREDIT: - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_HashCode uuid; - struct GNUNET_TIME_Absolute deposit_expiration; - - if (0 > - TALER_amount_add (&ctr->amount_deposited, - &ctr->amount_deposited, - &hi->amount)) - { - GNUNET_break_op (0); - resume_with_response ( - ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_DEPOSIT, - "Exchange returned invalid reserve history (amount overflow)")); - return; - } - deposit_expiration = GNUNET_TIME_absolute_add ( - hi->details.in_details.timestamp, - ctr->idle_reserve_expiration_time); - /* We're interested in the latest DEPOSIT timestamp, since this determines the - * reserve's expiration date. Note that the history isn't chronologically ordered. */ - ctr->reserve_expiration = GNUNET_TIME_absolute_max ( - ctr->reserve_expiration, - deposit_expiration); - GNUNET_CRYPTO_hash (hi->details.in_details.wire_reference, - hi->details.in_details.wire_reference_size, - &uuid); - db->preflight (db->cls); - qs = db->enable_tip_reserve_TR (db->cls, - &ctr->reserve_priv, - &uuid, - &hi->amount, - deposit_expiration); - - if (0 > qs) - { - /* This is not inherently fatal for the client's request, so we merely log it */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Database error updating tipping reserve status: %d\n", - qs); - } - } - break; - case TALER_EXCHANGE_RTT_WITHDRAWAL: - if (0 > - TALER_amount_add (&ctr->amount_withdrawn, - &ctr->amount_withdrawn, - &hi->amount)) - { - GNUNET_break_op (0); - resume_with_response ( - ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_WITHDRAW, - "Exchange returned invalid reserve history (amount overflow)")); - return; - } - break; - case TALER_EXCHANGE_RTT_RECOUP: - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_HashContext *hc; - struct GNUNET_HashCode uuid; - struct GNUNET_TIME_Absolute deposit_expiration; - struct GNUNET_TIME_AbsoluteNBO de; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Encountered unexpected recoup operation on tipping reserve\n"); - /* While unexpected, we can simply count these like deposits. */ - if (0 > - TALER_amount_add (&ctr->amount_deposited, - &ctr->amount_deposited, - &hi->amount)) - { - GNUNET_break_op (0); - resume_with_response ( - ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_RECOUP, - "Exchange returned invalid reserve history (amount overflow)")); - return; - } - deposit_expiration = GNUNET_TIME_absolute_add ( - hi->details.recoup_details.timestamp, - ctr->idle_reserve_expiration_time); - ctr->reserve_expiration = GNUNET_TIME_absolute_max ( - ctr->reserve_expiration, - deposit_expiration); - de = GNUNET_TIME_absolute_hton (deposit_expiration); - hc = GNUNET_CRYPTO_hash_context_start (); - GNUNET_CRYPTO_hash_context_read ( - hc, - &hi->details.recoup_details.coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP)); - GNUNET_CRYPTO_hash_context_read (hc, - &de, - sizeof (de)); - GNUNET_CRYPTO_hash_context_finish (hc, - &uuid); - db->preflight (db->cls); - qs = db->enable_tip_reserve_TR (db->cls, - &ctr->reserve_priv, - &uuid, - &hi->amount, - deposit_expiration); - if (0 > qs) - { - /* This is not inherently fatal for the client's request, so we merely log it */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Database error updating tipping reserve status: %d\n", - qs); - } - } - break; - case TALER_EXCHANGE_RTT_CLOSE: - /* We count 'closing' amounts just like withdrawals */ - if (0 > - TALER_amount_add (&ctr->amount_withdrawn, - &ctr->amount_withdrawn, - &hi->amount)) - { - GNUNET_break_op (0); - resume_with_response ( - ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_CLOSED, - "Exchange returned invalid reserve history (amount overflow)")); - return; - } - break; - } - } - - /* normal, non-error continuation */ - resume_with_response (ctr, - 0, - NULL); -} - - -/** - * Function called with the result of a #TMH_EXCHANGES_find_exchange() - * operation. Given the exchange handle, we will then interrogate - * the exchange about the status of the tipping reserve. - * - * @param cls closure with a `struct TMH_CheckTipReserve *` - * @param hr HTTP response details - * @param eh handle to the exchange context - * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available - * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config - */ -static void -exchange_cont (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - struct TALER_EXCHANGE_Handle *eh, - const struct TALER_Amount *wire_fee, - int exchange_trusted) -{ - struct TMH_CheckTipReserve *ctr = cls; - struct TALER_ReservePublicKeyP reserve_pub; - const struct TALER_EXCHANGE_Keys *keys; - - ctr->fo = NULL; - if (NULL == eh) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to contact exchange configured for tipping!\n"); - resume_with_response (ctr, - MHD_HTTP_FAILED_DEPENDENCY, - TALER_MHD_make_error ( - TALER_EC_TIP_QUERY_RESERVE_STATUS_FAILED_EXCHANGE_DOWN, - "Unable to obtain /keys from exchange")); - return; - } - keys = TALER_EXCHANGE_get_keys (eh); - GNUNET_assert (NULL != keys); - ctr->idle_reserve_expiration_time - = keys->reserve_closing_delay; - GNUNET_CRYPTO_eddsa_key_get_public (&ctr->reserve_priv.eddsa_priv, - &reserve_pub.eddsa_pub); - ctr->rsh = TALER_EXCHANGE_reserves_get (eh, - &reserve_pub, - &handle_status, - ctr); -} - - -/** - * Check the status of the given reserve at the given exchange. - * Suspends the MHD connection while this is happening and resumes - * processing once we know the reserve status (or once an error - * code has been determined). - * - * @param[in,out] ctr context for checking the reserve status - * @param tip_exchange the URL of the exchange to query - */ -void -TMH_check_tip_reserve (struct TMH_CheckTipReserve *ctr, - const char *tip_exchange) -{ - MHD_suspend_connection (ctr->connection); - ctr->suspended = GNUNET_YES; - GNUNET_CONTAINER_DLL_insert (ctr_head, - ctr_tail, - ctr); - db->preflight (db->cls); - ctr->fo = TMH_EXCHANGES_find_exchange (tip_exchange, - NULL, - GNUNET_NO, - &exchange_cont, - ctr); - if (NULL == ctr->fo) - { - GNUNET_break (0); - resume_with_response (ctr, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_MHD_make_error ( - TALER_EC_INTERNAL_INVARIANT_FAILURE, - "Unable to find exchange handle")); - } -} - - -/** - * Clean up any state that might be left in @a ctr. - * - * @param[in] context to clean up - */ -void -TMH_check_tip_reserve_cleanup (struct TMH_CheckTipReserve *ctr) -{ - if (NULL != ctr->rsh) - { - TALER_EXCHANGE_reserves_get_cancel (ctr->rsh); - ctr->rsh = NULL; - } - if (NULL != ctr->fo) - { - TMH_EXCHANGES_find_exchange_cancel (ctr->fo); - ctr->fo = NULL; - } - if (NULL != ctr->response) - { - MHD_destroy_response (ctr->response); - ctr->response = NULL; - } - if (MHD_YES == ctr->suspended) - { - resume_ctr (ctr); - ctr->suspended = GNUNET_NO; - } -} - - -/** - * Force all tip reserve helper contexts to be resumed as we are about to shut - * down MHD. - */ -void -MH_force_trh_resume () -{ - struct TMH_CheckTipReserve *n; - - for (struct TMH_CheckTipReserve *ctr = ctr_head; - NULL != ctr; - ctr = n) - { - n = ctr->next; - resume_ctr (ctr); - ctr->suspended = GNUNET_SYSERR; - } -} - - -/* end of taler-merchant-httpd_tip-reserve-helper.c */ |