summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-transfers-ID.c2
-rw-r--r--src/backend/taler-merchant-httpd_private-post-transfers.c154
2 files changed, 141 insertions, 15 deletions
diff --git a/src/backend/taler-merchant-httpd_private-delete-transfers-ID.c b/src/backend/taler-merchant-httpd_private-delete-transfers-ID.c
index fd5c968a..93656f4a 100644
--- a/src/backend/taler-merchant-httpd_private-delete-transfers-ID.c
+++ b/src/backend/taler-merchant-httpd_private-delete-transfers-ID.c
@@ -24,7 +24,7 @@
/**
- * Handle a DELETE "/transfers/$ID" request.
+ * Handle a DELETE "/private/transfers/$ID" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c
index 4fd0819d..5ac4ec9d 100644
--- a/src/backend/taler-merchant-httpd_private-post-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-post-transfers.c
@@ -146,6 +146,10 @@ struct PostTransfersContext
*/
bool downloaded;
+ /**
+ * Are we currently suspended?
+ */
+ bool suspended;
};
@@ -170,6 +174,7 @@ TMH_force_post_transfers_resume ()
GNUNET_CONTAINER_DLL_remove (ptc_head,
ptc_tail,
ptc);
+ ptc->suspended = false;
MHD_resume_connection (ptc->connection);
if (NULL != ptc->timeout_task)
{
@@ -207,6 +212,7 @@ resume_transfer_with_response (struct PostTransfersContext *ptc,
GNUNET_CONTAINER_DLL_remove (ptc_head,
ptc_tail,
ptc);
+ ptc->suspended = false;
MHD_resume_connection (ptc->connection);
TMH_trigger_daemon (); /* we resumed, kick MHD */
}
@@ -468,8 +474,22 @@ wire_transfer_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Got response code %u from exchange for GET /transfers/$WTID\n",
hr->http_status);
- if (MHD_HTTP_OK != hr->http_status)
+ switch (hr->http_status)
{
+ case MHD_HTTP_OK:
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ resume_transfer_with_response (
+ ptc,
+ MHD_HTTP_BAD_GATEWAY,
+ TALER_MHD_make_json_pack (
+ "{s:I, s:I, s:I}",
+ "code",
+ (json_int_t) TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN,
+ "exchange_code", (json_int_t) hr->ec,
+ "exchange_http_status", (json_int_t) hr->http_status));
+ return;
+ default:
resume_transfer_with_response (
ptc,
MHD_HTTP_BAD_GATEWAY,
@@ -482,7 +502,6 @@ wire_transfer_cb (void *cls,
"exchange_reply", hr->reply));
return;
}
-
TMH_db->preflight (TMH_db->cls);
/* Ok, exchange answer is acceptable, store it */
qs = TMH_db->insert_transfer_details (TMH_db->cls,
@@ -504,6 +523,29 @@ wire_transfer_cb (void *cls,
NULL);
return;
}
+ if (0 == qs)
+ {
+ GNUNET_break (0);
+ resume_transfer_with_error (
+ ptc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert-transfer-details");
+ return;
+ }
+ if (0 !=
+ TALER_amount_cmp (&td->total_amount,
+ &ptc->amount))
+ {
+ resume_transfer_with_error (
+ ptc,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS,
+ NULL);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Transfer details inserted, resuming request...\n");
/* resume processing, main function will build the response */
resume_transfer_with_response (ptc,
0,
@@ -536,6 +578,8 @@ process_transfer_with_exchange (void *cls,
ptc->fo = NULL;
if (NULL == hr)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Exchange failed to respond!\n");
resume_transfer_with_response (
ptc,
MHD_HTTP_GATEWAY_TIMEOUT,
@@ -584,6 +628,8 @@ process_transfer_with_exchange (void *cls,
ptc->master_pub = keys->master_pub;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requesting transfer details from exchange\n");
ptc->wdh = TALER_EXCHANGE_transfers_get (eh,
&ptc->wtid,
&wire_transfer_cb,
@@ -664,7 +710,7 @@ verify_exchange_claim_cb (void *cls,
ptc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
ptc->response =
TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "check_transfer_result must not be NULL");
+ "check_transfer_result must not be GNUNET_NO");
return;
case GNUNET_SYSERR:
/* #check_transfer() failed, report conflict! */
@@ -864,6 +910,7 @@ download (struct PostTransfersContext *ptc)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Suspending POST /private/transfers handling while working with exchange\n");
MHD_suspend_connection (ptc->connection);
+ ptc->suspended = true;
GNUNET_CONTAINER_DLL_insert (ptc_head,
ptc_tail,
ptc);
@@ -895,12 +942,14 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
hc->ctx = ptc;
hc->cc = &transfer_cleanup;
}
+ /* resume logic: did we get resumed after a reply was built? */
if (0 != ptc->response_code)
return queue (ptc);
if ( (NULL != ptc->fo) ||
(NULL != ptc->wdh) )
{
/* likely old MHD version causing spurious wake-up */
+ GNUNET_break (ptc->suspended);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Not sure why we are here, should be suspended\n");
return MHD_YES; /* still work in progress */
@@ -939,6 +988,11 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_CURRENCY_MISMATCH,
TMH_currency);
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "New inbound wire transfer over %s to %s from %s\n",
+ TALER_amount2s (&ptc->amount),
+ ptc->payto_uri,
+ ptc->exchange_url);
}
/* Check if transfer data is in database, if not, add it. */
@@ -946,8 +1000,10 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
{
struct GNUNET_TIME_Absolute execution_time;
struct TALER_Amount total_amount;
+ struct TALER_Amount exchange_amount;
struct TALER_Amount wire_fee;
bool verified;
+ bool have_exchange_sig;
TMH_db->preflight (TMH_db->cls);
if (GNUNET_OK !=
@@ -966,7 +1022,9 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
&ptc->wtid,
&total_amount,
&wire_fee,
+ &exchange_amount,
&execution_time,
+ &have_exchange_sig,
&verified);
switch (qs)
{
@@ -982,7 +1040,9 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TMH_db->rollback (TMH_db->cls);
continue;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* Transfer so far unknown */
+ /* Transfer so far unknown; try to persist the wire transfer information
+ we have received in the database (it is not yet present). Upon
+ success, try to download the transfer details from the exchange. */
{
uint64_t account_serial;
@@ -1019,6 +1079,8 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
break;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Inserting new transfer\n");
qs = TMH_db->insert_transfer (TMH_db->cls,
ptc->hc->instance->settings.id,
ptc->exchange_url,
@@ -1030,6 +1092,8 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
{
case GNUNET_DB_STATUS_SOFT_ERROR:
TMH_db->rollback (TMH_db->cls);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Soft error, retrying...\n");
continue;
case GNUNET_DB_STATUS_HARD_ERROR:
GNUNET_break (0);
@@ -1039,12 +1103,13 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_DB_STORE_FAILED,
"transfer");
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* transfer present, but transfer _details_
- missing (hence the SELECT returned an empty
- set after intersection via USING part of the
- query). Fine, we still need to talk to the
- exchange! */
- break;
+ TMH_db->rollback (TMH_db->cls);
+ /* Should not happen: we checked earlier! */
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "not unique");
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
}
@@ -1069,21 +1134,36 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
break;
}
download (ptc);
- return MHD_YES;
+ return MHD_YES; /* download() always suspends */
}
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* Transfer exists */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Transfer exists in DB\n");
+ "Transfer exists in DB (verified: %s, exchange signature: %s)\n",
+ verified ? "true" : "false",
+ have_exchange_sig ? "true" : "false");
if (! verified)
{
- if (! ptc->downloaded)
+ if ( (! ptc->downloaded) &&
+ (! have_exchange_sig) )
{
/* We may have previously attempted and failed to
download the exchange data, do it again! */
TMH_db->rollback (TMH_db->cls);
download (ptc);
- return MHD_YES;
+ return MHD_YES; /* download always suspends */
+ }
+ if (! have_exchange_sig)
+ {
+ /* We tried to download and still failed to get
+ an exchange signture. Still, that should have
+ been handled there. */
+ TMH_db->rollback (TMH_db->cls);
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "download but no exchange signature and no error");
}
/* verify */
if (GNUNET_SYSERR ==
@@ -1135,6 +1215,52 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TMH_db->rollback (TMH_db->cls);
continue;
}
+
+ {
+ struct TALER_Amount delta;
+
+ if (0 >
+ TALER_amount_subtract (&delta,
+ &total_amount,
+ &wire_fee))
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ NULL);
+ }
+ if (0 !=
+ TALER_amount_cmp (&exchange_amount,
+ &delta))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Amount of expected was %s\n",
+ TALER_amount2s (&delta));
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS,
+ TALER_amount2s (&exchange_amount));
+ }
+ if ( (GNUNET_OK !=
+ TALER_amount_cmp_currency (&ptc->amount,
+ &delta)) ||
+ (0 !=
+ TALER_amount_cmp (&ptc->amount,
+ &delta)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Amount submitted was %s\n",
+ TALER_amount2s (&ptc->amount));
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION,
+ TALER_amount2s (&exchange_amount));
+ }
+ }
verified = true;
qs = TMH_db->set_transfer_status_to_verified (TMH_db->cls,
ptc->exchange_url,