diff --git a/lib/hash.c b/lib/hash.c index 772c03b5ca081d..a26ce1d04252e5 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -40,7 +40,10 @@ hash_element_dtor(void *user, void *element) struct Curl_hash_element *e = (struct Curl_hash_element *) element; if(e->ptr) { - h->dtor(e->ptr); + if(e->dtor) + e->dtor(e->key, e->key_len, e->ptr); + else + h->dtor(e->ptr); e->ptr = NULL; } @@ -77,7 +80,8 @@ Curl_hash_init(struct Curl_hash *h, } static struct Curl_hash_element * -mk_hash_element(const void *key, size_t key_len, const void *p) +mk_hash_element(const void *key, size_t key_len, const void *p, + Curl_hash_elem_dtor dtor) { /* allocate the struct plus memory after it to store the key */ struct Curl_hash_element *he = malloc(sizeof(struct Curl_hash_element) + @@ -87,22 +91,15 @@ mk_hash_element(const void *key, size_t key_len, const void *p) memcpy(he->key, key, key_len); he->key_len = key_len; he->ptr = (void *) p; + he->dtor = dtor; } return he; } #define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)] -/* Insert the data in the hash. If there already was a match in the hash, that - * data is replaced. This function also "lazily" allocates the table if - * needed, as it isn't done in the _init function (anymore). - * - * @unittest: 1305 - * @unittest: 1602 - * @unittest: 1603 - */ -void * -Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) +void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p, + Curl_hash_elem_dtor dtor) { struct Curl_hash_element *he; struct Curl_llist_element *le; @@ -130,7 +127,7 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) } } - he = mk_hash_element(key, key_len, p); + he = mk_hash_element(key, key_len, p, dtor); if(he) { Curl_llist_append(l, he, &he->list); ++h->size; @@ -140,6 +137,20 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) return NULL; /* failure */ } +/* Insert the data in the hash. If there already was a match in the hash, that + * data is replaced. This function also "lazily" allocates the table if + * needed, as it isn't done in the _init function (anymore). + * + * @unittest: 1305 + * @unittest: 1602 + * @unittest: 1603 + */ +void * +Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) +{ + return Curl_hash_add2(h, key, key_len, p, NULL); +} + /* Remove the identified hash entry. * Returns non-zero on failure. * diff --git a/lib/hash.h b/lib/hash.h index 9cfffc25b08a8f..b1f7c381f54dbf 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -58,9 +58,12 @@ struct Curl_hash { size_t size; }; +typedef void (*Curl_hash_elem_dtor)(void *key, size_t key_len, void *p); + struct Curl_hash_element { struct Curl_llist_element list; void *ptr; + Curl_hash_elem_dtor dtor; size_t key_len; char key[1]; /* allocated memory following the struct */ }; @@ -78,6 +81,8 @@ void Curl_hash_init(struct Curl_hash *h, Curl_hash_dtor dtor); void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p); +void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p, + Curl_hash_elem_dtor dtor); int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len); void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len); void Curl_hash_apply(struct Curl_hash *h, void *user, diff --git a/lib/multi.c b/lib/multi.c index 55c6dfc8b9e493..0f4763d26ab853 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -366,6 +366,17 @@ static void sh_init(struct Curl_hash *hash, int hashsize) sh_freeentry); } +/* multi->proto_hash destructor. Should never be called as elements + * MUST be added with their own destructor */ +static void ph_freeentry(void *p) +{ + (void)p; + /* Will always be FALSE. Cannot use a 0 assert here since compilers + * are not in agreement if they then want a NORETURN attribute or + * not. *sigh* */ + DEBUGASSERT(p == NULL); +} + /* * multi_addmsg() * @@ -392,6 +403,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ sh_init(&multi->sockhash, hashsize); + Curl_hash_init(&multi->proto_hash, 23, + Curl_hash_str, Curl_str_key_compare, ph_freeentry); + if(Curl_conncache_init(&multi->conn_cache, chashsize)) goto error; @@ -427,6 +441,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ error: sockhash_destroy(&multi->sockhash); + Curl_hash_destroy(&multi->proto_hash); Curl_hash_destroy(&multi->hostcache); Curl_conncache_destroy(&multi->conn_cache); free(multi); @@ -2848,6 +2863,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_conncache_close_all_connections(&multi->conn_cache); sockhash_destroy(&multi->sockhash); + Curl_hash_destroy(&multi->proto_hash); Curl_conncache_destroy(&multi->conn_cache); Curl_hash_destroy(&multi->hostcache); Curl_psl_destroy(&multi->psl); @@ -2861,10 +2877,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) #endif #endif -#ifdef USE_SSL - Curl_free_multi_ssl_backend_data(multi->ssl_backend_data); -#endif - multi_xfer_bufs_free(multi); free(multi); diff --git a/lib/multihandle.h b/lib/multihandle.h index 122f8f6a7cb812..fedd30c8b208d2 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -79,10 +79,6 @@ typedef enum { /* value for MAXIMUM CONCURRENT STREAMS upper limit */ #define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1) -/* Curl_multi SSL backend-specific data; declared differently by each SSL - backend */ -struct multi_ssl_backend_data; - /* This is the struct known as CURLM on the outside */ struct Curl_multi { /* First a simple identifier to easier detect if a user mix up @@ -131,14 +127,17 @@ struct Curl_multi { char *xfer_ulbuf; /* the actual buffer */ size_t xfer_ulbuf_len; /* the allocated length */ -#if defined(USE_SSL) - struct multi_ssl_backend_data *ssl_backend_data; -#endif - /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note the pluralis form, there can be more than one easy handle waiting on the same actual socket) */ struct Curl_hash sockhash; + /* `proto_hash` is a general key-value store for protocol implementations + * with the lifetime of the multi handle. The number of elements kept here + * should be in the order of supported protocols (and sub-protocols like + * TLS), *not* in the order of connections or current transfers! + * Elements need to be added with their own destructor to be invoked when + * the multi handle is cleaned up (see Curl_hash_add2()).*/ + struct Curl_hash proto_hash; /* Shared connection cache (bundles)*/ struct conncache conn_cache; diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index e9e2ce86cc654a..447a7719ee66b3 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -1219,7 +1219,6 @@ const struct Curl_ssl Curl_ssl_bearssl = { bearssl_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ bearssl_recv, /* recv decrypted data */ bearssl_send, /* send data to encrypt */ }; diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index bd9c6239d02b60..a92a522a5f1efa 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -1813,7 +1813,6 @@ const struct Curl_ssl Curl_ssl_gnutls = { gtls_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ gtls_recv, /* recv decrypted data */ gtls_send, /* send data to encrypt */ }; diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 4967beac369c01..eaef62e2ef3e18 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -1354,7 +1354,6 @@ const struct Curl_ssl Curl_ssl_mbedtls = { mbedtls_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ mbed_recv, /* recv decrypted data */ mbed_send, /* send data to encrypt */ }; diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 36a1eb5a41cd8b..06711309e08cda 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -298,14 +298,6 @@ typedef unsigned long sslerr_t; #define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) #endif /* !LIBRESSL_VERSION_NUMBER */ -#if defined(HAVE_SSL_X509_STORE_SHARE) -struct multi_ssl_backend_data { - char *CAfile; /* CAfile path used to generate X509 store */ - X509_STORE *store; /* cached X509 store or NULL if none */ - struct curltime time; /* when the cached store was created */ -}; -#endif /* HAVE_SSL_X509_STORE_SHARE */ - #define push_certinfo(_label, _num) \ do { \ long info_len = BIO_get_mem_data(mem, &ptr); \ @@ -3353,8 +3345,33 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, } #if defined(HAVE_SSL_X509_STORE_SHARE) -static bool cached_x509_store_expired(const struct Curl_easy *data, - const struct multi_ssl_backend_data *mb) + +/* key to use at `multi->proto_hash` */ +#define MPROTO_OSSL_X509_KEY "tls:ossl:x509:share" + +struct ossl_x509_share { + char *CAfile; /* CAfile path used to generate X509 store */ + X509_STORE *store; /* cached X509 store or NULL if none */ + struct curltime time; /* when the cached store was created */ +}; + +static void oss_x509_share_free(void *key, size_t key_len, void *p) +{ + struct ossl_x509_share *share = p; + DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY)-1)); + DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len)); + (void)key; + (void)key_len; + if(share->store) { + X509_STORE_free(share->store); + } + free(share->CAfile); + free(share); +} + +static bool +cached_x509_store_expired(const struct Curl_easy *data, + const struct ossl_x509_share *mb) { const struct ssl_general_config *cfg = &data->set.general_ssl; struct curltime now = Curl_now(); @@ -3367,9 +3384,9 @@ static bool cached_x509_store_expired(const struct Curl_easy *data, return elapsed_ms >= timeout_ms; } -static bool cached_x509_store_different( - struct Curl_cfilter *cf, - const struct multi_ssl_backend_data *mb) +static bool +cached_x509_store_different(struct Curl_cfilter *cf, + const struct ossl_x509_share *mb) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); if(!mb->CAfile || !conn_config->CAfile) @@ -3382,15 +3399,17 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, const struct Curl_easy *data) { struct Curl_multi *multi = data->multi; + struct ossl_x509_share *share; X509_STORE *store = NULL; DEBUGASSERT(multi); - if(multi && - multi->ssl_backend_data && - multi->ssl_backend_data->store && - !cached_x509_store_expired(data, multi->ssl_backend_data) && - !cached_x509_store_different(cf, multi->ssl_backend_data)) { - store = multi->ssl_backend_data->store; + share = multi? Curl_hash_pick(&multi->proto_hash, + (void *)MPROTO_OSSL_X509_KEY, + sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL; + if(share && share->store && + !cached_x509_store_expired(data, share) && + !cached_x509_store_different(cf, share)) { + store = share->store; } return store; @@ -3402,20 +3421,28 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_multi *multi = data->multi; - struct multi_ssl_backend_data *mbackend; + struct ossl_x509_share *share; DEBUGASSERT(multi); if(!multi) return; + share = Curl_hash_pick(&multi->proto_hash, + (void *)MPROTO_OSSL_X509_KEY, + sizeof(MPROTO_OSSL_X509_KEY)-1); - if(!multi->ssl_backend_data) { - multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data)); - if(!multi->ssl_backend_data) + if(!share) { + share = calloc(1, sizeof(*share)); + if(!share) + return; + if(!Curl_hash_add2(&multi->proto_hash, + (void *)MPROTO_OSSL_X509_KEY, + sizeof(MPROTO_OSSL_X509_KEY)-1, + share, oss_x509_share_free)) { + free(share); return; + } } - mbackend = multi->ssl_backend_data; - if(X509_STORE_up_ref(store)) { char *CAfile = NULL; @@ -3427,14 +3454,14 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, } } - if(mbackend->store) { - X509_STORE_free(mbackend->store); - free(mbackend->CAfile); + if(share->store) { + X509_STORE_free(share->store); + free(share->CAfile); } - mbackend->time = Curl_now(); - mbackend->store = store; - mbackend->CAfile = CAfile; + share->time = Curl_now(); + share->store = store; + share->CAfile = CAfile; } } @@ -4961,20 +4988,6 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl, (void *)octx->ssl_ctx : (void *)octx->ssl; } -static void ossl_free_multi_ssl_backend_data( - struct multi_ssl_backend_data *mbackend) -{ -#if defined(HAVE_SSL_X509_STORE_SHARE) - if(mbackend->store) { - X509_STORE_free(mbackend->store); - } - free(mbackend->CAfile); - free(mbackend); -#else /* HAVE_SSL_X509_STORE_SHARE */ - (void)mbackend; -#endif /* HAVE_SSL_X509_STORE_SHARE */ -} - const struct Curl_ssl Curl_ssl_openssl = { { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ @@ -5016,7 +5029,6 @@ const struct Curl_ssl Curl_ssl_openssl = { #endif NULL, /* use of data in this connection */ NULL, /* remote of data from this connection */ - ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */ ossl_recv, /* recv decrypted data */ ossl_send, /* send data to encrypt */ }; diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index ceb26c5bd95102..c5de4703471871 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -751,7 +751,6 @@ const struct Curl_ssl Curl_ssl_rustls = { NULL, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ cr_recv, /* recv decrypted data */ cr_send, /* send data to encrypt */ }; diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index cec7fa9710278c..6916f80a7f0cb2 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -2757,7 +2757,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_multi *multi = data->multi; const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - struct schannel_multi_ssl_backend_data *mbackend; + struct schannel_cert_share *share; const struct ssl_general_config *cfg = &data->set.general_ssl; timediff_t timeout_ms; timediff_t elapsed_ms; @@ -2766,12 +2766,14 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, DEBUGASSERT(multi); - if(!multi || !multi->ssl_backend_data) { + if(!multi) { return NULL; } - mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; - if(!mbackend->cert_store) { + share = Curl_hash_pick(&multi->proto_hash, + (void *)MPROTO_SCHANNEL_CERT_SHARE_KEY, + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); + if(!share || !share->cert_store) { return NULL; } @@ -2786,37 +2788,52 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; if(timeout_ms >= 0) { now = Curl_now(); - elapsed_ms = Curl_timediff(now, mbackend->time); + elapsed_ms = Curl_timediff(now, share->time); if(elapsed_ms >= timeout_ms) { return NULL; } } if(ca_info_blob) { - if(!mbackend->CAinfo_blob_digest) { + if(!share->CAinfo_blob_digest) { return NULL; } - if(mbackend->CAinfo_blob_size != ca_info_blob->len) { + if(share->CAinfo_blob_size != ca_info_blob->len) { return NULL; } schannel_sha256sum((const unsigned char *)ca_info_blob->data, ca_info_blob->len, info_blob_digest, CURL_SHA256_DIGEST_LENGTH); - if(memcmp(mbackend->CAinfo_blob_digest, + if(memcmp(share->CAinfo_blob_digest, info_blob_digest, CURL_SHA256_DIGEST_LENGTH)) { return NULL; } } else { - if(!conn_config->CAfile || !mbackend->CAfile || - strcmp(mbackend->CAfile, conn_config->CAfile)) { + if(!conn_config->CAfile || !share->CAfile || + strcmp(share->CAfile, conn_config->CAfile)) { return NULL; } } - return mbackend->cert_store; + return share->cert_store; +} + +static void schannel_cert_share_free(void *key, size_t key_len, void *p) +{ + struct schannel_cert_share *share = p; + DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1)); + DEBUGASSERT(!memcmp(MPROTO_SCHANNEL_CERT_SHARE_KEY, key, key_len)); + (void)key; + (void)key_len; + if(share->cert_store) { + CertCloseStore(share->cert_store, 0); + } + free(share->CAinfo_blob_digest); + free(share->CAfile); + free(share); } bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, @@ -2826,7 +2843,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_multi *multi = data->multi; const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - struct schannel_multi_ssl_backend_data *mbackend; + struct schannel_cert_share *share; unsigned char *CAinfo_blob_digest = NULL; size_t CAinfo_blob_size = 0; char *CAfile = NULL; @@ -2837,17 +2854,23 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, return false; } - if(!multi->ssl_backend_data) { - multi->ssl_backend_data = - calloc(1, sizeof(struct schannel_multi_ssl_backend_data)); - if(!multi->ssl_backend_data) { + share = Curl_hash_pick(&multi->proto_hash, + (void *)MPROTO_SCHANNEL_CERT_SHARE_KEY, + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); + if(!share) { + share = calloc(1, sizeof(*share)); + if(!share) { + return false; + } + if(!Curl_hash_add2(&multi->proto_hash, + (void *)MPROTO_SCHANNEL_CERT_SHARE_KEY, + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1, + share, schannel_cert_share_free)) { + free(share); return false; } } - mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; - - if(ca_info_blob) { CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH); if(!CAinfo_blob_digest) { @@ -2869,33 +2892,20 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, } /* free old cache data */ - if(mbackend->cert_store) { - CertCloseStore(mbackend->cert_store, 0); + if(share->cert_store) { + CertCloseStore(share->cert_store, 0); } - free(mbackend->CAinfo_blob_digest); - free(mbackend->CAfile); + free(share->CAinfo_blob_digest); + free(share->CAfile); - mbackend->time = Curl_now(); - mbackend->cert_store = cert_store; - mbackend->CAinfo_blob_digest = CAinfo_blob_digest; - mbackend->CAinfo_blob_size = CAinfo_blob_size; - mbackend->CAfile = CAfile; + share->time = Curl_now(); + share->cert_store = cert_store; + share->CAinfo_blob_digest = CAinfo_blob_digest; + share->CAinfo_blob_size = CAinfo_blob_size; + share->CAfile = CAfile; return true; } -static void schannel_free_multi_ssl_backend_data( - struct multi_ssl_backend_data *msbd) -{ - struct schannel_multi_ssl_backend_data *mbackend = - (struct schannel_multi_ssl_backend_data*)msbd; - if(mbackend->cert_store) { - CertCloseStore(mbackend->cert_store, 0); - } - free(mbackend->CAinfo_blob_digest); - free(mbackend->CAfile); - free(mbackend); -} - const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ @@ -2931,7 +2941,6 @@ const struct Curl_ssl Curl_ssl_schannel = { schannel_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */ schannel_recv, /* recv decrypted data */ schannel_send, /* send data to encrypt */ }; diff --git a/lib/vtls/schannel_int.h b/lib/vtls/schannel_int.h index 5e233a9d05bf9c..af29b67de0088f 100644 --- a/lib/vtls/schannel_int.h +++ b/lib/vtls/schannel_int.h @@ -159,7 +159,10 @@ struct schannel_ssl_backend_data { #endif }; -struct schannel_multi_ssl_backend_data { +/* key to use at `multi->proto_hash` */ +#define MPROTO_SCHANNEL_CERT_SHARE_KEY "tls:schannel:cert:share" + +struct schannel_cert_share { unsigned char *CAinfo_blob_digest; /* CA info blob digest */ size_t CAinfo_blob_size; /* CA info blob size */ char *CAfile; /* CAfile path used to generate diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c index b7fc7c02224cae..aaf26ff3fc2865 100644 --- a/lib/vtls/sectransp.c +++ b/lib/vtls/sectransp.c @@ -3477,7 +3477,6 @@ const struct Curl_ssl Curl_ssl_sectransp = { sectransp_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ sectransp_recv, /* recv decrypted data */ sectransp_send, /* send data to encrypt */ }; diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 28d15953905f37..ed282928617724 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -744,12 +744,6 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf, return CURLE_OK; } -void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend) -{ - if(Curl_ssl->free_multi_ssl_backend_data && mbackend) - Curl_ssl->free_multi_ssl_backend_data(mbackend); -} - void Curl_ssl_close_all(struct Curl_easy *data) { /* kill the session ID cache if not shared */ @@ -1331,7 +1325,6 @@ static const struct Curl_ssl Curl_ssl_multi = { NULL, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ multissl_recv_plain, /* recv decrypted data */ multissl_send_plain, /* send data to encrypt */ }; diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index cd7eeeca174631..67e6937ef4718e 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -51,7 +51,6 @@ struct Curl_ssl_session; /* Curl_multi SSL backend-specific data; declared differently by each SSL backend */ -struct multi_ssl_backend_data; struct Curl_cfilter; CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, @@ -180,8 +179,6 @@ bool Curl_ssl_cert_status_request(void); bool Curl_ssl_false_start(struct Curl_easy *data); -void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend); - #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data, diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h index 8aca1d33311648..3750419b47f372 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -136,8 +136,6 @@ struct Curl_ssl { bool (*attach_data)(struct Curl_cfilter *cf, struct Curl_easy *data); void (*detach_data)(struct Curl_cfilter *cf, struct Curl_easy *data); - void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend); - ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, CURLcode *code); ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 48cf132a378ec3..67e1a3a96a742e 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -1421,7 +1421,6 @@ const struct Curl_ssl Curl_ssl_wolfssl = { wolfssl_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - NULL, /* free_multi_ssl_backend_data */ wolfssl_recv, /* recv decrypted data */ wolfssl_send, /* send data to encrypt */ }; diff --git a/tests/unit/unit1603.c b/tests/unit/unit1603.c index 004fdbccbaa2c1..76e25aca5ceef5 100644 --- a/tests/unit/unit1603.c +++ b/tests/unit/unit1603.c @@ -39,6 +39,16 @@ static void mydtor(void *p) (void)p; /* unused */ } +static size_t elem_dtor_calls; + +static void my_elem_dtor(void *key, size_t key_len, void *p) +{ + (void)p; /* unused */ + (void)key; /* unused */ + (void)key_len; /* unused */ + ++elem_dtor_calls; +} + static CURLcode unit_setup(void) { Curl_hash_init(&hash_static, slots, Curl_hash_str, @@ -147,6 +157,22 @@ UNITTEST_START nodep = Curl_hash_pick(&hash_static, &key3, strlen(key3)); fail_unless(nodep == key3, "hash retrieval failed"); + /* Add element with own destructor */ + nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1, + my_elem_dtor); + fail_unless(nodep, "add2 insertion into hash failed"); + fail_unless(elem_dtor_calls == 0, "element destructor count should be 0"); + /* Add it again, should invoke destructor on first */ + nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1, + my_elem_dtor); + fail_unless(nodep, "add2 again, insertion into hash failed"); + fail_unless(elem_dtor_calls == 1, "element destructor count should be 1"); + /* remove, should invoke destructor */ + rc = Curl_hash_delete(&hash_static, &key1, strlen(key1)); + fail_unless(rc == 0, "hash delete failed"); + fail_unless(elem_dtor_calls == 2, "element destructor count should be 1"); + + /* Clean up */ Curl_hash_clean(&hash_static);