From 778c2228f8662d748b65e48104be357c162d51ca Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 29 Nov 2019 23:21:33 +0100 Subject: fix issues --- src/include/sync_database_plugin.h | 5 +++ src/lib/sync_api_upload.c | 6 ++++ src/lib/test_sync_api.conf | 5 ++- src/sync/sync-httpd.c | 36 +++++++++++++++----- src/sync/sync-httpd.h | 7 ++++ src/sync/sync-httpd_backup.c | 12 +++++++ src/sync/sync-httpd_backup_post.c | 67 +++++++++++++++++++++++++++++++++++-- src/syncdb/plugin_syncdb_postgres.c | 2 +- 8 files changed, 127 insertions(+), 13 deletions(-) diff --git a/src/include/sync_database_plugin.h b/src/include/sync_database_plugin.h index 0321ce2..cf6a026 100644 --- a/src/include/sync_database_plugin.h +++ b/src/include/sync_database_plugin.h @@ -33,6 +33,11 @@ */ enum SYNC_DB_QueryStatus { + /** + * Client claimed to be updating an existing backup, but we have none. + */ + SYNC_DB_OLD_BACKUP_MISSING = -5, + /** * Update failed because the old backup hash does not match what we previously had in the DB. */ diff --git a/src/lib/sync_api_upload.c b/src/lib/sync_api_upload.c index 2e2f7c8..33ff381 100644 --- a/src/lib/sync_api_upload.c +++ b/src/lib/sync_api_upload.c @@ -158,6 +158,12 @@ handle_upload_finished (void *cls, ec = TALER_JSON_get_error_code2 (data, data_size); break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Internal server error: `%.*s\n", + (int) data_size, + (const char *) data); + break; } if (NULL != uo->cb) { diff --git a/src/lib/test_sync_api.conf b/src/lib/test_sync_api.conf index 057420d..c767b72 100644 --- a/src/lib/test_sync_api.conf +++ b/src/lib/test_sync_api.conf @@ -12,9 +12,12 @@ CURRENCY = EUR # Sync config [sync] -# Which port do we run the backend on? (HTTP server) +# Which port do we run the *sync* backend on? (HTTP server) PORT = 8084 +# Where does our payment backend run? Must match PORT under [merchant] +PAYMENT_BACKEND_URL = http://localhost:8080/ + [syncdb-postgres] CONFIG = postgres:///synccheck diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c index 975db92..8700a50 100644 --- a/src/sync/sync-httpd.c +++ b/src/sync/sync-httpd.c @@ -196,7 +196,7 @@ url_handler (void *cls, /* We only read the correlation ID on the first callback for every client */ correlation_id = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, - "sync-Correlation-Id"); + "Sync-Correlation-Id"); if ((NULL != correlation_id) && (GNUNET_YES != is_valid_correlation_id (correlation_id))) { @@ -249,11 +249,21 @@ url_handler (void *cls, if (0 == strcasecmp (method, MHD_HTTP_METHOD_POST)) { - return sync_handler_backup_post (connection, - con_cls, - &account_pub, - upload_data, - upload_data_size); + int ret; + + ret = sync_handler_backup_post (connection, + con_cls, + &account_pub, + upload_data, + upload_data_size); + hc = *con_cls; + if (NULL != hc) + { + /* Store the async context ID, so we can restore it if + * we get another callack for this request. */ + hc->async_scope_id = aid; + } + return ret; } } for (unsigned int i = 0; NULL != handlers[i].url; i++) @@ -409,8 +419,8 @@ SH_trigger_daemon () if (NULL != mhd_task) { GNUNET_SCHEDULER_cancel (mhd_task); - mhd_task = NULL; - run_daemon (NULL); + mhd_task = GNUNET_SCHEDULER_add_now (&run_daemon, + NULL); } else { @@ -419,6 +429,16 @@ SH_trigger_daemon () } +/** + * Kick GNUnet Curl scheduler to begin curl interactions. + */ +void +SH_trigger_curl () +{ + GNUNET_CURL_gnunet_scheduler_reschedule (&rc); +} + + /** * Function that queries MHD's select sets and * starts the task waiting for them. diff --git a/src/sync/sync-httpd.h b/src/sync/sync-httpd.h index a7279d5..989cd93 100644 --- a/src/sync/sync-httpd.h +++ b/src/sync/sync-httpd.h @@ -162,4 +162,11 @@ void SH_trigger_daemon (void); +/** + * Kick GNUnet Curl scheduler to begin curl interactions. + */ +void +SH_trigger_curl (void); + + #endif diff --git a/src/sync/sync-httpd_backup.c b/src/sync/sync-httpd_backup.c index d74f722..8f5facc 100644 --- a/src/sync/sync-httpd_backup.c +++ b/src/sync/sync-httpd_backup.c @@ -45,6 +45,12 @@ sync_handler_backup_get (struct MHD_Connection *connection, &backup_hash); switch (qs) { + case SYNC_DB_OLD_BACKUP_MISSING: + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "unexpected return status (backup missing)"); case SYNC_DB_OLD_BACKUP_MISSMATCH: GNUNET_break (0); return TALER_MHD_reply_with_error (connection, @@ -170,6 +176,12 @@ SH_return_backup (struct MHD_Connection *connection, &backup); switch (qs) { + case SYNC_DB_OLD_BACKUP_MISSING: + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "unexpected return status (backup missing)"); case SYNC_DB_OLD_BACKUP_MISSMATCH: GNUNET_break (0); return TALER_MHD_reply_with_error (connection, diff --git a/src/sync/sync-httpd_backup_post.c b/src/sync/sync-httpd_backup_post.c index 8bce0a6..8137910 100644 --- a/src/sync/sync-httpd_backup_post.c +++ b/src/sync/sync-httpd_backup_post.c @@ -268,7 +268,35 @@ proposal_cb (void *cls, GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Resuming connection with order `%s'\n", + order_id); MHD_resume_connection (bc->con); + SH_trigger_daemon (); + if (MHD_HTTP_OK != http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Backend returned status %u/%u\n", + http_status, + (unsigned int) ec); + GNUNET_break (0); + bc->resp = TALER_MHD_make_json_pack ("{s:I, s:s, s:I, s:I}", + "code", + (json_int_t) + TALER_EC_SYNC_PAYMENT_CREATE_BACKEND_ERROR, + "hint", + "Failed to setup order with merchant backend", + "backend-ec", (json_int_t) ec, + "backend-http-status", + (json_int_t) http_status); + GNUNET_assert (NULL != bc->resp); + fprintf (stderr, "SET: %p - %p\n", bc, (NULL != bc) ? bc->resp : NULL); + bc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Storing payment request for order %s\n", + order_id); qs = db->store_payment_TR (db->cls, &bc->account, order_id, @@ -278,6 +306,7 @@ proposal_cb (void *cls, GNUNET_break (0); bc->resp = TALER_MHD_make_error (TALER_EC_SYNC_PAYMENT_CREATE_DB_ERROR, "Failed to persist payment request in sync database"); + GNUNET_assert (NULL != bc->resp); bc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; return; } @@ -285,6 +314,7 @@ proposal_cb (void *cls, "Obtained fresh order `%s'\n", order_id); bc->resp = make_payment_request (order_id); + GNUNET_assert (NULL != bc->resp); bc->response_code = MHD_HTTP_PAYMENT_REQUIRED; } @@ -353,6 +383,7 @@ check_payment_cb (void *cls, "Payment status checked: %s\n", paid ? "paid" : "unpaid"); MHD_resume_connection (bc->con); + SH_trigger_daemon (); GNUNET_break ( (GNUNET_NO == refunded) && (NULL == refund_amount) ); if (paid) @@ -368,6 +399,7 @@ check_payment_cb (void *cls, GNUNET_break (0); bc->resp = TALER_MHD_make_error (TALER_EC_SYNC_PAYMENT_CONFIRM_DB_ERROR, "Failed to persist payment confirmation in sync database"); + GNUNET_assert (NULL != bc->resp); bc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; return; /* continue as planned */ } @@ -377,6 +409,7 @@ check_payment_cb (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Repeating payment request\n"); bc->resp = make_payment_request (bc->existing_order_id); + GNUNET_assert (NULL != bc->resp); bc->response_code = MHD_HTTP_PAYMENT_REQUIRED; return; } @@ -384,6 +417,7 @@ check_payment_cb (void *cls, "Timeout waiting for payment\n"); bc->resp = TALER_MHD_make_error (TALER_EC_SYNC_PAYMENT_TIMEOUT, "Timeout awaiting promised payment"); + GNUNET_assert (NULL != bc->resp); bc->response_code = MHD_HTTP_REQUEST_TIMEOUT; } @@ -413,6 +447,7 @@ await_payment (struct BackupContext *bc, timeout, &check_payment_cb, bc); + SH_trigger_curl (); } @@ -466,7 +501,8 @@ begin_payment (struct BackupContext *bc, bc_tail, bc); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Suspending connection while creating order...\n"); + "Suspending connection while creating order at `%s'\n", + SH_backend_url); MHD_suspend_connection (bc->con); order = json_pack ("{s:o, s:s, s:s}", "amount", TALER_JSON_from_amount (&SH_annual_fee), @@ -477,6 +513,7 @@ begin_payment (struct BackupContext *bc, order, &proposal_cb, bc); + SH_trigger_curl (); json_decref (order); return MHD_YES; } @@ -497,6 +534,13 @@ handle_database_error (struct BackupContext *bc, { switch (qs) { + case SYNC_DB_OLD_BACKUP_MISSING: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Update failed: no existing backup\n"); + return TALER_MHD_reply_with_error (bc->con, + MHD_HTTP_NOT_FOUND, + TALER_EC_SYNC_PREVIOUS_BACKUP_UNKNOWN, + "Cannot update, no existing backup known"); case SYNC_DB_OLD_BACKUP_MISSMATCH: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Conflict detected, returning existing backup\n"); @@ -565,6 +609,7 @@ sync_handler_backup_post (struct MHD_Connection *connection, struct BackupContext *bc; bc = *con_cls; + fprintf (stderr, "%p - %p\n", bc, (NULL != bc) ? bc->resp : NULL); if (NULL == bc) { /* first call, setup internals */ @@ -764,9 +809,12 @@ sync_handler_backup_post (struct MHD_Connection *connection, return MHD_YES; } /* handle upload */ - if (0 != upload_data_size) + if (0 != *upload_data_size) { /* check MHD invariant */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Processing %u bytes of upload data\n", + (unsigned int) *upload_data_size); GNUNET_assert (bc->upload_off + *upload_data_size <= bc->upload_size); memcpy (&bc->upload[bc->upload_off], upload_data, @@ -783,10 +831,15 @@ sync_handler_backup_post (struct MHD_Connection *connection, int ret; /* We generated a response asynchronously, queue that */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Returning asynchronously generated response with HTTP status %u\n", + bc->response_code); ret = MHD_queue_response (connection, bc->response_code, bc->resp); GNUNET_break (MHD_YES == ret); + MHD_destroy_response (bc->resp); + bc->resp = NULL; return ret; } @@ -812,14 +865,21 @@ sync_handler_backup_post (struct MHD_Connection *connection, { enum SYNC_DB_QueryStatus qs; - if (GNUNET_is_zero (&bc->old_backup_hash)) + if (0 == GNUNET_is_zero (&bc->old_backup_hash)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Uploading first backup to account\n"); qs = db->store_backup_TR (db->cls, account, &bc->account_sig, &bc->new_backup_hash, bc->upload_size, bc->upload); + } else + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Uploading existing backup of account\n"); qs = db->update_backup_TR (db->cls, account, &bc->old_backup_hash, @@ -827,6 +887,7 @@ sync_handler_backup_post (struct MHD_Connection *connection, &bc->new_backup_hash, bc->upload_size, bc->upload); + } if (qs < 0) return handle_database_error (bc, qs); diff --git a/src/syncdb/plugin_syncdb_postgres.c b/src/syncdb/plugin_syncdb_postgres.c index 475109f..61b192c 100644 --- a/src/syncdb/plugin_syncdb_postgres.c +++ b/src/syncdb/plugin_syncdb_postgres.c @@ -616,7 +616,7 @@ postgres_update_backup (void *cls, return SYNC_DB_SOFT_ERROR; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break (0); - return SYNC_DB_NO_RESULTS; + return SYNC_DB_OLD_BACKUP_MISSING; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: return SYNC_DB_ONE_RESULT; case GNUNET_DB_STATUS_HARD_ERROR: -- cgit v1.2.3