dynamic curl timeouts for /keys and /wire requests
This commit is contained in:
parent
2518da8f45
commit
8f887a215e
@ -68,27 +68,6 @@
|
|||||||
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
|
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
|
||||||
function, __FILE__, __LINE__, curl_easy_strerror (code));
|
function, __FILE__, __LINE__, curl_easy_strerror (code));
|
||||||
|
|
||||||
/**
|
|
||||||
* Stages of initialization for the `struct TALER_EXCHANGE_Handle`
|
|
||||||
*/
|
|
||||||
enum ExchangeHandleState
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Just allocated.
|
|
||||||
*/
|
|
||||||
MHS_INIT = 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtained the exchange's certification data and keys.
|
|
||||||
*/
|
|
||||||
MHS_CERT = 1,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Failed to initialize (fatal).
|
|
||||||
*/
|
|
||||||
MHS_FAILED = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for the request to get the /keys of a exchange.
|
* Data for the request to get the /keys of a exchange.
|
||||||
@ -145,83 +124,6 @@ struct TEAH_AuditorListEntry
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle to the exchange
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGE_Handle
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The context of this handle
|
|
||||||
*/
|
|
||||||
struct GNUNET_CURL_Context *ctx;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL of the exchange (i.e. "http://exchange.taler.net/")
|
|
||||||
*/
|
|
||||||
char *url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to call with the exchange's certification data,
|
|
||||||
* NULL if this has already been done.
|
|
||||||
*/
|
|
||||||
TALER_EXCHANGE_CertificationCallback cert_cb;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closure to pass to @e cert_cb.
|
|
||||||
*/
|
|
||||||
void *cert_cb_cls;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data for the request to get the /keys of a exchange,
|
|
||||||
* NULL once we are past stage #MHS_INIT.
|
|
||||||
*/
|
|
||||||
struct KeysRequest *kr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Task for retrying /keys request.
|
|
||||||
*/
|
|
||||||
struct GNUNET_SCHEDULER_Task *retry_task;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw key data of the exchange, only valid if
|
|
||||||
* @e handshake_complete is past stage #MHS_CERT.
|
|
||||||
*/
|
|
||||||
json_t *key_data_raw;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Head of DLL of auditors of this exchange.
|
|
||||||
*/
|
|
||||||
struct TEAH_AuditorListEntry *auditors_head;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tail of DLL of auditors of this exchange.
|
|
||||||
*/
|
|
||||||
struct TEAH_AuditorListEntry *auditors_tail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key data of the exchange, only valid if
|
|
||||||
* @e handshake_complete is past stage #MHS_CERT.
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGE_Keys key_data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retry /keys frequency.
|
|
||||||
*/
|
|
||||||
struct GNUNET_TIME_Relative retry_delay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When does @e key_data expire?
|
|
||||||
*/
|
|
||||||
struct GNUNET_TIME_Absolute key_data_expiration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stage of the exchange's initialization routines.
|
|
||||||
*/
|
|
||||||
enum ExchangeHandleState state;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* ***************** Internal /keys fetching ************* */
|
/* ***************** Internal /keys fetching ************* */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,6 +152,7 @@ struct KeysRequest
|
|||||||
*/
|
*/
|
||||||
struct GNUNET_TIME_Absolute expire;
|
struct GNUNET_TIME_Absolute expire;
|
||||||
|
|
||||||
|
struct GNUNET_SCHEDULER_Task *timeout_task;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1201,6 +1104,8 @@ keys_completed_cb (void *cls,
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
free_keys_request (kr);
|
free_keys_request (kr);
|
||||||
|
/* FIXME: Maybe we should only increment when we know it's a timeout? */
|
||||||
|
exchange->keys_error_count++;
|
||||||
exchange->kr = NULL;
|
exchange->kr = NULL;
|
||||||
GNUNET_assert (NULL == exchange->retry_task);
|
GNUNET_assert (NULL == exchange->retry_task);
|
||||||
exchange->retry_delay = EXCHANGE_LIB_BACKOFF (exchange->retry_delay);
|
exchange->retry_delay = EXCHANGE_LIB_BACKOFF (exchange->retry_delay);
|
||||||
@ -1209,6 +1114,7 @@ keys_completed_cb (void *cls,
|
|||||||
exchange);
|
exchange);
|
||||||
return;
|
return;
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
|
exchange->keys_error_count = 0;
|
||||||
if (NULL == j)
|
if (NULL == j)
|
||||||
{
|
{
|
||||||
response_code = 0;
|
response_code = 0;
|
||||||
@ -1290,6 +1196,8 @@ keys_completed_cb (void *cls,
|
|||||||
exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
|
exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
|
||||||
|
exchange->keys_error_count++;
|
||||||
hr.ec = TALER_JSON_get_error_code (j);
|
hr.ec = TALER_JSON_get_error_code (j);
|
||||||
hr.hint = TALER_JSON_get_error_hint (j);
|
hr.hint = TALER_JSON_get_error_hint (j);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
@ -1882,6 +1790,20 @@ TALER_EXCHANGE_connect (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the network timeout for the next request to /keys.
|
||||||
|
*
|
||||||
|
* @param exchange the exchange handle
|
||||||
|
* @returns the timeout in seconds (for use by CURL)
|
||||||
|
*/
|
||||||
|
static long
|
||||||
|
get_keys_timeout_seconds (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
|
{
|
||||||
|
return GNUNET_MIN (60,
|
||||||
|
5 + (1L << exchange->keys_error_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate download of /keys from the exchange.
|
* Initiate download of /keys from the exchange.
|
||||||
*
|
*
|
||||||
@ -1936,7 +1858,7 @@ request_keys (void *cls)
|
|||||||
GNUNET_break (CURLE_OK ==
|
GNUNET_break (CURLE_OK ==
|
||||||
curl_easy_setopt (eh,
|
curl_easy_setopt (eh,
|
||||||
CURLOPT_TIMEOUT,
|
CURLOPT_TIMEOUT,
|
||||||
(long) 300));
|
get_keys_timeout_seconds (exchange)));
|
||||||
GNUNET_assert (CURLE_OK ==
|
GNUNET_assert (CURLE_OK ==
|
||||||
curl_easy_setopt (eh,
|
curl_easy_setopt (eh,
|
||||||
CURLOPT_HEADERFUNCTION,
|
CURLOPT_HEADERFUNCTION,
|
||||||
|
@ -58,6 +58,118 @@ struct TEAH_AuditorInteractionEntry
|
|||||||
struct TALER_AUDITOR_DepositConfirmationHandle *dch;
|
struct TALER_AUDITOR_DepositConfirmationHandle *dch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stages of initialization for the `struct TALER_EXCHANGE_Handle`
|
||||||
|
*/
|
||||||
|
enum ExchangeHandleState
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Just allocated.
|
||||||
|
*/
|
||||||
|
MHS_INIT = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtained the exchange's certification data and keys.
|
||||||
|
*/
|
||||||
|
MHS_CERT = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Failed to initialize (fatal).
|
||||||
|
*/
|
||||||
|
MHS_FAILED = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to the exchange
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_Handle
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The context of this handle
|
||||||
|
*/
|
||||||
|
struct GNUNET_CURL_Context *ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of the exchange (i.e. "http://exchange.taler.net/")
|
||||||
|
*/
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to call with the exchange's certification data,
|
||||||
|
* NULL if this has already been done.
|
||||||
|
*/
|
||||||
|
TALER_EXCHANGE_CertificationCallback cert_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure to pass to @e cert_cb.
|
||||||
|
*/
|
||||||
|
void *cert_cb_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for the request to get the /keys of a exchange,
|
||||||
|
* NULL once we are past stage #MHS_INIT.
|
||||||
|
*/
|
||||||
|
struct KeysRequest *kr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task for retrying /keys request.
|
||||||
|
*/
|
||||||
|
struct GNUNET_SCHEDULER_Task *retry_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw key data of the exchange, only valid if
|
||||||
|
* @e handshake_complete is past stage #MHS_CERT.
|
||||||
|
*/
|
||||||
|
json_t *key_data_raw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Head of DLL of auditors of this exchange.
|
||||||
|
*/
|
||||||
|
struct TEAH_AuditorListEntry *auditors_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tail of DLL of auditors of this exchange.
|
||||||
|
*/
|
||||||
|
struct TEAH_AuditorListEntry *auditors_tail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key data of the exchange, only valid if
|
||||||
|
* @e handshake_complete is past stage #MHS_CERT.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_Keys key_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retry /keys frequency.
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Relative retry_delay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When does @e key_data expire?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute key_data_expiration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of subsequent failed requests to /keys.
|
||||||
|
*
|
||||||
|
* Used to compute the CURL timeout for the request.
|
||||||
|
*/
|
||||||
|
unsigned int keys_error_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of subsequent failed requests to /wire.
|
||||||
|
*
|
||||||
|
* Used to compute the CURL timeout for the request.
|
||||||
|
*/
|
||||||
|
unsigned int wire_error_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stage of the exchange's initialization routines.
|
||||||
|
*/
|
||||||
|
enum ExchangeHandleState state;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called for each auditor to give us a chance to possibly
|
* Function called for each auditor to give us a chance to possibly
|
||||||
@ -111,6 +223,15 @@ struct GNUNET_CURL_Context *
|
|||||||
TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h);
|
TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handle is ready to process requests.
|
||||||
|
*
|
||||||
|
* @param h the exchange handle to query
|
||||||
|
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the handle is ready to process requests.
|
* Check if the handle is ready to process requests.
|
||||||
*
|
*
|
||||||
|
@ -219,6 +219,8 @@ handle_wire_finished (void *cls,
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
|
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
|
||||||
|
/* FIXME: Maybe we should only increment when we know it's a timeout? */
|
||||||
|
wh->exchange->wire_error_count++;
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
{
|
{
|
||||||
@ -233,6 +235,8 @@ handle_wire_finished (void *cls,
|
|||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
wh->exchange->wire_error_count = 0;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (j,
|
GNUNET_JSON_parse (j,
|
||||||
spec,
|
spec,
|
||||||
@ -356,6 +360,8 @@ handle_wire_finished (void *cls,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* unexpected response code */
|
/* unexpected response code */
|
||||||
|
if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
|
||||||
|
wh->exchange->wire_error_count++;
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
hr.ec = TALER_JSON_get_error_code (j);
|
hr.ec = TALER_JSON_get_error_code (j);
|
||||||
hr.hint = TALER_JSON_get_error_hint (j);
|
hr.hint = TALER_JSON_get_error_hint (j);
|
||||||
@ -374,6 +380,20 @@ handle_wire_finished (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the network timeout for the next request to /wire.
|
||||||
|
*
|
||||||
|
* @param exchange the exchange handle
|
||||||
|
* @returns the timeout in seconds (for use by CURL)
|
||||||
|
*/
|
||||||
|
static long
|
||||||
|
get_wire_timeout_seconds (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
|
{
|
||||||
|
return GNUNET_MIN (60,
|
||||||
|
5 + (1L << exchange->wire_error_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain information about a exchange's wire instructions.
|
* Obtain information about a exchange's wire instructions.
|
||||||
* A exchange may provide wire instructions for creating
|
* A exchange may provide wire instructions for creating
|
||||||
@ -416,6 +436,10 @@ TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
wh->url = TEAH_path_to_url (exchange,
|
wh->url = TEAH_path_to_url (exchange,
|
||||||
"/wire");
|
"/wire");
|
||||||
eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
|
eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
|
||||||
|
GNUNET_break (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_TIMEOUT,
|
||||||
|
get_wire_timeout_seconds (wh->exchange)));
|
||||||
if (NULL == eh)
|
if (NULL == eh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
Loading…
Reference in New Issue
Block a user