commit a90483affc1af150a8cea6cde4195b8843dafd34
parent 93f42dd13e38027396690eec8973641d573b4e2e
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 8 Apr 2025 13:00:36 +0200
add retries on soft failures
Diffstat:
5 files changed, 178 insertions(+), 105 deletions(-)
diff --git a/src/challenger/challenger-httpd_authorize.c b/src/challenger/challenger-httpd_authorize.c
@@ -28,6 +28,11 @@
#include "challenger_cm_enums.h"
/**
+ * Maximum number of retries for the database interaction.
+ */
+#define MAX_RETRIES 3
+
+/**
* Generate error reply in the format requested by
* the client.
*
@@ -212,46 +217,57 @@ CH_handler_authorize (struct CH_HandlerContext *hc,
/* authorize_start will return 0 if a 'redirect_uri' was
configured for the client and this one differs. */
- qs = CH_db->authorize_start (CH_db->cls,
- &nonce,
- client_id,
- scope,
- state,
- redirect_uri,
- code_challenge,
- (uint32_t) code_challenge_method_enum,
- &last_address,
- &address_attempts_left,
- &pin_transmissions_left,
- &auth_attempts_left,
- &solved,
- &last_tx_time);
- switch (qs)
+ for (unsigned int r = 0; r<MAX_RETRIES; r++)
{
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return reply_error (
- hc,
- "internal-error",
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "authorize_start");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to find authorization process of client %llu for nonce `%s'\n",
- client_id,
- hc->path);
- return reply_error (
- hc,
- "validation-unknown",
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ qs = CH_db->authorize_start (CH_db->cls,
+ &nonce,
+ client_id,
+ scope,
+ state,
+ redirect_uri,
+ code_challenge,
+ (uint32_t) code_challenge_method_enum,
+ &last_address,
+ &address_attempts_left,
+ &pin_transmissions_left,
+ &auth_attempts_left,
+ &solved,
+ &last_tx_time);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return reply_error (
+ hc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "authorize_start");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (r < MAX_RETRIES - 1)
+ continue;
+ GNUNET_break (0);
+ return reply_error (
+ hc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "authorize_start");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to find authorization process of client %llu for nonce `%s'\n",
+ client_id,
+ hc->path);
+ return reply_error (
+ hc,
+ "validation-unknown",
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
break;
}
if (0 == CH_get_output_type (hc->connection))
diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c
@@ -28,6 +28,10 @@
#include <taler/taler_signatures.h>
#include "challenger-httpd_common.h"
+/**
+ * Maximum number of retries for the database interaction.
+ */
+#define MAX_RETRIES 3
/**
* Context for a /challenge operation.
@@ -687,42 +691,52 @@ CH_handler_challenge (struct CH_HandlerContext *hc,
}
if (! bc->db_finished)
{
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_assert (NULL == bc->client_redirect_uri);
- qs = CH_db->challenge_set_address_and_pin (
- CH_db->cls,
- &bc->nonce,
- bc->address,
- CH_validation_duration,
- &bc->tan,
- &bc->state,
- &bc->last_tx_time,
- &bc->pin_attempts_left,
- &bc->retransmit,
- &bc->client_redirect_uri,
- &bc->address_refused,
- &bc->solved);
- switch (qs)
+ for (unsigned int r = 0; r < MAX_RETRIES; r++)
{
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return reply_error (bc,
- "internal-error",
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "set-address-and-pin");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break_op (0);
- return reply_error (bc,
- "validation-unknown",
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (NULL == bc->client_redirect_uri);
+ qs = CH_db->challenge_set_address_and_pin (
+ CH_db->cls,
+ &bc->nonce,
+ bc->address,
+ CH_validation_duration,
+ &bc->tan,
+ &bc->state,
+ &bc->last_tx_time,
+ &bc->pin_attempts_left,
+ &bc->retransmit,
+ &bc->client_redirect_uri,
+ &bc->address_refused,
+ &bc->solved);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return reply_error (bc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "set-address-and-pin");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (r < MAX_RETRIES - 1)
+ continue;
+ GNUNET_break (0);
+ return reply_error (bc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "set-address-and-pin");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break_op (0);
+ return reply_error (bc,
+ "validation-unknown",
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
break;
}
bc->db_finished = true;
diff --git a/src/challenger/challenger-httpd_info.c b/src/challenger/challenger-httpd_info.c
@@ -30,6 +30,11 @@
#define BEARER_PREFIX "Bearer "
+/**
+ * Maximum number of retries for the database interaction.
+ */
+#define MAX_RETRIES 3
+
MHD_RESULT
CH_handler_info (struct CH_HandlerContext *hc,
const char *upload_data,
@@ -78,6 +83,7 @@ CH_handler_info (struct CH_HandlerContext *hc,
}
/* Check token is valid */
+ for (unsigned int r = 0; r<MAX_RETRIES; r++)
{
uint64_t id;
json_t *address;
@@ -98,8 +104,13 @@ CH_handler_info (struct CH_HandlerContext *hc,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"info_get_token");
case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (r < MAX_RETRIES - 1)
+ continue;
GNUNET_break (0);
- return MHD_NO;
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "info_get_token");
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
return TALER_MHD_reply_with_error (hc->connection,
MHD_HTTP_NOT_FOUND,
@@ -120,4 +131,6 @@ CH_handler_info (struct CH_HandlerContext *hc,
GNUNET_JSON_pack_timestamp ("expires",
address_expiration));
}
+ GNUNET_assert (0);
+ return MHD_NO;
}
diff --git a/src/challenger/challenger-httpd_setup.c b/src/challenger/challenger-httpd_setup.c
@@ -24,6 +24,11 @@
#include "challenger-httpd_setup.h"
#include "challenger-httpd_common.h"
+/**
+ * Maximum number of retries for the database interaction.
+ */
+#define MAX_RETRIES 3
+
struct SetupContext
{
@@ -134,6 +139,7 @@ CH_handler_setup (struct CH_HandlerContext *hc,
MHD_HTTP_HEADER_AUTHORIZATION);
}
+ for (unsigned int r = 0; r<MAX_RETRIES; r++)
{
enum GNUNET_DB_QueryStatus qs;
char *client_url = NULL;
@@ -146,7 +152,14 @@ CH_handler_setup (struct CH_HandlerContext *hc,
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (hc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (r < MAX_RETRIES - 1)
+ continue;
GNUNET_break (0);
return TALER_MHD_reply_with_error (hc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -161,6 +174,7 @@ CH_handler_setup (struct CH_HandlerContext *hc,
break;
}
GNUNET_free (client_url);
+ break;
}
{
diff --git a/src/challenger/challenger-httpd_solve.c b/src/challenger/challenger-httpd_solve.c
@@ -27,6 +27,10 @@
#include <taler/taler_templating_lib.h>
#include <taler/taler_signatures.h>
+/**
+ * Maximum number of retries for the database interaction.
+ */
+#define MAX_RETRIES 3
/**
* Context for a /solve operation.
@@ -265,37 +269,49 @@ CH_handler_solve (struct CH_HandlerContext *hc,
"pin");
}
- qs = CH_db->validate_solve_pin (CH_db->cls,
- &bc->nonce,
- pin,
- &solved,
- &exhausted,
- &no_challenge,
- &bc->state,
- &bc->addr_left,
- &bc->auth_attempts_left,
- &bc->pin_transmissions_left,
- &bc->client_redirect_uri);
- switch (qs)
+ for (unsigned int r = 0; r<MAX_RETRIES; r++)
{
- case GNUNET_DB_STATUS_HARD_ERROR:
- return reply_error (
- bc,
- "internal-error",
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "validate_solve_pin");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return MHD_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- return reply_error (
- bc,
- "validation-unknown",
- MHD_HTTP_NOT_FOUND,
- TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ qs = CH_db->validate_solve_pin (CH_db->cls,
+ &bc->nonce,
+ pin,
+ &solved,
+ &exhausted,
+ &no_challenge,
+ &bc->state,
+ &bc->addr_left,
+ &bc->auth_attempts_left,
+ &bc->pin_transmissions_left,
+ &bc->client_redirect_uri);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return reply_error (
+ bc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "validate_solve_pin");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (r < MAX_RETRIES - 1)
+ continue;
+ GNUNET_break (0);
+ return reply_error (
+ bc,
+ "internal-error",
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "validate_solve_pin");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return reply_error (
+ bc,
+ "validation-unknown",
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
break;
}
if (! solved)