diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-11-17 18:45:39 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-11-17 18:45:39 +0100 |
commit | 1e58df9cbc55bddd40b2de333924eef79a00c2c4 (patch) | |
tree | 4a527c737d1a1a66e03f45c132f6a9cac91766a2 /src | |
parent | 5feedd7154afcd66d4d16923bdfe4ecbfd5cb700 (diff) | |
download | sync-1e58df9cbc55bddd40b2de333924eef79a00c2c4.tar.gz sync-1e58df9cbc55bddd40b2de333924eef79a00c2c4.tar.bz2 sync-1e58df9cbc55bddd40b2de333924eef79a00c2c4.zip |
address last FIXME
Diffstat (limited to 'src')
-rw-r--r-- | src/sync/sync-httpd_backup_post.c | 160 |
1 files changed, 88 insertions, 72 deletions
diff --git a/src/sync/sync-httpd_backup_post.c b/src/sync/sync-httpd_backup_post.c index 58d517a..0866784 100644 --- a/src/sync/sync-httpd_backup_post.c +++ b/src/sync/sync-httpd_backup_post.c @@ -118,6 +118,12 @@ struct BackupContext char *existing_order_id; /** + * Timestamp of the order in @e existing_order_id. Used to + * select the most recent unpaid offer. + */ + struct GNUNET_TIME_Absolute existing_order_timestamp; + + /** * Expected total upload size. */ size_t upload_size; @@ -190,6 +196,7 @@ cleanup_ctx (struct TM_HandlerContext *hc) GNUNET_CRYPTO_hash_context_abort (bc->hash_ctx); if (NULL != bc->resp) MHD_destroy_response (bc->resp); + GNUNET_free_non_null (bc->existing_order_id); GNUNET_free_non_null (bc->upload); GNUNET_free (bc); } @@ -290,78 +297,17 @@ ongoing_payment_cb (void *cls, { struct BackupContext *bc = cls; + (void) amount; if (0 != TALER_amount_cmp (amount, &SH_annual_fee)) return; /* can't re-use, fees changed */ - bc->existing_order_id = GNUNET_strdup (order_id); -} - - -/** - * Helper function used to ask our backend to begin - * processing a payment for the user's account. - * - * @param bc context to begin payment for. - */ -static int -begin_payment (struct BackupContext *bc) -{ - json_t *order; - enum GNUNET_DB_QueryStatus qs; - - qs = db->lookup_pending_payments_by_account_TR (db->cls, - &bc->account, - &ongoing_payment_cb, - bc); - if (qs < 0) - { - struct MHD_Response *resp; - int ret; - - resp = SH_RESPONSE_make_error (TALER_EC_SYNC_PAYMENT_CHECK_ORDER_DB_ERROR, - "Failed to check for existing orders in sync database"); - ret = MHD_queue_response (bc->con, - MHD_HTTP_INTERNAL_SERVER_ERROR, - resp); - MHD_destroy_response (resp); - return ret; - } - if (NULL != bc->existing_order_id) + if ( (NULL == bc->existing_order_id) || + (bc->existing_order_timestamp.abs_value_us < timestamp.abs_value_us) ) { - // FIXME: this is incorrect, we should FIRST check - // if that payment was ALREADY MADE against our - // backend, and only if NOT return payment required here! - // (this also means that #begin_payment() and - // #handle_database_error() have for now - // the wrong signature, as it is possible that we - // would continue as if there were no problem! - struct MHD_Response *resp; - int ret; - - resp = make_payment_request (bc->existing_order_id); - GNUNET_free (bc->existing_order_id); - bc->existing_order_id = NULL; - ret = MHD_queue_response (bc->con, - MHD_HTTP_PAYMENT_REQUIRED, - resp); - MHD_destroy_response (resp); - return ret; + GNUNET_free_non_null (bc->existing_order_id); + bc->existing_order_id = GNUNET_strdup (order_id); + bc->existing_order_timestamp = timestamp; } - GNUNET_CONTAINER_DLL_insert (bc_head, - bc_tail, - bc); - MHD_suspend_connection (bc->con); - order = json_pack ("{s:o, s:s, s:s}", - "amount", TALER_JSON_from_amount (&SH_annual_fee), - "summary", "annual fee for sync service", - "fulfillment_url", SH_my_base_url); - bc->po = TALER_MERCHANT_order_put (SH_ctx, - SH_backend_url, - order, - &proposal_cb, - bc); - json_decref (order); - return MHD_YES; } @@ -413,6 +359,13 @@ check_payment_cb (void *cls, bc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; return; /* continue as planned */ } + if (NULL != bc->existing_order_id) + { + /* repeat payment request */ + bc->resp = make_payment_request (bc->existing_order_id); + bc->response_code = MHD_HTTP_PAYMENT_REQUIRED; + return; + } bc->resp = SH_RESPONSE_make_error (TALER_EC_SYNC_PAYMENT_TIMEOUT, "Timeout awaiting promised payment"); bc->response_code = MHD_HTTP_REQUEST_TIMEOUT; @@ -448,7 +401,69 @@ await_payment (struct BackupContext *bc, /** + * Helper function used to ask our backend to begin + * processing a payment for the user's account. + * May perform asynchronous operations by suspending the connection + * if required. + * + * @param bc context to begin payment for. + * @param pay_req #GNUNET_YES if payment was explicitly requested, + * #GNUNET_NO if payment is needed + * @return MHD status code + */ +static int +begin_payment (struct BackupContext *bc, + int pay_req) +{ + json_t *order; + enum GNUNET_DB_QueryStatus qs; + + qs = db->lookup_pending_payments_by_account_TR (db->cls, + &bc->account, + &ongoing_payment_cb, + bc); + if (qs < 0) + { + struct MHD_Response *resp; + int ret; + + resp = SH_RESPONSE_make_error (TALER_EC_SYNC_PAYMENT_CHECK_ORDER_DB_ERROR, + "Failed to check for existing orders in sync database"); + ret = MHD_queue_response (bc->con, + MHD_HTTP_INTERNAL_SERVER_ERROR, + resp); + MHD_destroy_response (resp); + return ret; + } + if (NULL != bc->existing_order_id) + { + await_payment (bc, + GNUNET_TIME_UNIT_ZERO /* no long polling */, + bc->existing_order_id); + return MHD_YES; + } + GNUNET_CONTAINER_DLL_insert (bc_head, + bc_tail, + bc); + MHD_suspend_connection (bc->con); + order = json_pack ("{s:o, s:s, s:s}", + "amount", TALER_JSON_from_amount (&SH_annual_fee), + "summary", "annual fee for sync service", + "fulfillment_url", SH_my_base_url); + bc->po = TALER_MERCHANT_order_put (SH_ctx, + SH_backend_url, + order, + &proposal_cb, + bc); + json_decref (order); + return MHD_YES; +} + + +/** * We got some query status from the DB. Handle the error cases. + * May perform asynchronous operations by suspending the connection + * if required. * * @param bc connection to handle status for * @param qs query status to handle @@ -472,7 +487,10 @@ handle_database_error (struct BackupContext *bc, MHD_GET_ARGUMENT_KIND, "paying"); if (NULL == order_id) - return begin_payment (bc); + { + return begin_payment (bc, + GNUNET_NO); + } await_payment (bc, CHECK_PAYMENT_TIMEOUT, order_id); @@ -694,10 +712,8 @@ sync_handler_backup_post (struct MHD_Connection *connection, MHD_GET_ARGUMENT_KIND, "pay"); if (NULL != order_req) - { - begin_payment (bc); - return MHD_YES; - } + return begin_payment (bc, + GNUNET_YES); } /* ready to begin! */ return MHD_YES; |