Merge bafd2bddc7 into e7751571eb
This commit is contained in:
commit
941cbe37c6
@ -164,6 +164,7 @@ LIB_CFILES = \
|
||||
getinfo.c \
|
||||
gopher.c \
|
||||
hash.c \
|
||||
hash_offt.c \
|
||||
headers.c \
|
||||
hmac.c \
|
||||
hostasyn.c \
|
||||
@ -312,6 +313,7 @@ LIB_HFILES = \
|
||||
getinfo.h \
|
||||
gopher.h \
|
||||
hash.h \
|
||||
hash_offt.h \
|
||||
headers.h \
|
||||
hostip.h \
|
||||
hsts.h \
|
||||
|
||||
22
lib/hash.c
22
lib/hash.c
@ -400,25 +400,3 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
|
||||
|
||||
return iter->current;
|
||||
}
|
||||
|
||||
void Curl_hash_offt_init(struct Curl_hash *h,
|
||||
size_t slots,
|
||||
Curl_hash_dtor dtor)
|
||||
{
|
||||
Curl_hash_init(h, slots, Curl_hash_str, Curl_str_key_compare, dtor);
|
||||
}
|
||||
|
||||
void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem)
|
||||
{
|
||||
return Curl_hash_add(h, &id, sizeof(id), elem);
|
||||
}
|
||||
|
||||
int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id)
|
||||
{
|
||||
return Curl_hash_delete(h, &id, sizeof(id));
|
||||
}
|
||||
|
||||
void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id)
|
||||
{
|
||||
return Curl_hash_pick(h, &id, sizeof(id));
|
||||
}
|
||||
|
||||
@ -108,13 +108,4 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter);
|
||||
void Curl_hash_print(struct Curl_hash *h,
|
||||
void (*func)(void *));
|
||||
|
||||
/* Hash for `curl_off_t` as key */
|
||||
void Curl_hash_offt_init(struct Curl_hash *h, size_t slots,
|
||||
Curl_hash_dtor dtor);
|
||||
|
||||
void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem);
|
||||
int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id);
|
||||
void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id);
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_HASH_H */
|
||||
|
||||
242
lib/hash_offt.c
Normal file
242
lib/hash_offt.c
Normal file
@ -0,0 +1,242 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "hash_offt.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* random patterns for API verification */
|
||||
#ifdef DEBUGBUILD
|
||||
#define CURL_HASHOFFTINIT 0x7117e781
|
||||
#endif
|
||||
|
||||
static size_t hash_offt_hash(curl_off_t id, size_t slots)
|
||||
{
|
||||
return (size_t)((id >= 0) ? (id % slots) : (-id % slots));
|
||||
}
|
||||
|
||||
struct Curl_hash_offt_entry {
|
||||
curl_off_t id;
|
||||
struct Curl_hash_offt_entry *next;
|
||||
void *value;
|
||||
};
|
||||
|
||||
void Curl_hash_offt_init(struct Curl_hash_offt *h,
|
||||
size_t slots,
|
||||
Curl_hash_offt_dtor *dtor)
|
||||
{
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(slots);
|
||||
|
||||
h->table = NULL;
|
||||
h->dtor = dtor;
|
||||
h->size = 0;
|
||||
h->slots = slots;
|
||||
#ifdef DEBUGBUILD
|
||||
h->init = CURL_HASHOFFTINIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct Curl_hash_offt_entry *
|
||||
hash_offt_mk_entry(curl_off_t id, void *value)
|
||||
{
|
||||
struct Curl_hash_offt_entry *e;
|
||||
|
||||
/* allocate the struct for the hash entry */
|
||||
e = malloc(sizeof(*e));
|
||||
if(e) {
|
||||
e->id = id;
|
||||
e->next = NULL;
|
||||
e->value = value;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static void hash_offt_entry_clear(struct Curl_hash_offt *h,
|
||||
struct Curl_hash_offt_entry *e)
|
||||
{
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(e);
|
||||
if(e->value) {
|
||||
if(h->dtor)
|
||||
h->dtor(e->id, e->value);
|
||||
e->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void hash_offt_entry_destroy(struct Curl_hash_offt *h,
|
||||
struct Curl_hash_offt_entry *e)
|
||||
{
|
||||
hash_offt_entry_clear(h, e);
|
||||
free(e);
|
||||
}
|
||||
|
||||
static void hash_offt_entry_unlink(struct Curl_hash_offt *h,
|
||||
struct Curl_hash_offt_entry **he_anchor,
|
||||
struct Curl_hash_offt_entry *he)
|
||||
{
|
||||
*he_anchor = he->next;
|
||||
--h->size;
|
||||
}
|
||||
|
||||
static void hash_offtr_elem_link(struct Curl_hash_offt *h,
|
||||
struct Curl_hash_offt_entry **he_anchor,
|
||||
struct Curl_hash_offt_entry *he)
|
||||
{
|
||||
he->next = *he_anchor;
|
||||
*he_anchor = he;
|
||||
++h->size;
|
||||
}
|
||||
|
||||
#define CURL_HASH_OFFT_SLOT(h,id) h->table[hash_offt_hash(id, h->slots)]
|
||||
#define CURL_HASH_OFFT_SLOT_ADDR(h,id) &CURL_HASH_OFFT_SLOT(h,id)
|
||||
|
||||
bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value)
|
||||
{
|
||||
struct Curl_hash_offt_entry *he, **slot;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->slots);
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
if(!h->table) {
|
||||
h->table = calloc(h->slots, sizeof(*he));
|
||||
if(!h->table)
|
||||
return FALSE; /* OOM */
|
||||
}
|
||||
|
||||
slot = CURL_HASH_OFFT_SLOT_ADDR(h, id);
|
||||
for(he = *slot; he; he = he->next) {
|
||||
if(he->id == id) {
|
||||
/* existing key entry, overwrite by clearing old pointer */
|
||||
hash_offt_entry_clear(h, he);
|
||||
he->value = value;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
he = hash_offt_mk_entry(id, value);
|
||||
if(!he)
|
||||
return FALSE; /* OOM */
|
||||
|
||||
hash_offtr_elem_link(h, slot, he);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id)
|
||||
{
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->slots);
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
if(h->table) {
|
||||
struct Curl_hash_offt_entry *he, **he_anchor;
|
||||
|
||||
he_anchor = CURL_HASH_OFFT_SLOT_ADDR(h, id);
|
||||
while(*he_anchor) {
|
||||
he = *he_anchor;
|
||||
if(id == he->id) {
|
||||
hash_offt_entry_unlink(h, he_anchor, he);
|
||||
hash_offt_entry_destroy(h, he);
|
||||
return TRUE;
|
||||
}
|
||||
he_anchor = &he->next;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id)
|
||||
{
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
if(h->table) {
|
||||
struct Curl_hash_offt_entry *he;
|
||||
DEBUGASSERT(h->slots);
|
||||
he = CURL_HASH_OFFT_SLOT(h, id);
|
||||
while(he) {
|
||||
if(id == he->id) {
|
||||
return he->value;
|
||||
}
|
||||
he = he->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Curl_hash_offt_clear(struct Curl_hash_offt *h)
|
||||
{
|
||||
if(h && h->table) {
|
||||
struct Curl_hash_offt_entry *he, **he_anchor;
|
||||
size_t i;
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
for(i = 0; i < h->slots; ++i) {
|
||||
he_anchor = &h->table[i];
|
||||
while(*he_anchor) {
|
||||
he = *he_anchor;
|
||||
hash_offt_entry_unlink(h, he_anchor, he);
|
||||
hash_offt_entry_destroy(h, he);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Curl_hash_offt_destroy(struct Curl_hash_offt *h)
|
||||
{
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
if(h->table) {
|
||||
Curl_hash_offt_clear(h);
|
||||
Curl_safefree(h->table);
|
||||
}
|
||||
DEBUGASSERT(h->size == 0);
|
||||
h->slots = 0;
|
||||
}
|
||||
|
||||
size_t Curl_hash_offt_count(struct Curl_hash_offt *h)
|
||||
{
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
return h->size;
|
||||
}
|
||||
|
||||
void Curl_hash_offt_visit(struct Curl_hash_offt *h,
|
||||
Curl_hash_offt_visit_cb *cb,
|
||||
void *user_data)
|
||||
{
|
||||
if(h && h->table && cb) {
|
||||
struct Curl_hash_offt_entry *he;
|
||||
size_t i;
|
||||
DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
|
||||
for(i = 0; i < h->slots; ++i) {
|
||||
for(he = h->table[i]; he; he = he->next) {
|
||||
if(!cb(he->id, he->value, user_data))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
lib/hash_offt.h
Normal file
67
lib/hash_offt.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef HEADER_CURL_HASH_OFFT_H
|
||||
#define HEADER_CURL_HASH_OFFT_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
struct Curl_hash_offt_entry;
|
||||
typedef void Curl_hash_offt_dtor(curl_off_t id, void *value);
|
||||
|
||||
/* Hash for `curl_off_t` as key */
|
||||
struct Curl_hash_offt {
|
||||
struct Curl_hash_offt_entry **table;
|
||||
Curl_hash_offt_dtor *dtor;
|
||||
size_t slots;
|
||||
size_t size;
|
||||
#ifdef DEBUGBUILD
|
||||
int init;
|
||||
#endif
|
||||
};
|
||||
|
||||
void Curl_hash_offt_init(struct Curl_hash_offt *h,
|
||||
size_t slots,
|
||||
Curl_hash_offt_dtor *dtor);
|
||||
void Curl_hash_offt_destroy(struct Curl_hash_offt *h);
|
||||
|
||||
bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value);
|
||||
bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id);
|
||||
void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id);
|
||||
void Curl_hash_offt_clear(struct Curl_hash_offt *h);
|
||||
size_t Curl_hash_offt_count(struct Curl_hash_offt *h);
|
||||
|
||||
|
||||
typedef bool Curl_hash_offt_visit_cb(curl_off_t id, void *value,
|
||||
void *user_data);
|
||||
|
||||
void Curl_hash_offt_visit(struct Curl_hash_offt *h,
|
||||
Curl_hash_offt_visit_cb *cb,
|
||||
void *user_data);
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_HASH_OFFT_H */
|
||||
12
lib/http2.c
12
lib/http2.c
@ -29,7 +29,7 @@
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "urldata.h"
|
||||
#include "bufq.h"
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
#include "http1.h"
|
||||
#include "http2.h"
|
||||
#include "http.h"
|
||||
@ -135,7 +135,7 @@ struct cf_h2_ctx {
|
||||
struct bufc_pool stream_bufcp; /* spares for stream buffers */
|
||||
struct dynbuf scratch; /* scratch buffer for temp use */
|
||||
|
||||
struct Curl_hash streams; /* hash of `data->mid` to `h2_stream_ctx` */
|
||||
struct Curl_hash_offt streams; /* hash of `data->mid` to `h2_stream_ctx` */
|
||||
size_t drain_total; /* sum of all stream's UrlState drain */
|
||||
uint32_t max_concurrent_streams;
|
||||
uint32_t goaway_error; /* goaway error code from server */
|
||||
@ -155,7 +155,7 @@ struct cf_h2_ctx {
|
||||
#define CF_CTX_CALL_DATA(cf) \
|
||||
((struct cf_h2_ctx *)(cf)->ctx)->call_data
|
||||
|
||||
static void h2_stream_hash_free(void *stream);
|
||||
static void h2_stream_hash_free(curl_off_t id, void *stream);
|
||||
|
||||
static void cf_h2_ctx_init(struct cf_h2_ctx *ctx, bool via_h1_upgrade)
|
||||
{
|
||||
@ -176,8 +176,7 @@ static void cf_h2_ctx_free(struct cf_h2_ctx *ctx)
|
||||
Curl_bufq_free(&ctx->outbufq);
|
||||
Curl_bufcp_free(&ctx->stream_bufcp);
|
||||
Curl_dyn_free(&ctx->scratch);
|
||||
Curl_hash_clean(&ctx->streams);
|
||||
Curl_hash_destroy(&ctx->streams);
|
||||
Curl_hash_offt_destroy(&ctx->streams);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
free(ctx);
|
||||
@ -267,8 +266,9 @@ static void h2_stream_ctx_free(struct h2_stream_ctx *stream)
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static void h2_stream_hash_free(void *stream)
|
||||
static void h2_stream_hash_free(curl_off_t id, void *stream)
|
||||
{
|
||||
(void)id;
|
||||
DEBUGASSERT(stream);
|
||||
h2_stream_ctx_free((struct h2_stream_ctx *)stream);
|
||||
}
|
||||
|
||||
@ -54,8 +54,8 @@ static void mev_in_callback(struct Curl_multi *multi, bool value)
|
||||
* what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE)
|
||||
*/
|
||||
struct mev_sh_entry {
|
||||
struct Curl_hash xfers; /* hash of transfers using this socket */
|
||||
struct Curl_hash conns; /* hash of connections using this socket */
|
||||
struct Curl_hash_offt xfers; /* hash of transfers using this socket */
|
||||
struct Curl_hash_offt conns; /* hash of connections using this socket */
|
||||
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 +81,8 @@ 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_destroy(&entry->xfers);
|
||||
Curl_hash_destroy(&entry->conns);
|
||||
Curl_hash_offt_destroy(&entry->xfers);
|
||||
Curl_hash_offt_destroy(&entry->conns);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
@ -97,11 +97,6 @@ mev_sh_entry_get(struct Curl_hash *sh, curl_socket_t s)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mev_nop_dtor(void *e)
|
||||
{
|
||||
(void)e; /* does nothing */
|
||||
}
|
||||
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
static struct mev_sh_entry *
|
||||
mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
|
||||
@ -119,8 +114,8 @@ 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, mev_nop_dtor);
|
||||
Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, mev_nop_dtor);
|
||||
Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, NULL);
|
||||
Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, NULL);
|
||||
|
||||
/* make/add new hash entry */
|
||||
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
|
||||
@ -139,7 +134,7 @@ 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_count(&e->xfers) + Curl_hash_count(&e->conns);
|
||||
return Curl_hash_offt_count(&e->xfers) + Curl_hash_offt_count(&e->conns);
|
||||
}
|
||||
|
||||
static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
|
||||
@ -174,7 +169,7 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
|
||||
static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
return !Curl_hash_offt_remove(&e->xfers, data->id);
|
||||
return Curl_hash_offt_remove(&e->xfers, data->id);
|
||||
}
|
||||
|
||||
/* Purge any information about socket `s`.
|
||||
@ -341,8 +336,8 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||
", total=%zu/%zu (xfer/conn)", s,
|
||||
conn ? "connection" : "transfer",
|
||||
conn ? conn->connection_id : data->id,
|
||||
Curl_hash_count(&entry->xfers),
|
||||
Curl_hash_count(&entry->conns));
|
||||
Curl_hash_offt_count(&entry->xfers),
|
||||
Curl_hash_offt_count(&entry->conns));
|
||||
}
|
||||
else {
|
||||
for(j = 0; j < prev_ps->num; j++) {
|
||||
@ -399,8 +394,8 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||
return mresult;
|
||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
|
||||
"total=%zu/%zu (xfer/conn)", s,
|
||||
Curl_hash_count(&entry->xfers),
|
||||
Curl_hash_count(&entry->conns));
|
||||
Curl_hash_offt_count(&entry->xfers),
|
||||
Curl_hash_offt_count(&entry->conns));
|
||||
}
|
||||
else {
|
||||
mresult = mev_forget_socket(multi, data, s, "last user gone");
|
||||
@ -415,7 +410,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||
}
|
||||
|
||||
static struct easy_pollset*
|
||||
mev_add_new_pollset(struct Curl_hash *h, curl_off_t id)
|
||||
mev_add_new_pollset(struct Curl_hash_offt *h, curl_off_t id)
|
||||
{
|
||||
struct easy_pollset *ps;
|
||||
|
||||
@ -522,6 +517,20 @@ 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,
|
||||
@ -539,24 +548,9 @@ 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) {
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
Curl_hash_offt_visit(&entry->xfers, mev_xfer_expire_cb, (void *)nowp);
|
||||
|
||||
/* the socket can be shared by many transfers, iterate */
|
||||
Curl_hash_start_iterate(&entry->xfers, &iter);
|
||||
for(he = Curl_hash_next_element(&iter); he;
|
||||
he = Curl_hash_next_element(&iter)) {
|
||||
struct Curl_easy *data = (struct Curl_easy *)he->ptr;
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
|
||||
DEBUGASSERT(data->id >= 0); /* we should not track internal handles */
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if(Curl_hash_count(&entry->conns))
|
||||
if(Curl_hash_offt_count(&entry->conns))
|
||||
*run_cpool = TRUE;
|
||||
}
|
||||
}
|
||||
@ -587,8 +581,9 @@ void Curl_multi_ev_conn_done(struct Curl_multi *multi,
|
||||
|
||||
#define CURL_MEV_PS_HASH_SLOTS (991) /* nice prime */
|
||||
|
||||
static void mev_hash_pollset_free(void *entry)
|
||||
static void mev_hash_pollset_free(curl_off_t id, void *entry)
|
||||
{
|
||||
(void)id;
|
||||
free(entry);
|
||||
}
|
||||
|
||||
@ -605,6 +600,6 @@ void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
|
||||
void Curl_multi_ev_cleanup(struct Curl_multi *multi)
|
||||
{
|
||||
Curl_hash_destroy(&multi->ev.sh_entries);
|
||||
Curl_hash_destroy(&multi->ev.xfer_pollsets);
|
||||
Curl_hash_destroy(&multi->ev.conn_pollsets);
|
||||
Curl_hash_offt_destroy(&multi->ev.xfer_pollsets);
|
||||
Curl_hash_offt_destroy(&multi->ev.conn_pollsets);
|
||||
}
|
||||
|
||||
@ -24,14 +24,17 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
|
||||
struct Curl_easy;
|
||||
struct Curl_multi;
|
||||
struct easy_pollset;
|
||||
|
||||
struct curl_multi_ev {
|
||||
struct Curl_hash sh_entries;
|
||||
struct Curl_hash xfer_pollsets;
|
||||
struct Curl_hash conn_pollsets;
|
||||
struct Curl_hash_offt xfer_pollsets;
|
||||
struct Curl_hash_offt conn_pollsets;
|
||||
};
|
||||
|
||||
/* Setup/teardown of multi event book-keeping. */
|
||||
|
||||
@ -159,6 +159,7 @@ typedef unsigned int curl_prot_t;
|
||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||
#include "hostip.h"
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
#include "splay.h"
|
||||
#include "dynbuf.h"
|
||||
#include "dynhds.h"
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
#include "urldata.h"
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
#include "timeval.h"
|
||||
#include "multiif.h"
|
||||
#include "sendf.h"
|
||||
@ -119,7 +120,7 @@ struct cf_msh3_ctx {
|
||||
struct cf_call_data call_data;
|
||||
struct curltime connect_started; /* time the current attempt started */
|
||||
struct curltime handshake_at; /* time connect handshake finished */
|
||||
struct Curl_hash streams; /* hash `data->mid` to `stream_ctx` */
|
||||
struct Curl_hash_offt streams; /* hash `data->mid` to `stream_ctx` */
|
||||
/* Flags written by msh3/msquic thread */
|
||||
bool handshake_complete;
|
||||
bool handshake_succeeded;
|
||||
@ -130,7 +131,7 @@ struct cf_msh3_ctx {
|
||||
BIT(active);
|
||||
};
|
||||
|
||||
static void h3_stream_hash_free(void *stream);
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream);
|
||||
|
||||
static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
|
||||
const struct Curl_addrinfo *ai)
|
||||
@ -154,7 +155,7 @@ static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
|
||||
static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
|
||||
{
|
||||
if(ctx && ctx->initialized) {
|
||||
Curl_hash_destroy(&ctx->streams);
|
||||
Curl_hash_offt_destroy(&ctx->streams);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
@ -196,8 +197,9 @@ static void h3_stream_ctx_free(struct stream_ctx *stream)
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static void h3_stream_hash_free(void *stream)
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream)
|
||||
{
|
||||
(void)id;
|
||||
DEBUGASSERT(stream);
|
||||
h3_stream_ctx_free((struct stream_ctx *)stream);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
#include "sendf.h"
|
||||
#include "strdup.h"
|
||||
#include "rand.h"
|
||||
@ -133,7 +133,7 @@ struct cf_ngtcp2_ctx {
|
||||
struct curltime handshake_at; /* time connect handshake finished */
|
||||
struct bufc_pool stream_bufcp; /* chunk pool for streams */
|
||||
struct dynbuf scratch; /* temp buffer for header construction */
|
||||
struct Curl_hash streams; /* hash `data->mid` to `h3_stream_ctx` */
|
||||
struct Curl_hash_offt streams; /* hash `data->mid` to `h3_stream_ctx` */
|
||||
size_t max_stream_window; /* max flow window for one stream */
|
||||
uint64_t max_idle_ms; /* max idle time for QUIC connection */
|
||||
uint64_t used_bidi_streams; /* bidi streams we have opened */
|
||||
@ -156,7 +156,7 @@ struct cf_ngtcp2_ctx {
|
||||
#define CF_CTX_CALL_DATA(cf) \
|
||||
((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
|
||||
|
||||
static void h3_stream_hash_free(void *stream);
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream);
|
||||
|
||||
static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx)
|
||||
{
|
||||
@ -179,8 +179,7 @@ static void cf_ngtcp2_ctx_free(struct cf_ngtcp2_ctx *ctx)
|
||||
vquic_ctx_free(&ctx->q);
|
||||
Curl_bufcp_free(&ctx->stream_bufcp);
|
||||
Curl_dyn_free(&ctx->scratch);
|
||||
Curl_hash_clean(&ctx->streams);
|
||||
Curl_hash_destroy(&ctx->streams);
|
||||
Curl_hash_offt_destroy(&ctx->streams);
|
||||
Curl_ssl_peer_cleanup(&ctx->peer);
|
||||
}
|
||||
free(ctx);
|
||||
@ -225,8 +224,9 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static void h3_stream_hash_free(void *stream)
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream)
|
||||
{
|
||||
(void)id;
|
||||
DEBUGASSERT(stream);
|
||||
h3_stream_ctx_free((struct h3_stream_ctx *)stream);
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ struct cf_osslq_ctx {
|
||||
struct curltime handshake_at; /* time connect handshake finished */
|
||||
struct curltime first_byte_at; /* when first byte was recvd */
|
||||
struct bufc_pool stream_bufcp; /* chunk pool for streams */
|
||||
struct Curl_hash streams; /* hash `data->mid` to `h3_stream_ctx` */
|
||||
struct Curl_hash_offt streams; /* hash `data->mid` to `h3_stream_ctx` */
|
||||
size_t max_stream_window; /* max flow window for one stream */
|
||||
uint64_t max_idle_ms; /* max idle time for QUIC connection */
|
||||
SSL_POLL_ITEM *poll_items; /* Array for polling on writable state */
|
||||
@ -299,7 +299,7 @@ struct cf_osslq_ctx {
|
||||
BIT(need_send); /* QUIC connection needs to send */
|
||||
};
|
||||
|
||||
static void h3_stream_hash_free(void *stream);
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream);
|
||||
|
||||
static void cf_osslq_ctx_init(struct cf_osslq_ctx *ctx)
|
||||
{
|
||||
@ -317,8 +317,7 @@ static void cf_osslq_ctx_free(struct cf_osslq_ctx *ctx)
|
||||
{
|
||||
if(ctx && ctx->initialized) {
|
||||
Curl_bufcp_free(&ctx->stream_bufcp);
|
||||
Curl_hash_clean(&ctx->streams);
|
||||
Curl_hash_destroy(&ctx->streams);
|
||||
Curl_hash_offt_destroy(&ctx->streams);
|
||||
Curl_ssl_peer_cleanup(&ctx->peer);
|
||||
free(ctx->poll_items);
|
||||
free(ctx->curl_items);
|
||||
@ -603,8 +602,9 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static void h3_stream_hash_free(void *stream)
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream)
|
||||
{
|
||||
(void)id;
|
||||
DEBUGASSERT(stream);
|
||||
h3_stream_ctx_free((struct h3_stream_ctx *)stream);
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include "bufq.h"
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "cf-socket.h"
|
||||
@ -97,7 +97,7 @@ struct cf_quiche_ctx {
|
||||
struct curltime started_at; /* time the current attempt started */
|
||||
struct curltime handshake_at; /* time connect handshake finished */
|
||||
struct bufc_pool stream_bufcp; /* chunk pool for streams */
|
||||
struct Curl_hash streams; /* hash `data->mid` to `stream_ctx` */
|
||||
struct Curl_hash_offt streams; /* hash `data->mid` to `stream_ctx` */
|
||||
curl_off_t data_recvd;
|
||||
BIT(initialized);
|
||||
BIT(goaway); /* got GOAWAY from server */
|
||||
@ -115,7 +115,7 @@ static void quiche_debug_log(const char *line, void *argp)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void h3_stream_hash_free(void *stream);
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream);
|
||||
|
||||
static void cf_quiche_ctx_init(struct cf_quiche_ctx *ctx)
|
||||
{
|
||||
@ -142,8 +142,7 @@ static void cf_quiche_ctx_free(struct cf_quiche_ctx *ctx)
|
||||
Curl_ssl_peer_cleanup(&ctx->peer);
|
||||
vquic_ctx_free(&ctx->q);
|
||||
Curl_bufcp_free(&ctx->stream_bufcp);
|
||||
Curl_hash_clean(&ctx->streams);
|
||||
Curl_hash_destroy(&ctx->streams);
|
||||
Curl_hash_offt_destroy(&ctx->streams);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
@ -190,8 +189,9 @@ static void h3_stream_ctx_free(struct stream_ctx *stream)
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static void h3_stream_hash_free(void *stream)
|
||||
static void h3_stream_hash_free(curl_off_t id, void *stream)
|
||||
{
|
||||
(void)id;
|
||||
DEBUGASSERT(stream);
|
||||
h3_stream_ctx_free((struct stream_ctx *)stream);
|
||||
}
|
||||
|
||||
@ -25,15 +25,16 @@
|
||||
|
||||
#include "curlx.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "hash_offt.h"
|
||||
|
||||
#include "memdebug.h" /* LAST include file */
|
||||
|
||||
static struct Curl_hash hash_static;
|
||||
static struct Curl_hash_offt hash_static;
|
||||
|
||||
static void mydtor(void *elem)
|
||||
static void mydtor(curl_off_t id, void *elem)
|
||||
{
|
||||
int *ptr = (int *)elem;
|
||||
(void)id;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
@ -45,13 +46,13 @@ static CURLcode unit_setup(void)
|
||||
|
||||
static void unit_stop(void)
|
||||
{
|
||||
Curl_hash_destroy(&hash_static);
|
||||
Curl_hash_offt_destroy(&hash_static);
|
||||
}
|
||||
|
||||
UNITTEST_START
|
||||
int *value, *v;
|
||||
int *value2;
|
||||
int *nodep;
|
||||
bool ok;
|
||||
|
||||
curl_off_t key = 20;
|
||||
curl_off_t key2 = 25;
|
||||
@ -60,24 +61,24 @@ UNITTEST_START
|
||||
value = malloc(sizeof(int));
|
||||
abort_unless(value != NULL, "Out of memory");
|
||||
*value = 199;
|
||||
nodep = Curl_hash_offt_set(&hash_static, key, value);
|
||||
if(!nodep)
|
||||
ok = Curl_hash_offt_set(&hash_static, key, value);
|
||||
if(!ok)
|
||||
free(value);
|
||||
abort_unless(nodep, "insertion into hash failed");
|
||||
abort_unless(ok, "insertion into hash failed");
|
||||
v = Curl_hash_offt_get(&hash_static, key);
|
||||
abort_unless(v == value, "lookup present entry failed");
|
||||
v = Curl_hash_offt_get(&hash_static, key2);
|
||||
abort_unless(!v, "lookup missing entry failed");
|
||||
Curl_hash_clean(&hash_static);
|
||||
Curl_hash_offt_clear(&hash_static);
|
||||
|
||||
/* Attempt to add another key/value pair */
|
||||
value2 = malloc(sizeof(int));
|
||||
abort_unless(value2 != NULL, "Out of memory");
|
||||
*value2 = 204;
|
||||
nodep = Curl_hash_offt_set(&hash_static, key2, value2);
|
||||
if(!nodep)
|
||||
ok = Curl_hash_offt_set(&hash_static, key2, value2);
|
||||
if(!ok)
|
||||
free(value2);
|
||||
abort_unless(nodep, "insertion into hash failed");
|
||||
abort_unless(ok, "insertion into hash failed");
|
||||
v = Curl_hash_offt_get(&hash_static, key2);
|
||||
abort_unless(v == value2, "lookup present entry failed");
|
||||
v = Curl_hash_offt_get(&hash_static, key);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user