From 86d1a677fd310d7d90d6f7545c02a4bd68e1d955 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Wed, 4 Jun 2025 09:49:23 +0300 Subject: libcurl: update to 8.14.0 --- libs/libcurl/src/multi_ev.c | 164 ++++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 74 deletions(-) (limited to 'libs/libcurl/src/multi_ev.c') diff --git a/libs/libcurl/src/multi_ev.c b/libs/libcurl/src/multi_ev.c index 541bc0a739..55fe3614d7 100644 --- a/libs/libcurl/src/multi_ev.c +++ b/libs/libcurl/src/multi_ev.c @@ -27,13 +27,17 @@ #include #include "urldata.h" +#include "url.h" #include "cfilters.h" #include "curl_trc.h" #include "multiif.h" -#include "timeval.h" +#include "curlx/timeval.h" #include "multi_ev.h" #include "select.h" -#include "warnless.h" +#include "uint-bset.h" +#include "uint-spbset.h" +#include "uint-table.h" +#include "curlx/warnless.h" #include "multihandle.h" #include "socks.h" /* The last 3 #include files should be in this order */ @@ -47,15 +51,14 @@ static void mev_in_callback(struct Curl_multi *multi, bool value) multi->in_callback = value; } -#define CURL_MEV_XFER_HASH_SIZE 13 #define CURL_MEV_CONN_HASH_SIZE 3 /* Information about a socket for which we inform the libcurl application * what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE) */ struct mev_sh_entry { - struct Curl_hash_offt xfers; /* hash of transfers using this socket */ - struct Curl_hash_offt conns; /* hash of connections using this socket */ + struct uint_spbset xfers; /* bitset of transfers `mid`s on this socket */ + struct connectdata *conn; /* connection using this socket or NULL */ void *user_data; /* libcurl app data via curl_multi_assign() */ unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the * libcurl application to watch out for */ @@ -81,8 +84,7 @@ static size_t mev_sh_entry_compare(void *k1, size_t k1_len, static void mev_sh_entry_dtor(void *freethis) { struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis; - Curl_hash_offt_destroy(&entry->xfers); - Curl_hash_offt_destroy(&entry->conns); + Curl_uint_spbset_destroy(&entry->xfers); free(entry); } @@ -114,8 +116,7 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s) if(!check) return NULL; /* major failure */ - Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, NULL); - Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, NULL); + Curl_uint_spbset_init(&check->xfers); /* make/add new hash entry */ if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { @@ -134,19 +135,19 @@ static void mev_sh_entry_kill(struct Curl_multi *multi, curl_socket_t s) static size_t mev_sh_entry_user_count(struct mev_sh_entry *e) { - return Curl_hash_offt_count(&e->xfers) + Curl_hash_offt_count(&e->conns); + return Curl_uint_spbset_count(&e->xfers) + (e->conn ? 1 : 0); } static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e, struct Curl_easy *data) { - return !!Curl_hash_offt_get(&e->xfers, data->mid); + return Curl_uint_spbset_contains(&e->xfers, data->mid); } static bool mev_sh_entry_conn_known(struct mev_sh_entry *e, struct connectdata *conn) { - return !!Curl_hash_offt_get(&e->conns, conn->connection_id); + return (e->conn == conn); } static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e, @@ -154,7 +155,7 @@ static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e, { /* detect weird values */ DEBUGASSERT(mev_sh_entry_user_count(e) < 100000); - return !!Curl_hash_offt_set(&e->xfers, data->mid, data); + return Curl_uint_spbset_add(&e->xfers, data->mid); } static bool mev_sh_entry_conn_add(struct mev_sh_entry *e, @@ -162,20 +163,32 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e, { /* detect weird values */ DEBUGASSERT(mev_sh_entry_user_count(e) < 100000); - return !!Curl_hash_offt_set(&e->conns, conn->connection_id, conn); + DEBUGASSERT(!e->conn); + if(e->conn) + return FALSE; + e->conn = conn; + return TRUE; } static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e, struct Curl_easy *data) { - return Curl_hash_offt_remove(&e->xfers, data->mid); + bool present = Curl_uint_spbset_contains(&e->xfers, data->mid); + if(present) + Curl_uint_spbset_remove(&e->xfers, data->mid); + return present; } static bool mev_sh_entry_conn_remove(struct mev_sh_entry *e, struct connectdata *conn) { - return Curl_hash_offt_remove(&e->conns, conn->connection_id); + DEBUGASSERT(e->conn == conn); + if(e->conn == conn) { + e->conn = NULL; + return TRUE; + } + return FALSE; } /* Purge any information about socket `s`. @@ -339,11 +352,11 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, return CURLM_OUT_OF_MEMORY; } CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", added %s #%" FMT_OFF_T - ", total=%zu/%zu (xfer/conn)", s, + ", total=%u/%d (xfer/conn)", s, conn ? "connection" : "transfer", conn ? conn->connection_id : data->mid, - Curl_hash_offt_count(&entry->xfers), - Curl_hash_offt_count(&entry->conns)); + Curl_uint_spbset_count(&entry->xfers), + entry->conn ? 1 : 0); } else { for(j = 0; j < prev_ps->num; j++) { @@ -409,9 +422,9 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, if(mresult) return mresult; CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, " - "total=%zu/%zu (xfer/conn)", s, - Curl_hash_offt_count(&entry->xfers), - Curl_hash_offt_count(&entry->conns)); + "total=%u/%d (xfer/conn)", s, + Curl_uint_spbset_count(&entry->xfers), + entry->conn ? 1 : 0); } else { mresult = mev_forget_socket(multi, data, s, "last user gone"); @@ -425,31 +438,47 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, return CURLM_OK; } +static void mev_pollset_dtor(void *key, size_t klen, void *entry) +{ + (void)key; + (void)klen; + free(entry); +} + static struct easy_pollset* -mev_add_new_pollset(struct Curl_hash_offt *h, curl_off_t id) +mev_add_new_conn_pollset(struct connectdata *conn) { struct easy_pollset *ps; ps = calloc(1, sizeof(*ps)); if(!ps) return NULL; - if(!Curl_hash_offt_set(h, id, ps)) { - free(ps); + if(Curl_conn_meta_set(conn, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor)) + return NULL; + return ps; +} + +static struct easy_pollset* +mev_add_new_xfer_pollset(struct Curl_easy *data) +{ + struct easy_pollset *ps; + + ps = calloc(1, sizeof(*ps)); + if(!ps) + return NULL; + if(Curl_meta_set(data, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor)) return NULL; - } return ps; } static struct easy_pollset * -mev_get_last_pollset(struct Curl_multi *multi, - struct Curl_easy *data, +mev_get_last_pollset(struct Curl_easy *data, struct connectdata *conn) { if(data) { if(conn) - return Curl_hash_offt_get(&multi->ev.conn_pollsets, - conn->connection_id); - return Curl_hash_offt_get(&multi->ev.xfer_pollsets, data->mid); + return Curl_conn_meta_get(conn, CURL_META_MEV_POLLSET); + return Curl_meta_get(data, CURL_META_MEV_POLLSET); } return NULL; } @@ -473,14 +502,13 @@ static CURLMcode mev_assess(struct Curl_multi *multi, struct easy_pollset ps, *last_ps; mev_init_cur_pollset(&ps, data, conn); - last_ps = mev_get_last_pollset(multi, data, conn); + last_ps = mev_get_last_pollset(data, conn); if(!last_ps && ps.num) { if(conn) - last_ps = mev_add_new_pollset(&multi->ev.conn_pollsets, - conn->connection_id); + last_ps = mev_add_new_conn_pollset(conn); else - last_ps = mev_add_new_pollset(&multi->ev.xfer_pollsets, data->mid); + last_ps = mev_add_new_xfer_pollset(data); if(!last_ps) return CURLM_OUT_OF_MEMORY; } @@ -506,16 +534,19 @@ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi, return mev_assess(multi, data, conn); } -CURLMcode Curl_multi_ev_assess_xfer_list(struct Curl_multi *multi, - struct Curl_llist *list) +CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi, + struct uint_bset *set) { - struct Curl_llist_node *e; + unsigned int mid; CURLMcode result = CURLM_OK; - if(multi && multi->socket_cb) { - for(e = Curl_llist_head(list); e && !result; e = Curl_node_next(e)) { - result = Curl_multi_ev_assess_xfer(multi, Curl_node_elem(e)); + if(multi && multi->socket_cb && Curl_uint_bset_first(set, &mid)) { + do { + struct Curl_easy *data = Curl_multi_get_easy(multi, mid); + if(data) + result = Curl_multi_ev_assess_xfer(multi, data); } + while(!result && Curl_uint_bset_next(set, mid, &mid)); } return result; } @@ -532,21 +563,6 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi, return CURLM_OK; } -static bool mev_xfer_expire_cb(curl_off_t id, void *value, void *user_data) -{ - const struct curltime *nowp = user_data; - struct Curl_easy *data = value; - - DEBUGASSERT(data); - DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER); - if(data && id >= 0) { - /* Expire with out current now, so we will get it below when - * asking the splaytree for expired transfers. */ - Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW); - } - return TRUE; -} - void Curl_multi_ev_expire_xfers(struct Curl_multi *multi, curl_socket_t s, const struct curltime *nowp, @@ -563,10 +579,22 @@ void Curl_multi_ev_expire_xfers(struct Curl_multi *multi, asked to get removed, so thus we better survive stray socket actions and just move on. */ if(entry) { - Curl_hash_offt_visit(&entry->xfers, mev_xfer_expire_cb, - CURL_UNCONST(nowp)); + struct Curl_easy *data; + unsigned int mid; + + if(Curl_uint_spbset_first(&entry->xfers, &mid)) { + do { + data = Curl_multi_get_easy(multi, mid); + if(data) { + /* Expire with out current now, so we will get it below when + * asking the splaytree for expired transfers. */ + Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW); + } + } + while(Curl_uint_spbset_next(&entry->xfers, mid, &mid)); + } - if(Curl_hash_offt_count(&entry->conns)) + if(entry->conn) *run_cpool = TRUE; } } @@ -581,9 +609,9 @@ void Curl_multi_ev_xfer_done(struct Curl_multi *multi, struct Curl_easy *data) { DEBUGASSERT(!data->conn); /* transfer should have been detached */ - if(data->mid >= 0) { + if(data != multi->admin) { (void)mev_assess(multi, data, NULL); - Curl_hash_offt_remove(&multi->ev.xfer_pollsets, data->mid); + Curl_meta_remove(data, CURL_META_MEV_POLLSET); } } @@ -592,30 +620,18 @@ void Curl_multi_ev_conn_done(struct Curl_multi *multi, struct connectdata *conn) { (void)mev_assess(multi, data, conn); - Curl_hash_offt_remove(&multi->ev.conn_pollsets, conn->connection_id); + Curl_conn_meta_remove(conn, CURL_META_MEV_POLLSET); } #define CURL_MEV_PS_HASH_SLOTS (991) /* nice prime */ -static void mev_hash_pollset_free(curl_off_t id, void *entry) -{ - (void)id; - free(entry); -} - void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize) { Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash, mev_sh_entry_compare, mev_sh_entry_dtor); - Curl_hash_offt_init(&multi->ev.xfer_pollsets, - CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free); - Curl_hash_offt_init(&multi->ev.conn_pollsets, - CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free); } void Curl_multi_ev_cleanup(struct Curl_multi *multi) { Curl_hash_destroy(&multi->ev.sh_entries); - Curl_hash_offt_destroy(&multi->ev.xfer_pollsets); - Curl_hash_offt_destroy(&multi->ev.conn_pollsets); } -- cgit v1.2.3