time-keeping: keep timestamp in multi, always update

Always use curlx_now() when calling Curl_pgrs_now(data). Tests with the
"manual" updates to now proved differ more then 100ms in parallel testing.

Add `curlx_nowp()` to set current time into a struct curltime.
Add `curlx_ptimediff_ms() and friends, passing pointers.

Update documentation.

Closes #19998
This commit is contained in:
Stefan Eissing 2025-12-18 13:55:07 +01:00 committed by Daniel Stenberg
parent 308c347c8b
commit b4be1f271e
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
61 changed files with 471 additions and 502 deletions

View file

@ -412,7 +412,7 @@ CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
}
shared->refcount = 1;
shared->time = data->progress.now;
shared->time = *Curl_pgrs_now(data);
*pcreds = shared;
return CURLE_OK;
}
@ -559,11 +559,11 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
/* key to use at `multi->proto_hash` */
#define MPROTO_GTLS_X509_KEY "tls:gtls:x509:share"
static bool gtls_shared_creds_expired(const struct Curl_easy *data,
static bool gtls_shared_creds_expired(struct Curl_easy *data,
const struct gtls_shared_creds *sc)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, sc->time);
timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &sc->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms < 0)

View file

@ -53,6 +53,7 @@
#include "openssl.h"
#include "../connect.h"
#include "../slist.h"
#include "../progress.h"
#include "../select.h"
#include "../curlx/wait.h"
#include "vtls.h"
@ -3212,14 +3213,14 @@ static void oss_x509_share_free(void *key, size_t key_len, void *p)
curlx_free(share);
}
static bool ossl_cached_x509_store_expired(const struct Curl_easy *data,
static bool ossl_cached_x509_store_expired(struct Curl_easy *data,
const struct ossl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
if(cfg->ca_cache_timeout < 0)
return FALSE;
else {
timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, mb->time);
timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
return elapsed_ms >= timeout_ms;
@ -3241,7 +3242,7 @@ static bool ossl_cached_x509_store_different(struct Curl_cfilter *cf,
}
static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
struct Curl_easy *data,
bool *pempty)
{
struct Curl_multi *multi = data->multi;
@ -3264,7 +3265,7 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
}
static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
struct Curl_easy *data,
X509_STORE *store,
bool is_empty)
{
@ -3310,7 +3311,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
curlx_free(share->CAfile);
}
share->time = data->progress.now;
share->time = *Curl_pgrs_now(data);
share->store = store;
share->store_is_empty = is_empty;
share->CAfile = CAfile;

View file

@ -1722,7 +1722,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
connssl->connecting_state = ssl_connect_2;
memset(rs, 0, sizeof(*rs));
rs->io_need = CURL_SSL_IO_NEED_SEND;
rs->start_time = curlx_now();
rs->start_time = *Curl_pgrs_now(data);
rs->started = TRUE;
}
@ -1731,7 +1731,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
curl_socket_t readfd, writefd;
timediff_t elapsed;
elapsed = curlx_timediff_ms(curlx_now(), rs->start_time);
elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time);
if(elapsed >= MAX_RENEG_BLOCK_TIME) {
failf(data, "schannel: renegotiation timeout");
result = CURLE_SSL_CONNECT_ERROR;
@ -1797,7 +1797,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
if(result)
break;
elapsed = curlx_timediff_ms(curlx_now(), rs->start_time);
elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time);
if(elapsed >= MAX_RENEG_BLOCK_TIME) {
failf(data, "schannel: renegotiation timeout");
result = CURLE_SSL_CONNECT_ERROR;
@ -2723,7 +2723,7 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
}
HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
const struct Curl_easy *data)
struct Curl_easy *data)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
@ -2732,7 +2732,6 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
const struct ssl_general_config *cfg = &data->set.general_ssl;
timediff_t timeout_ms;
timediff_t elapsed_ms;
struct curltime now;
unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
DEBUGASSERT(multi);
@ -2758,8 +2757,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
negative timeout means retain forever. */
timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms >= 0) {
now = curlx_now();
elapsed_ms = curlx_timediff_ms(now, share->time);
elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &share->time);
if(elapsed_ms >= timeout_ms) {
return NULL;
}
@ -2803,7 +2801,7 @@ static void schannel_cert_share_free(void *key, size_t key_len, void *p)
}
bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
struct Curl_easy *data,
HCERTSTORE cert_store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);

View file

@ -158,10 +158,10 @@ struct num_ip_data {
};
HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
const struct Curl_easy *data);
struct Curl_easy *data);
bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
struct Curl_easy *data,
HCERTSTORE cert_store);
#endif /* USE_SCHANNEL */

View file

@ -1371,8 +1371,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
if(!result && *done) {
cf->connected = TRUE;
if(connssl->state == ssl_connection_complete) {
Curl_pgrs_now_set(data);
connssl->handshake_done = data->progress.now;
connssl->handshake_done = *Curl_pgrs_now(data);
}
/* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete ||

View file

@ -723,11 +723,11 @@ static void wssl_x509_share_free(void *key, size_t key_len, void *p)
curlx_free(share);
}
static bool wssl_cached_x509_store_expired(const struct Curl_easy *data,
static bool wssl_cached_x509_store_expired(struct Curl_easy *data,
const struct wssl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, mb->time);
timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms < 0)
@ -747,7 +747,7 @@ static bool wssl_cached_x509_store_different(struct Curl_cfilter *cf,
}
static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
const struct Curl_easy *data)
struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct wssl_x509_share *share;
@ -767,7 +767,7 @@ static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
}
static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
struct Curl_easy *data,
WOLFSSL_X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
@ -810,7 +810,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
curlx_free(share->CAfile);
}
share->time = data->progress.now;
share->time = *Curl_pgrs_now(data);
share->store = store;
share->CAfile = CAfile;
}