mirror of
https://github.com/curl/curl.git
synced 2025-04-12 16:20:35 +08:00
llist: remove direct struct accesses, use only functions
- Turned them all into functions to also do asserts etc. - The llist related structs got all their fields renamed in order to make sure no existing code remains using direct access. - Each list node struct now points back to the list it "lives in", so Curl_node_remove() no longer needs the list pointer. - Rename the node struct and some of the access functions. - Added lots of ASSERTs to verify API being used correctly - Fix some cases of API misuse Add docs/LLIST.md documenting the internal linked list API. Closes #14485
This commit is contained in:
parent
6f00a05e89
commit
ba235ab269
190
docs/LLIST.md
Normal file
190
docs/LLIST.md
Normal file
@ -0,0 +1,190 @@
|
||||
<!--
|
||||
Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
|
||||
SPDX-License-Identifier: curl
|
||||
-->
|
||||
|
||||
# `llist` - linked lists
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
This is the internal module for linked lists. The API is designed to be
|
||||
flexible but also to avoid dynamic memory allocation.
|
||||
|
||||
None of the involved structs should be accessed using struct fields (outside
|
||||
of `llist.c`). Use the functions.
|
||||
|
||||
## Setup and shutdown
|
||||
|
||||
`struct Curl_llist` is the struct holding a single linked list. It needs to be
|
||||
initialized with a call to `Curl_llist_init()` before it can be used
|
||||
|
||||
To clean up a list, call `Curl_llist_destroy()`. Since the linked lists
|
||||
themselves do not allocate memory, it can also be fine to just *not* clean up
|
||||
the list.
|
||||
|
||||
## Add a node
|
||||
|
||||
There are two functions for adding a node to a linked list:
|
||||
|
||||
1. Add it last in the list with `Curl_llist_append`
|
||||
2. Add it after a specific existing node with `Curl_llist_insert_next`
|
||||
|
||||
When a node is added to a list, it stores an associated custom pointer to
|
||||
anything you like and you provide a pointer to a `struct Curl_llist_node`
|
||||
struct in which it stores and updates pointers. If you intend to add the same
|
||||
struct to multiple lists concurrently, you need to have one `struct
|
||||
Curl_llist_node` for each list.
|
||||
|
||||
Add a node to a list with `Curl_llist_append(list, elem, node)`. Where
|
||||
|
||||
- `list`: points to a `struct Curl_llist`
|
||||
- `elem`: points to what you want added to the list
|
||||
- `node`: is a pointer to a `struct Curl_llist_node`. Data storage for this
|
||||
node.
|
||||
|
||||
Example: to add a `struct foobar` to a linked list. Add a node struct within
|
||||
it:
|
||||
|
||||
struct foobar {
|
||||
char *random;
|
||||
struct Curl_llist_node storage; /* can be anywhere in the struct */
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct Curl_llist barlist; /* the list for foobar entries */
|
||||
struct foobar entries[10];
|
||||
|
||||
Curl_llist_init(&barlist, NULL);
|
||||
|
||||
/* add the first struct to the list */
|
||||
Curl_llist_append(&barlist, &entries[0], &entries[0].storage);
|
||||
|
||||
See also `Curl_llist_insert_next`.
|
||||
|
||||
## Remove a node
|
||||
|
||||
Remove a node again from a list by calling `Curl_llist_remove()`.
|
||||
|
||||
## Iterate
|
||||
|
||||
To iterate over a list: first get the head entry and then iterate over the
|
||||
nodes as long there is a next. Each node has an *element* associated with it,
|
||||
the custom pointer you stored there. Usually a struct pointer or similar.
|
||||
|
||||
struct Curl_llist_node *iter;
|
||||
|
||||
/* get the first entry of the 'barlist' */
|
||||
iter = Curl_llist_head(&barlist);
|
||||
|
||||
while(iter) {
|
||||
/* extract the element pointer from the node */
|
||||
struct foobar *elem = Curl_node_elem(iter);
|
||||
|
||||
/* advance to the next node in the list */
|
||||
iter = Curl_node_next(iter);
|
||||
}
|
||||
|
||||
# Function overview
|
||||
|
||||
## `Curl_llist_init`
|
||||
|
||||
~~~c
|
||||
void Curl_llist_init(struct Curl_llist *list, Curl_llist_dtor dtor);
|
||||
~~~
|
||||
|
||||
Initializes the `list`. The argument `dtor` is NULL or a function pointer that
|
||||
gets called when list nodes are removed from this list.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
~~~c
|
||||
typedef void (*Curl_llist_dtor)(void *user, void *elem);
|
||||
~~~
|
||||
|
||||
`dtor` is called with two arguments: `user` and `elem`. The first being the
|
||||
`user` pointer passed in to `Curl_llist_remove()`or `Curl_llist_destroy()` and
|
||||
the second is the `elem` pointer associated with removed node. The pointer
|
||||
that `Curl_node_elem()` would have returned for that node.
|
||||
|
||||
## `Curl_llist_destroy`
|
||||
|
||||
~~~c
|
||||
void Curl_llist_destroy(struct Curl_llist *list, void *user);
|
||||
~~~
|
||||
|
||||
This removes all nodes from the `list`. This leaves the list in a cleared
|
||||
state.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
## `Curl_llist_append`
|
||||
|
||||
~~~c
|
||||
void Curl_llist_append(struct Curl_llist *list,
|
||||
const void *elem, struct Curl_llist_node *node);
|
||||
~~~
|
||||
|
||||
Adds `node` last in the `list` with a custom pointer to `elem`.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
## `Curl_llist_insert_next`
|
||||
|
||||
~~~c
|
||||
void Curl_llist_insert_next(struct Curl_llist *list,
|
||||
struct Curl_llist_node *node,
|
||||
const void *elem,
|
||||
struct Curl_llist_node *node);
|
||||
~~~
|
||||
|
||||
Adds `node` to the `list` with a custom pointer to `elem` immediately after
|
||||
the previous list `node`.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
## `Curl_llist_head`
|
||||
|
||||
~~~c
|
||||
struct Curl_llist_node *Curl_llist_head(struct Curl_llist *list);
|
||||
~~~
|
||||
|
||||
Returns a pointer to the first node of the `list`, or a NULL if empty.
|
||||
|
||||
## `Curl_node_uremove`
|
||||
|
||||
~~~c
|
||||
void Curl_node_uremove(struct Curl_llist_node *node, void *user);
|
||||
~~~
|
||||
|
||||
Removes the `node` the list it was previously added to. Passes the `user`
|
||||
pointer to the list's destructor function if one was setup.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
## `Curl_node_remove`
|
||||
|
||||
~~~c
|
||||
void Curl_node_remove(struct Curl_llist_node *node);
|
||||
~~~
|
||||
|
||||
Removes the `node` the list it was previously added to. Passes a NULL pointer
|
||||
to the list's destructor function if one was setup.
|
||||
|
||||
The function is infallible.
|
||||
|
||||
## `Curl_node_elem`
|
||||
|
||||
~~~c
|
||||
void *Curl_node_elem(struct Curl_llist_node *node);
|
||||
~~~
|
||||
|
||||
Given a list node, this function returns the associated element.
|
||||
|
||||
## `Curl_node_next`
|
||||
|
||||
~~~c
|
||||
struct Curl_llist_node *Curl_node_next(struct Curl_llist_node *node);
|
||||
~~~
|
||||
|
||||
Given a list node, this function returns the next node in the list.
|
@ -81,6 +81,7 @@ EXTRA_DIST = \
|
||||
INSTALL.md \
|
||||
INTERNALS.md \
|
||||
IPFS.md \
|
||||
LLIST.md \
|
||||
KNOWN_BUGS \
|
||||
MAIL-ETIQUETTE.md \
|
||||
MANUAL.md \
|
||||
|
44
lib/altsvc.c
44
lib/altsvc.c
@ -337,13 +337,13 @@ CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
|
||||
*/
|
||||
void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
if(*altsvcp) {
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
struct altsvcinfo *altsvc = *altsvcp;
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&altsvc->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
altsvc_free(as);
|
||||
}
|
||||
free(altsvc->filename);
|
||||
@ -358,8 +358,6 @@ void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
|
||||
CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
struct altsvcinfo *altsvc, const char *file)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
CURLcode result = CURLE_OK;
|
||||
FILE *out;
|
||||
char *tempstore = NULL;
|
||||
@ -378,12 +376,14 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
|
||||
result = Curl_fopen(data, file, &out, &tempstore);
|
||||
if(!result) {
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
|
||||
"# This file was generated by libcurl! Edit at your own risk.\n",
|
||||
out);
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&altsvc->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
result = altsvc_out(as, out);
|
||||
if(result)
|
||||
break;
|
||||
@ -440,15 +440,15 @@ static bool hostcompare(const char *host, const char *check)
|
||||
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
|
||||
const char *srchost, unsigned short srcport)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
for(e = Curl_llist_head(&asi->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
if((srcalpnid == as->src.alpnid) &&
|
||||
(srcport == as->src.port) &&
|
||||
hostcompare(srchost, as->src.host)) {
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
altsvc_free(as);
|
||||
}
|
||||
}
|
||||
@ -677,19 +677,19 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
struct altsvc **dstentry,
|
||||
const int versions) /* one or more bits */
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
time_t now = time(NULL);
|
||||
DEBUGASSERT(asi);
|
||||
DEBUGASSERT(srchost);
|
||||
DEBUGASSERT(dstentry);
|
||||
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&asi->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
if(as->expires < now) {
|
||||
/* an expired entry, remove */
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
altsvc_free(as);
|
||||
continue;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ struct altsvc {
|
||||
time_t expires;
|
||||
bool persist;
|
||||
unsigned int prio;
|
||||
struct Curl_llist_element node;
|
||||
struct Curl_llist_node node;
|
||||
};
|
||||
|
||||
struct altsvcinfo {
|
||||
|
109
lib/conncache.c
109
lib/conncache.c
@ -99,17 +99,15 @@ static void bundle_add_conn(struct connectbundle *bundle,
|
||||
static int bundle_remove_conn(struct connectbundle *bundle,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct Curl_llist_element *curr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
struct Curl_llist_node *curr = Curl_llist_head(&bundle->conn_list);
|
||||
while(curr) {
|
||||
if(curr->ptr == conn) {
|
||||
Curl_llist_remove(&bundle->conn_list, curr, NULL);
|
||||
if(Curl_node_elem(curr) == conn) {
|
||||
Curl_node_remove(curr);
|
||||
bundle->num_connections--;
|
||||
conn->bundle = NULL;
|
||||
return 1; /* we removed a handle */
|
||||
}
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
DEBUGASSERT(0);
|
||||
return 0;
|
||||
@ -149,7 +147,6 @@ void Curl_conncache_destroy(struct conncache *connc)
|
||||
if(connc) {
|
||||
Curl_hash_destroy(&connc->hash);
|
||||
connc->multi = NULL;
|
||||
DEBUGASSERT(!Curl_llist_count(&connc->shutdowns.conn_list));
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +338,6 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param))
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
if(!connc)
|
||||
@ -352,17 +348,16 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct connectbundle *bundle;
|
||||
|
||||
bundle = he->ptr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct connectbundle *bundle = he->ptr;
|
||||
he = Curl_hash_next_element(&iter);
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conn_list);
|
||||
while(curr) {
|
||||
/* Yes, we need to update curr before calling func(), because func()
|
||||
might decide to remove the connection */
|
||||
struct connectdata *conn = curr->ptr;
|
||||
curr = curr->next;
|
||||
struct connectdata *conn = Curl_node_elem(curr);
|
||||
curr = Curl_node_next(curr);
|
||||
|
||||
if(1 == func(data, conn, param)) {
|
||||
CONNCACHE_UNLOCK(data);
|
||||
@ -391,12 +386,12 @@ connc_find_first_connection(struct conncache *connc)
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
bundle = he->ptr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conn_list);
|
||||
if(curr) {
|
||||
return curr->ptr;
|
||||
return Curl_node_elem(curr);
|
||||
}
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
@ -451,7 +446,7 @@ struct connectdata *
|
||||
Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
struct connectbundle *bundle)
|
||||
{
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
timediff_t highscore = -1;
|
||||
timediff_t score;
|
||||
struct curltime now;
|
||||
@ -462,9 +457,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
|
||||
now = Curl_now();
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conn_list);
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
conn = Curl_node_elem(curr);
|
||||
|
||||
if(!CONN_INUSE(conn)) {
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
@ -475,7 +470,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
conn_candidate = conn;
|
||||
}
|
||||
}
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
if(conn_candidate) {
|
||||
/* remove it to prevent another thread from nicking it */
|
||||
@ -499,7 +494,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
{
|
||||
struct conncache *connc = data->state.conn_cache;
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct Curl_hash_element *he;
|
||||
timediff_t highscore =- 1;
|
||||
timediff_t score;
|
||||
@ -519,9 +514,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
|
||||
bundle = he->ptr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conn_list);
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
conn = Curl_node_elem(curr);
|
||||
|
||||
if(!CONN_INUSE(conn) && !conn->bits.close &&
|
||||
!conn->connect_only) {
|
||||
@ -534,7 +529,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
bundle_candidate = bundle;
|
||||
}
|
||||
}
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
@ -553,7 +548,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
|
||||
static void connc_shutdown_discard_all(struct conncache *connc)
|
||||
{
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&connc->shutdowns.conn_list);
|
||||
struct connectdata *conn;
|
||||
|
||||
if(!e)
|
||||
@ -563,12 +558,12 @@ static void connc_shutdown_discard_all(struct conncache *connc)
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
while(e) {
|
||||
conn = e->ptr;
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_node_remove(e);
|
||||
DEBUGF(infof(connc->closure_handle, "discard connection #%"
|
||||
CURL_FORMAT_CURL_OFF_T, conn->connection_id));
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
e = connc->shutdowns.conn_list.head;
|
||||
e = Curl_llist_head(&connc->shutdowns.conn_list);
|
||||
}
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
}
|
||||
@ -626,18 +621,18 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
|
||||
|
||||
static void connc_shutdown_discard_oldest(struct conncache *connc)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
struct connectdata *conn;
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
if(connc->shutdowns.iter_locked)
|
||||
return;
|
||||
|
||||
e = connc->shutdowns.conn_list.head;
|
||||
e = Curl_llist_head(&connc->shutdowns.conn_list);
|
||||
if(e) {
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
conn = e->ptr;
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_node_remove(e);
|
||||
sigpipe_init(&pipe_st);
|
||||
sigpipe_apply(connc->closure_handle, &pipe_st);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
@ -840,13 +835,14 @@ CURLcode Curl_conncache_add_pollfds(struct conncache *connc,
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
if(connc->shutdowns.conn_list.head) {
|
||||
struct Curl_llist_element *e;
|
||||
if(Curl_llist_head(&connc->shutdowns.conn_list)) {
|
||||
struct Curl_llist_node *e;
|
||||
struct easy_pollset ps;
|
||||
struct connectdata *conn;
|
||||
|
||||
for(e = connc->shutdowns.conn_list.head; e; e = e->next) {
|
||||
conn = e->ptr;
|
||||
for(e = Curl_llist_head(&connc->shutdowns.conn_list); e;
|
||||
e = Curl_node_next(e)) {
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(connc->closure_handle, conn);
|
||||
Curl_conn_adjust_pollset(connc->closure_handle, &ps);
|
||||
@ -871,13 +867,14 @@ CURLcode Curl_conncache_add_waitfds(struct conncache *connc,
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
if(connc->shutdowns.conn_list.head) {
|
||||
struct Curl_llist_element *e;
|
||||
if(Curl_llist_head(&connc->shutdowns.conn_list)) {
|
||||
struct Curl_llist_node *e;
|
||||
struct easy_pollset ps;
|
||||
struct connectdata *conn;
|
||||
|
||||
for(e = connc->shutdowns.conn_list.head; e; e = e->next) {
|
||||
conn = e->ptr;
|
||||
for(e = Curl_llist_head(&connc->shutdowns.conn_list); e;
|
||||
e = Curl_node_next(e)) {
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(connc->closure_handle, conn);
|
||||
Curl_conn_adjust_pollset(connc->closure_handle, &ps);
|
||||
@ -896,8 +893,8 @@ out:
|
||||
static void connc_perform(struct conncache *connc)
|
||||
{
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct Curl_llist_element *enext;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&connc->shutdowns.conn_list);
|
||||
struct Curl_llist_node *enext;
|
||||
struct connectdata *conn;
|
||||
struct curltime *nowp = NULL;
|
||||
struct curltime now;
|
||||
@ -913,15 +910,15 @@ static void connc_perform(struct conncache *connc)
|
||||
Curl_llist_count(&connc->shutdowns.conn_list)));
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
while(e) {
|
||||
enext = e->next;
|
||||
conn = e->ptr;
|
||||
enext = Curl_node_next(e);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_attach_connection(data, conn);
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" CURL_FORMAT_CURL_OFF_T
|
||||
", done=%d", conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done) {
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
}
|
||||
else {
|
||||
@ -1039,7 +1036,7 @@ void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
||||
{
|
||||
struct conncache *connc = &multi->conn_cache;
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&connc->shutdowns.conn_list);
|
||||
struct connectdata *conn;
|
||||
bool done;
|
||||
|
||||
@ -1050,7 +1047,7 @@ void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
||||
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
while(e) {
|
||||
conn = e->ptr;
|
||||
conn = Curl_node_elem(e);
|
||||
if(s == conn->sock[FIRSTSOCKET] || s == conn->sock[SECONDARYSOCKET]) {
|
||||
Curl_attach_connection(data, conn);
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
@ -1058,12 +1055,12 @@ void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
||||
", done=%d", conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done || connc_update_shutdown_ev(multi, data, conn)) {
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
e = e->next;
|
||||
e = Curl_node_next(e);
|
||||
}
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
}
|
||||
@ -1119,13 +1116,13 @@ static void connc_shutdown_all(struct conncache *connc, int timeout_ms)
|
||||
}
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
while(connc->shutdowns.conn_list.head) {
|
||||
while(Curl_llist_head(&connc->shutdowns.conn_list)) {
|
||||
timediff_t timespent;
|
||||
int remain_ms;
|
||||
|
||||
connc_perform(connc);
|
||||
|
||||
if(!connc->shutdowns.conn_list.head) {
|
||||
if(!Curl_llist_head(&connc->shutdowns.conn_list)) {
|
||||
DEBUGF(infof(data, "conncache shutdown ok"));
|
||||
break;
|
||||
}
|
||||
@ -1154,7 +1151,7 @@ static void connc_shutdown_all(struct conncache *connc, int timeout_ms)
|
||||
void Curl_conncache_print(struct conncache *connc)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
if(!connc)
|
||||
@ -1172,12 +1169,12 @@ void Curl_conncache_print(struct conncache *connc)
|
||||
bundle = he->ptr;
|
||||
|
||||
fprintf(stderr, "%s -", he->key);
|
||||
curr = bundle->conn_list->head;
|
||||
curr = Curl_llist_head(bundle->conn_list);
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
conn = Curl_node_elem(curr);
|
||||
|
||||
fprintf(stderr, " [%p %d]", (void *)conn, conn->refcount);
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
|
@ -597,10 +597,10 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
}
|
||||
else {
|
||||
/* here pollrc is > 0 */
|
||||
struct Curl_llist_element *e = multi->process.head;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&multi->process);
|
||||
struct Curl_easy *data;
|
||||
DEBUGASSERT(e);
|
||||
data = e->ptr;
|
||||
data = Curl_node_elem(e);
|
||||
DEBUGASSERT(data);
|
||||
|
||||
/* loop over the monitored sockets to see which ones had activity */
|
||||
@ -1018,7 +1018,9 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* USE_ARES */
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&outcurl->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_initinfo(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
struct fileinfo {
|
||||
struct curl_fileinfo info;
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
struct dynbuf buf;
|
||||
};
|
||||
|
||||
|
17
lib/ftp.c
17
lib/ftp.c
@ -4037,7 +4037,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
continue;
|
||||
}
|
||||
if(wildcard->filelist.size == 0) {
|
||||
if(Curl_llist_count(&wildcard->filelist) == 0) {
|
||||
/* no corresponding file */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
@ -4048,7 +4048,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
case CURLWC_DOWNLOADING: {
|
||||
/* filelist has at least one file, lets get first one */
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
|
||||
struct Curl_llist_node *head = Curl_llist_head(&wildcard->filelist);
|
||||
struct curl_fileinfo *finfo = Curl_node_elem(head);
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
|
||||
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
|
||||
@ -4064,7 +4065,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
long userresponse;
|
||||
Curl_set_in_callback(data, true);
|
||||
userresponse = data->set.chunk_bgn(
|
||||
finfo, data->set.wildcardptr, (int)wildcard->filelist.size);
|
||||
finfo, data->set.wildcardptr,
|
||||
(int)Curl_llist_count(&wildcard->filelist));
|
||||
Curl_set_in_callback(data, false);
|
||||
switch(userresponse) {
|
||||
case CURL_CHUNK_BGN_FUNC_SKIP:
|
||||
@ -4090,9 +4092,10 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
return result;
|
||||
|
||||
/* we do not need the Curl_fileinfo of first file anymore */
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
Curl_node_remove(Curl_llist_head(&wildcard->filelist));
|
||||
|
||||
if(wildcard->filelist.size == 0) { /* remains only one file to down. */
|
||||
if(Curl_llist_count(&wildcard->filelist) == 0) {
|
||||
/* remains only one file to down. */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
/* after that will be ftp_do called once again and no transfer
|
||||
will be done because of CURLWC_CLEAN state */
|
||||
@ -4107,8 +4110,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
data->set.chunk_end(data->set.wildcardptr);
|
||||
Curl_set_in_callback(data, false);
|
||||
}
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
wildcard->state = (wildcard->filelist.size == 0) ?
|
||||
Curl_node_remove(Curl_llist_head(&wildcard->filelist));
|
||||
wildcard->state = (Curl_llist_count(&wildcard->filelist) == 0) ?
|
||||
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
||||
continue;
|
||||
}
|
||||
|
51
lib/hash.c
51
lib/hash.c
@ -102,7 +102,7 @@ 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;
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
@ -118,10 +118,10 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for(le = l->head; le; le = le->next) {
|
||||
he = (struct Curl_hash_element *) le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
he = (struct Curl_hash_element *) Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *)h);
|
||||
Curl_node_uremove(le, (void *)h);
|
||||
--h->size;
|
||||
break;
|
||||
}
|
||||
@ -158,18 +158,16 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
||||
*/
|
||||
int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->slots);
|
||||
if(h->table) {
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for(le = l->head; le; le = le->next) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *) h);
|
||||
Curl_node_uremove(le, (void *) h);
|
||||
--h->size;
|
||||
return 0;
|
||||
}
|
||||
@ -185,15 +183,14 @@ int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
|
||||
void *
|
||||
Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
if(h->table) {
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l;
|
||||
DEBUGASSERT(h->slots);
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
for(le = l->head; le; le = le->next) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
return he->ptr;
|
||||
}
|
||||
@ -239,23 +236,21 @@ void
|
||||
Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
|
||||
int (*comp)(void *, void *))
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist_element *lnext;
|
||||
struct Curl_llist *list;
|
||||
size_t i;
|
||||
|
||||
if(!h || !h->table)
|
||||
return;
|
||||
|
||||
for(i = 0; i < h->slots; ++i) {
|
||||
list = &h->table[i];
|
||||
le = list->head; /* get first list entry */
|
||||
struct Curl_llist *list = &h->table[i];
|
||||
struct Curl_llist_node *le =
|
||||
Curl_llist_head(list); /* get first list entry */
|
||||
while(le) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
lnext = le->next;
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
struct Curl_llist_node *lnext = Curl_node_next(le);
|
||||
/* ask the callback function if we shall remove this entry or not */
|
||||
if(!comp || comp(user, he->ptr)) {
|
||||
Curl_llist_remove(list, le, (void *) h);
|
||||
Curl_node_uremove(le, (void *) h);
|
||||
--h->size; /* one less entry in the hash now */
|
||||
}
|
||||
le = lnext;
|
||||
@ -305,14 +300,14 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
|
||||
|
||||
/* Get the next element in the current list, if any */
|
||||
if(iter->current_element)
|
||||
iter->current_element = iter->current_element->next;
|
||||
iter->current_element = Curl_node_next(iter->current_element);
|
||||
|
||||
/* If we have reached the end of the list, find the next one */
|
||||
if(!iter->current_element) {
|
||||
size_t i;
|
||||
for(i = iter->slot_index; i < h->slots; i++) {
|
||||
if(h->table[i].head) {
|
||||
iter->current_element = h->table[i].head;
|
||||
if(Curl_llist_head(&h->table[i])) {
|
||||
iter->current_element = Curl_llist_head(&h->table[i]);
|
||||
iter->slot_index = i + 1;
|
||||
break;
|
||||
}
|
||||
@ -320,7 +315,7 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
|
||||
}
|
||||
|
||||
if(iter->current_element) {
|
||||
struct Curl_hash_element *he = iter->current_element->ptr;
|
||||
struct Curl_hash_element *he = Curl_node_elem(iter->current_element);
|
||||
return he;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -61,7 +61,7 @@ struct Curl_hash {
|
||||
typedef void (*Curl_hash_elem_dtor)(void *key, size_t key_len, void *p);
|
||||
|
||||
struct Curl_hash_element {
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
void *ptr;
|
||||
Curl_hash_elem_dtor dtor;
|
||||
size_t key_len;
|
||||
@ -71,7 +71,7 @@ struct Curl_hash_element {
|
||||
struct Curl_hash_iterator {
|
||||
struct Curl_hash *hash;
|
||||
size_t slot_index;
|
||||
struct Curl_llist_element *current_element;
|
||||
struct Curl_llist_node *current_element;
|
||||
};
|
||||
|
||||
void Curl_hash_init(struct Curl_hash *h,
|
||||
|
@ -42,7 +42,7 @@
|
||||
static void copy_header_external(struct Curl_header_store *hs,
|
||||
size_t index,
|
||||
size_t amount,
|
||||
struct Curl_llist_element *e,
|
||||
struct Curl_llist_node *e,
|
||||
struct curl_header *hout)
|
||||
{
|
||||
struct curl_header *h = hout;
|
||||
@ -66,8 +66,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
int request,
|
||||
struct curl_header **hout)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *e_pick = NULL;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *e_pick = NULL;
|
||||
struct Curl_easy *data = easy;
|
||||
size_t match = 0;
|
||||
size_t amount = 0;
|
||||
@ -85,8 +85,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
request = data->state.requests;
|
||||
|
||||
/* we need a first round to count amount of this header */
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
hs = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
hs = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, name) &&
|
||||
(hs->type & type) &&
|
||||
(hs->request == request)) {
|
||||
@ -104,8 +104,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
/* if the last or only occurrence is what's asked for, then we know it */
|
||||
hs = pick;
|
||||
else {
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
hs = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
hs = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, name) &&
|
||||
(hs->type & type) &&
|
||||
(hs->request == request) &&
|
||||
@ -131,8 +131,8 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
struct curl_header *prev)
|
||||
{
|
||||
struct Curl_easy *data = easy;
|
||||
struct Curl_llist_element *pick;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *pick;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_header_store *hs;
|
||||
size_t amount = 0;
|
||||
size_t index = 0;
|
||||
@ -147,18 +147,18 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
if(!pick)
|
||||
/* something is wrong */
|
||||
return NULL;
|
||||
pick = pick->next;
|
||||
pick = Curl_node_next(pick);
|
||||
}
|
||||
else
|
||||
pick = data->state.httphdrs.head;
|
||||
pick = Curl_llist_head(&data->state.httphdrs);
|
||||
|
||||
if(pick) {
|
||||
/* make sure it is the next header of the desired type */
|
||||
do {
|
||||
hs = pick->ptr;
|
||||
hs = Curl_node_elem(pick);
|
||||
if((hs->type & type) && (hs->request == request))
|
||||
break;
|
||||
pick = pick->next;
|
||||
pick = Curl_node_next(pick);
|
||||
} while(pick);
|
||||
}
|
||||
|
||||
@ -166,12 +166,12 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
/* no more headers available */
|
||||
return NULL;
|
||||
|
||||
hs = pick->ptr;
|
||||
hs = Curl_node_elem(pick);
|
||||
|
||||
/* count number of occurrences of this name within the mask and figure out
|
||||
the index for the currently selected entry */
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
struct Curl_header_store *check = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
struct Curl_header_store *check = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, check->name) &&
|
||||
(check->request == request) &&
|
||||
(check->type & type))
|
||||
@ -247,7 +247,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
|
||||
/* since this header block might move in the realloc below, it needs to
|
||||
first be unlinked from the list and then re-added again after the
|
||||
realloc */
|
||||
Curl_llist_remove(&data->state.httphdrs, &hs->node, NULL);
|
||||
Curl_node_remove(&hs->node);
|
||||
|
||||
/* new size = struct + new value length + old name+value length */
|
||||
newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1);
|
||||
@ -405,12 +405,12 @@ CURLcode Curl_headers_init(struct Curl_easy *data)
|
||||
*/
|
||||
CURLcode Curl_headers_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
|
||||
for(e = data->state.httphdrs.head; e; e = n) {
|
||||
struct Curl_header_store *hs = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = n) {
|
||||
struct Curl_header_store *hs = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
free(hs);
|
||||
}
|
||||
headers_reset(data);
|
||||
|
@ -28,7 +28,7 @@
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
|
||||
|
||||
struct Curl_header_store {
|
||||
struct Curl_llist_element node;
|
||||
struct Curl_llist_node node;
|
||||
char *name; /* points into 'buffer' */
|
||||
char *value; /* points into 'buffer */
|
||||
int request; /* 0 is the first request, then 1.. 2.. */
|
||||
|
42
lib/hsts.c
42
lib/hsts.c
@ -94,11 +94,11 @@ void Curl_hsts_cleanup(struct hsts **hp)
|
||||
{
|
||||
struct hsts *h = *hp;
|
||||
if(h) {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
for(e = h->list.head; e; e = n) {
|
||||
struct stsentry *sts = e->ptr;
|
||||
n = e->next;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
for(e = Curl_llist_head(&h->list); e; e = n) {
|
||||
struct stsentry *sts = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
hsts_free(sts);
|
||||
}
|
||||
free(h->filename);
|
||||
@ -215,7 +215,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
|
||||
/* remove the entry if present verbatim (without subdomain match) */
|
||||
sts = Curl_hsts(h, hostname, FALSE);
|
||||
if(sts) {
|
||||
Curl_llist_remove(&h->list, &sts->node, NULL);
|
||||
Curl_node_remove(&sts->node);
|
||||
hsts_free(sts);
|
||||
}
|
||||
return CURLE_OK;
|
||||
@ -253,8 +253,8 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
|
||||
char buffer[MAX_HSTS_HOSTLEN + 1];
|
||||
time_t now = time(NULL);
|
||||
size_t hlen = strlen(hostname);
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
|
||||
if((hlen > MAX_HSTS_HOSTLEN) || !hlen)
|
||||
return NULL;
|
||||
@ -265,12 +265,12 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
|
||||
buffer[hlen] = 0;
|
||||
hostname = buffer;
|
||||
|
||||
for(e = h->list.head; e; e = n) {
|
||||
struct stsentry *sts = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&h->list); e; e = n) {
|
||||
struct stsentry *sts = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
if(sts->expires <= now) {
|
||||
/* remove expired entries */
|
||||
Curl_llist_remove(&h->list, &sts->node, NULL);
|
||||
Curl_node_remove(&sts->node);
|
||||
hsts_free(sts);
|
||||
continue;
|
||||
}
|
||||
@ -353,8 +353,8 @@ static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
|
||||
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
|
||||
const char *file)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
CURLcode result = CURLE_OK;
|
||||
FILE *out;
|
||||
char *tempstore = NULL;
|
||||
@ -376,9 +376,9 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
|
||||
fputs("# Your HSTS cache. https://curl.se/docs/hsts.html\n"
|
||||
"# This file was generated by libcurl! Edit at your own risk.\n",
|
||||
out);
|
||||
for(e = h->list.head; e; e = n) {
|
||||
struct stsentry *sts = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&h->list); e; e = n) {
|
||||
struct stsentry *sts = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
result = hsts_out(sts, out);
|
||||
if(result)
|
||||
break;
|
||||
@ -395,12 +395,12 @@ skipsave:
|
||||
if(data->set.hsts_write) {
|
||||
/* if there is a write callback */
|
||||
struct curl_index i; /* count */
|
||||
i.total = h->list.size;
|
||||
i.total = Curl_llist_count(&h->list);
|
||||
i.index = 0;
|
||||
for(e = h->list.head; e; e = n) {
|
||||
struct stsentry *sts = e->ptr;
|
||||
for(e = Curl_llist_head(&h->list); e; e = n) {
|
||||
struct stsentry *sts = Curl_node_elem(e);
|
||||
bool stop;
|
||||
n = e->next;
|
||||
n = Curl_node_next(e);
|
||||
result = hsts_push(data, &i, sts, &stop);
|
||||
if(result || stop)
|
||||
break;
|
||||
|
@ -34,7 +34,7 @@ extern time_t deltatime;
|
||||
#endif
|
||||
|
||||
struct stsentry {
|
||||
struct Curl_llist_element node;
|
||||
struct Curl_llist_node node;
|
||||
const char *host;
|
||||
bool includeSubDomains;
|
||||
curl_off_t expires; /* the timestamp of this entry's expiry */
|
||||
|
@ -3118,7 +3118,7 @@ CURLcode Curl_http_header(struct Curl_easy *data,
|
||||
#ifdef DEBUGBUILD
|
||||
else
|
||||
infof(data, "Parsed STS header fine (%zu entries)",
|
||||
data->hsts->list.size);
|
||||
Curl_llist_count(&data->hsts->list));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
190
lib/llist.c
190
lib/llist.c
@ -32,16 +32,34 @@
|
||||
/* this must be the last include file */
|
||||
#include "memdebug.h"
|
||||
|
||||
#define LLISTINIT 0x100cc001 /* random pattern */
|
||||
#define NODEINIT 0x12344321 /* random pattern */
|
||||
#define NODEREM 0x54321012 /* random pattern */
|
||||
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#define VERIFYNODE(x) verifynode(x)
|
||||
static struct Curl_llist_node *verifynode(struct Curl_llist_node *n)
|
||||
{
|
||||
DEBUGASSERT(!n || (n->_init == NODEINIT));
|
||||
return n;
|
||||
}
|
||||
#else
|
||||
#define VERIFYNODE(x) x
|
||||
#endif
|
||||
/*
|
||||
* @unittest: 1300
|
||||
*/
|
||||
void
|
||||
Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor)
|
||||
{
|
||||
l->size = 0;
|
||||
l->dtor = dtor;
|
||||
l->head = NULL;
|
||||
l->tail = NULL;
|
||||
l->_size = 0;
|
||||
l->_dtor = dtor;
|
||||
l->_head = NULL;
|
||||
l->_tail = NULL;
|
||||
#ifdef DEBUGBUILD
|
||||
l->_init = LLISTINIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -56,36 +74,45 @@ Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor)
|
||||
* @unittest: 1300
|
||||
*/
|
||||
void
|
||||
Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e,
|
||||
Curl_llist_insert_next(struct Curl_llist *list,
|
||||
struct Curl_llist_node *e, /* may be NULL */
|
||||
const void *p,
|
||||
struct Curl_llist_element *ne)
|
||||
struct Curl_llist_node *ne)
|
||||
{
|
||||
ne->ptr = (void *) p;
|
||||
if(list->size == 0) {
|
||||
list->head = ne;
|
||||
list->head->prev = NULL;
|
||||
list->head->next = NULL;
|
||||
list->tail = ne;
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
DEBUGASSERT(ne);
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
ne->_init = NODEINIT;
|
||||
#endif
|
||||
ne->_ptr = (void *) p;
|
||||
ne->_list = list;
|
||||
if(list->_size == 0) {
|
||||
list->_head = ne;
|
||||
list->_head->_prev = NULL;
|
||||
list->_head->_next = NULL;
|
||||
list->_tail = ne;
|
||||
}
|
||||
else {
|
||||
/* if 'e' is NULL here, we insert the new element first in the list */
|
||||
ne->next = e?e->next:list->head;
|
||||
ne->prev = e;
|
||||
ne->_next = e?e->_next:list->_head;
|
||||
ne->_prev = e;
|
||||
if(!e) {
|
||||
list->head->prev = ne;
|
||||
list->head = ne;
|
||||
list->_head->_prev = ne;
|
||||
list->_head = ne;
|
||||
}
|
||||
else if(e->next) {
|
||||
e->next->prev = ne;
|
||||
else if(e->_next) {
|
||||
e->_next->_prev = ne;
|
||||
}
|
||||
else {
|
||||
list->tail = ne;
|
||||
list->_tail = ne;
|
||||
}
|
||||
if(e)
|
||||
e->next = ne;
|
||||
e->_next = ne;
|
||||
}
|
||||
|
||||
++list->size;
|
||||
++list->_size;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -99,64 +126,131 @@ Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e,
|
||||
*/
|
||||
void
|
||||
Curl_llist_append(struct Curl_llist *list, const void *p,
|
||||
struct Curl_llist_element *ne)
|
||||
struct Curl_llist_node *ne)
|
||||
{
|
||||
Curl_llist_insert_next(list, list->tail, p, ne);
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
DEBUGASSERT(ne);
|
||||
Curl_llist_insert_next(list, list->_tail, p, ne);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unittest: 1300
|
||||
*/
|
||||
void
|
||||
Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e,
|
||||
void *user)
|
||||
Curl_node_uremove(struct Curl_llist_node *e, void *user)
|
||||
{
|
||||
void *ptr;
|
||||
if(!e || list->size == 0)
|
||||
struct Curl_llist *list;
|
||||
if(!e)
|
||||
return;
|
||||
|
||||
if(e == list->head) {
|
||||
list->head = e->next;
|
||||
list = e->_list;
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
DEBUGASSERT(list->_size);
|
||||
DEBUGASSERT(e->_init == NODEINIT);
|
||||
if(e == list->_head) {
|
||||
list->_head = e->_next;
|
||||
|
||||
if(!list->head)
|
||||
list->tail = NULL;
|
||||
if(!list->_head)
|
||||
list->_tail = NULL;
|
||||
else
|
||||
e->next->prev = NULL;
|
||||
e->_next->_prev = NULL;
|
||||
}
|
||||
else {
|
||||
if(e->prev)
|
||||
e->prev->next = e->next;
|
||||
if(e->_prev)
|
||||
e->_prev->_next = e->_next;
|
||||
|
||||
if(!e->next)
|
||||
list->tail = e->prev;
|
||||
if(!e->_next)
|
||||
list->_tail = e->_prev;
|
||||
else
|
||||
e->next->prev = e->prev;
|
||||
e->_next->_prev = e->_prev;
|
||||
}
|
||||
|
||||
ptr = e->ptr;
|
||||
ptr = e->_ptr;
|
||||
|
||||
e->ptr = NULL;
|
||||
e->prev = NULL;
|
||||
e->next = NULL;
|
||||
e->_ptr = NULL;
|
||||
e->_prev = NULL;
|
||||
e->_next = NULL;
|
||||
#ifdef DEBUGBUILD
|
||||
e->_init = NODEREM; /* specific pattern on remove - not zero */
|
||||
#endif
|
||||
|
||||
--list->size;
|
||||
--list->_size;
|
||||
|
||||
/* call the dtor() last for when it actually frees the 'e' memory itself */
|
||||
if(list->dtor)
|
||||
list->dtor(user, ptr);
|
||||
if(list->_dtor)
|
||||
list->_dtor(user, ptr);
|
||||
}
|
||||
|
||||
void Curl_node_remove(struct Curl_llist_node *e)
|
||||
{
|
||||
Curl_node_uremove(e, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
Curl_llist_destroy(struct Curl_llist *list, void *user)
|
||||
{
|
||||
if(list) {
|
||||
while(list->size > 0)
|
||||
Curl_llist_remove(list, list->tail, user);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
while(list->_size > 0)
|
||||
Curl_node_uremove(list->_tail, user);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
Curl_llist_count(struct Curl_llist *list)
|
||||
/* Curl_llist_head() returns the first 'struct Curl_llist_node *', which
|
||||
might be NULL */
|
||||
struct Curl_llist_node *Curl_llist_head(struct Curl_llist *list)
|
||||
{
|
||||
return list->size;
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
return VERIFYNODE(list->_head);
|
||||
}
|
||||
|
||||
/* Curl_llist_tail() returns the last 'struct Curl_llist_node *', which
|
||||
might be NULL */
|
||||
struct Curl_llist_node *Curl_llist_tail(struct Curl_llist *list)
|
||||
{
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
return VERIFYNODE(list->_tail);
|
||||
}
|
||||
|
||||
/* Curl_llist_count() returns a size_t the number of nodes in the list */
|
||||
size_t Curl_llist_count(struct Curl_llist *list)
|
||||
{
|
||||
DEBUGASSERT(list);
|
||||
DEBUGASSERT(list->_init == LLISTINIT);
|
||||
return list->_size;
|
||||
}
|
||||
|
||||
/* Curl_node_elem() returns the custom data from a Curl_llist_node */
|
||||
void *Curl_node_elem(struct Curl_llist_node *n)
|
||||
{
|
||||
DEBUGASSERT(n);
|
||||
DEBUGASSERT(n->_init == NODEINIT);
|
||||
return n->_ptr;
|
||||
}
|
||||
|
||||
/* Curl_node_next() returns the next element in a list from a given
|
||||
Curl_llist_node */
|
||||
struct Curl_llist_node *Curl_node_next(struct Curl_llist_node *n)
|
||||
{
|
||||
DEBUGASSERT(n);
|
||||
DEBUGASSERT(n->_init == NODEINIT);
|
||||
return VERIFYNODE(n->_next);
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
|
||||
/* Curl_node_prev() returns the previous element in a list from a given
|
||||
Curl_llist_node */
|
||||
struct Curl_llist_node *Curl_node_prev(struct Curl_llist_node *n)
|
||||
{
|
||||
DEBUGASSERT(n);
|
||||
DEBUGASSERT(n->_init == NODEINIT);
|
||||
return VERIFYNODE(n->_prev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
64
lib/llist.h
64
lib/llist.h
@ -27,28 +27,60 @@
|
||||
#include "curl_setup.h"
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void (*Curl_llist_dtor)(void *, void *);
|
||||
typedef void (*Curl_llist_dtor)(void *user, void *elem);
|
||||
|
||||
struct Curl_llist_element {
|
||||
void *ptr;
|
||||
struct Curl_llist_element *prev;
|
||||
struct Curl_llist_element *next;
|
||||
};
|
||||
/* none of these struct members should be referenced directly, use the
|
||||
dedicated functions */
|
||||
|
||||
struct Curl_llist {
|
||||
struct Curl_llist_element *head;
|
||||
struct Curl_llist_element *tail;
|
||||
Curl_llist_dtor dtor;
|
||||
size_t size;
|
||||
struct Curl_llist_node *_head;
|
||||
struct Curl_llist_node *_tail;
|
||||
Curl_llist_dtor _dtor;
|
||||
size_t _size;
|
||||
#ifdef DEBUGBUILD
|
||||
int _init; /* detect API usage mistakes */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Curl_llist_node {
|
||||
struct Curl_llist *_list; /* the list where this belongs */
|
||||
void *_ptr;
|
||||
struct Curl_llist_node *_prev;
|
||||
struct Curl_llist_node *_next;
|
||||
#ifdef DEBUGBUILD
|
||||
int _init; /* detect API usage mistakes */
|
||||
#endif
|
||||
};
|
||||
|
||||
void Curl_llist_init(struct Curl_llist *, Curl_llist_dtor);
|
||||
void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_element *,
|
||||
const void *, struct Curl_llist_element *node);
|
||||
void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_node *,
|
||||
const void *, struct Curl_llist_node *node);
|
||||
void Curl_llist_append(struct Curl_llist *,
|
||||
const void *, struct Curl_llist_element *node);
|
||||
void Curl_llist_remove(struct Curl_llist *, struct Curl_llist_element *,
|
||||
void *);
|
||||
size_t Curl_llist_count(struct Curl_llist *);
|
||||
const void *, struct Curl_llist_node *node);
|
||||
void Curl_node_uremove(struct Curl_llist_node *, void *);
|
||||
void Curl_node_remove(struct Curl_llist_node *);
|
||||
void Curl_llist_destroy(struct Curl_llist *, void *);
|
||||
|
||||
/* Curl_llist_head() returns the first 'struct Curl_llist_node *', which
|
||||
might be NULL */
|
||||
struct Curl_llist_node *Curl_llist_head(struct Curl_llist *list);
|
||||
|
||||
/* Curl_llist_tail() returns the last 'struct Curl_llist_node *', which
|
||||
might be NULL */
|
||||
struct Curl_llist_node *Curl_llist_tail(struct Curl_llist *list);
|
||||
|
||||
/* Curl_llist_count() returns a size_t the number of nodes in the list */
|
||||
size_t Curl_llist_count(struct Curl_llist *list);
|
||||
|
||||
/* Curl_node_elem() returns the custom data from a Curl_llist_node */
|
||||
void *Curl_node_elem(struct Curl_llist_node *n);
|
||||
|
||||
/* Curl_node_next() returns the next element in a list from a given
|
||||
Curl_llist_node */
|
||||
struct Curl_llist_node *Curl_node_next(struct Curl_llist_node *n);
|
||||
|
||||
/* Curl_node_prev() returns the previous element in a list from a given
|
||||
Curl_llist_node */
|
||||
struct Curl_llist_node *Curl_node_prev(struct Curl_llist_node *n);
|
||||
|
||||
#endif /* HEADER_CURL_LLIST_H */
|
||||
|
178
lib/multi.c
178
lib/multi.c
@ -467,21 +467,6 @@ static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
|
||||
#define multi_warn_debug(x,y) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
static void link_easy(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
/* add the easy handle to the process list */
|
||||
Curl_llist_append(&multi->process, data, &data->multi_queue);
|
||||
}
|
||||
|
||||
/* unlink the given easy handle from the process list */
|
||||
static void unlink_easy(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
Curl_llist_remove(&multi->process, &data->multi_queue, NULL);
|
||||
}
|
||||
|
||||
|
||||
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
@ -557,8 +542,10 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
|
||||
|
||||
rc = Curl_update_timer(multi);
|
||||
if(rc)
|
||||
if(rc) {
|
||||
data->multi = NULL; /* not anymore */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* set the easy handle */
|
||||
multistate(data, MSTATE_INIT);
|
||||
@ -586,7 +573,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
data->psl = &multi->psl;
|
||||
#endif
|
||||
|
||||
link_easy(multi, data);
|
||||
/* add the easy handle to the process list */
|
||||
Curl_llist_append(&multi->process, data, &data->multi_queue);
|
||||
|
||||
/* increase the node-counter */
|
||||
multi->num_easy++;
|
||||
@ -706,7 +694,7 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
CONNCACHE_UNLOCK(data);
|
||||
DEBUGF(infof(data, "Connection still in use %zu, "
|
||||
"no more multi_done now!",
|
||||
conn->easyq.size));
|
||||
Curl_llist_count(&conn->easyq)));
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -804,7 +792,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
{
|
||||
struct Curl_easy *easy = data;
|
||||
bool premature;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
CURLMcode rc;
|
||||
|
||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||
@ -812,7 +800,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
/* Verify that we got a somewhat good easy handle too */
|
||||
if(!GOOD_EASY_HANDLE(data))
|
||||
if(!GOOD_EASY_HANDLE(data) || !multi->num_easy)
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
|
||||
/* Prevent users from trying to remove same easy handle more than once */
|
||||
@ -858,15 +846,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
called. Do it after multi_done() in case that sets another time! */
|
||||
Curl_expire_clear(data);
|
||||
|
||||
if(data->multi_queue.ptr) {
|
||||
/* the handle is in a list, remove it from the right one */
|
||||
if(data->mstate == MSTATE_PENDING)
|
||||
Curl_llist_remove(&multi->pending, &data->multi_queue, NULL);
|
||||
else if(data->mstate == MSTATE_MSGSENT)
|
||||
Curl_llist_remove(&multi->msgsent, &data->multi_queue, NULL);
|
||||
else
|
||||
Curl_llist_remove(&multi->process, &data->multi_queue, NULL);
|
||||
}
|
||||
/* the handle is in a list, remove it from whichever it is */
|
||||
Curl_node_remove(&data->multi_queue);
|
||||
|
||||
if(data->dns.hostcachetype == HCACHE_MULTI) {
|
||||
/* stop using the multi handle's DNS cache, *after* the possible
|
||||
@ -927,11 +908,11 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
|
||||
/* make sure there is no pending message in the queue sent from this easy
|
||||
handle */
|
||||
for(e = multi->msglist.head; e; e = e->next) {
|
||||
struct Curl_message *msg = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->msglist); e; e = Curl_node_next(e)) {
|
||||
struct Curl_message *msg = Curl_node_elem(e);
|
||||
|
||||
if(msg->extmsg.easy_handle == easy) {
|
||||
Curl_llist_remove(&multi->msglist, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
/* there can only be one from this specific handle */
|
||||
break;
|
||||
}
|
||||
@ -966,7 +947,7 @@ void Curl_detach_connection(struct Curl_easy *data)
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn) {
|
||||
Curl_conn_ev_data_detach(conn, data);
|
||||
Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
|
||||
Curl_node_remove(&data->conn_queue);
|
||||
}
|
||||
data->conn = NULL;
|
||||
}
|
||||
@ -1181,7 +1162,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
|
||||
and then we must make sure that is done. */
|
||||
int this_max_fd = -1;
|
||||
struct easy_pollset ps;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
(void)exc_fd_set; /* not used */
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
@ -1191,8 +1172,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
|
||||
return CURLM_RECURSIVE_API_CALL;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
for(e = multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
unsigned int i;
|
||||
|
||||
multi_getsock(data, &ps);
|
||||
@ -1223,7 +1204,7 @@ CURLMcode curl_multi_waitfds(struct Curl_multi *multi,
|
||||
struct curl_waitfds cwfds;
|
||||
struct easy_pollset ps;
|
||||
CURLMcode result = CURLM_OK;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
if(!ufds)
|
||||
return CURLM_BAD_FUNCTION_ARGUMENT;
|
||||
@ -1236,8 +1217,8 @@ CURLMcode curl_multi_waitfds(struct Curl_multi *multi,
|
||||
|
||||
Curl_waitfds_init(&cwfds, ufds, size);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
for(e = multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
multi_getsock(data, &ps);
|
||||
if(Curl_waitfds_add_ps(&cwfds, &ps)) {
|
||||
result = CURLM_OUT_OF_MEMORY;
|
||||
@ -1290,7 +1271,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
struct curl_pollfds cpfds;
|
||||
unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
|
||||
CURLMcode result = CURLM_OK;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSANETWORKEVENTS wsa_events;
|
||||
@ -1313,8 +1294,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
|
||||
/* Add the curl handles to our pollfds first */
|
||||
for(e = multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
|
||||
multi_getsock(data, &ps);
|
||||
if(Curl_pollfds_add_ps(&cpfds, &ps)) {
|
||||
@ -1453,8 +1434,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
/* Count up all our own sockets that had activity,
|
||||
and remove them from the event. */
|
||||
if(curl_nfds) {
|
||||
for(e = multi->process.head; e && !result; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e && !result;
|
||||
e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
multi_getsock(data, &ps);
|
||||
|
||||
for(i = 0; i < ps.num; i++) {
|
||||
@ -1948,7 +1930,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
state and wait for an available connection. */
|
||||
multistate(data, MSTATE_PENDING);
|
||||
/* unlink from process list */
|
||||
unlink_easy(multi, data);
|
||||
Curl_node_remove(&data->multi_queue);
|
||||
/* add handle to pending list */
|
||||
Curl_llist_append(&multi->pending, data, &data->multi_queue);
|
||||
result = CURLE_OK;
|
||||
@ -2661,9 +2643,9 @@ statemachine_end:
|
||||
}
|
||||
multistate(data, MSTATE_MSGSENT);
|
||||
|
||||
/* unlink from the main list */
|
||||
unlink_easy(multi, data);
|
||||
/* add this handle to the list of msgsent handles */
|
||||
/* unlink from the process list */
|
||||
Curl_node_remove(&data->multi_queue);
|
||||
/* add this handle msgsent list */
|
||||
Curl_llist_append(&multi->msgsent, data, &data->multi_queue);
|
||||
return CURLM_OK;
|
||||
}
|
||||
@ -2679,8 +2661,8 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
|
||||
CURLMcode returncode = CURLM_OK;
|
||||
struct Curl_tree *t;
|
||||
struct curltime now = Curl_now();
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n = NULL;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n = NULL;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
@ -2690,15 +2672,15 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
|
||||
return CURLM_RECURSIVE_API_CALL;
|
||||
|
||||
sigpipe_init(&pipe_st);
|
||||
for(e = multi->process.head; e; e = n) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = n) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
CURLMcode result;
|
||||
/* Do the loop and only alter the signal ignore state if the next handle
|
||||
has a different NO_SIGNAL state than the previous */
|
||||
|
||||
/* the current node might be unlinked in multi_runsingle(), get the next
|
||||
pointer now */
|
||||
n = e->next;
|
||||
n = Curl_node_next(e);
|
||||
|
||||
if(data != multi->conn_cache.closure_handle) {
|
||||
/* connection cache handle is processed below */
|
||||
@ -2755,14 +2737,14 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
|
||||
the process list */
|
||||
static void unlink_all_msgsent_handles(struct Curl_multi *multi)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
for(e = multi->msgsent.head; e; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
struct Curl_llist_node *e;
|
||||
for(e = Curl_llist_head(&multi->msgsent); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
if(data) {
|
||||
DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
|
||||
Curl_llist_remove(&multi->msgsent, &data->multi_queue, NULL);
|
||||
Curl_node_remove(&data->multi_queue);
|
||||
/* put it into the process list */
|
||||
link_easy(multi, data);
|
||||
Curl_llist_append(&multi->process, data, &data->multi_queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2770,8 +2752,8 @@ static void unlink_all_msgsent_handles(struct Curl_multi *multi)
|
||||
CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
|
||||
{
|
||||
if(GOOD_MULTI_HANDLE(multi)) {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
if(multi->in_callback)
|
||||
return CURLM_RECURSIVE_API_CALL;
|
||||
|
||||
@ -2783,13 +2765,13 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
|
||||
process_pending_handles(multi);
|
||||
|
||||
/* First remove all remaining easy handles */
|
||||
for(e = multi->process.head; e; e = n) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = n) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
|
||||
if(!GOOD_EASY_HANDLE(data))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
n = e->next;
|
||||
n = Curl_node_next(e);
|
||||
if(!data->state.done && data->conn)
|
||||
/* if DONE was never called for this handle */
|
||||
(void)multi_done(data, CURLE_OK, TRUE);
|
||||
@ -2858,15 +2840,15 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
|
||||
!multi->in_callback &&
|
||||
Curl_llist_count(&multi->msglist)) {
|
||||
/* there is one or more messages in the list */
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
/* extract the head of the list to return */
|
||||
e = multi->msglist.head;
|
||||
e = Curl_llist_head(&multi->msglist);
|
||||
|
||||
msg = e->ptr;
|
||||
msg = Curl_node_elem(e);
|
||||
|
||||
/* remove the extracted entry */
|
||||
Curl_llist_remove(&multi->msglist, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
|
||||
*msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
|
||||
|
||||
@ -3110,26 +3092,24 @@ static CURLMcode add_next_timeout(struct curltime now,
|
||||
{
|
||||
struct curltime *tv = &d->state.expiretime;
|
||||
struct Curl_llist *list = &d->state.timeoutlist;
|
||||
struct Curl_llist_element *e;
|
||||
struct time_node *node = NULL;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
/* move over the timeout list for this specific handle and remove all
|
||||
timeouts that are now passed tense and store the next pending
|
||||
timeout in *tv */
|
||||
for(e = list->head; e;) {
|
||||
struct Curl_llist_element *n = e->next;
|
||||
timediff_t diff;
|
||||
node = (struct time_node *)e->ptr;
|
||||
diff = Curl_timediff_us(node->time, now);
|
||||
for(e = Curl_llist_head(list); e;) {
|
||||
struct Curl_llist_node *n = Curl_node_next(e);
|
||||
struct time_node *node = Curl_node_elem(e);
|
||||
timediff_t diff = Curl_timediff_us(node->time, now);
|
||||
if(diff <= 0)
|
||||
/* remove outdated entry */
|
||||
Curl_llist_remove(list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
else
|
||||
/* the list is sorted so get out on the first mismatch */
|
||||
break;
|
||||
e = n;
|
||||
}
|
||||
e = list->head;
|
||||
e = Curl_llist_head(list);
|
||||
if(!e) {
|
||||
/* clear the expire times within the handles that we remove from the
|
||||
splay tree */
|
||||
@ -3137,6 +3117,7 @@ static CURLMcode add_next_timeout(struct curltime now,
|
||||
tv->tv_usec = 0;
|
||||
}
|
||||
else {
|
||||
struct time_node *node = Curl_node_elem(e);
|
||||
/* copy the first entry to 'tv' */
|
||||
memcpy(tv, &node->time, sizeof(*tv));
|
||||
|
||||
@ -3162,15 +3143,16 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(checkall) {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
/* *perform() deals with running_handles on its own */
|
||||
result = curl_multi_perform(multi, running_handles);
|
||||
|
||||
/* walk through each easy handle and do the socket state change magic
|
||||
and callbacks */
|
||||
if(result != CURLM_BAD_HANDLE) {
|
||||
for(e = multi->process.head; e && !result; e = e->next) {
|
||||
result = singlesocket(multi, e->ptr);
|
||||
for(e = Curl_llist_head(&multi->process); e && !result;
|
||||
e = Curl_node_next(e)) {
|
||||
result = singlesocket(multi, Curl_node_elem(e));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3499,13 +3481,13 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi)
|
||||
static void
|
||||
multi_deltimeout(struct Curl_easy *data, expire_id eid)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist *timeoutlist = &data->state.timeoutlist;
|
||||
/* find and remove the specific node from the list */
|
||||
for(e = timeoutlist->head; e; e = e->next) {
|
||||
struct time_node *n = (struct time_node *)e->ptr;
|
||||
for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
|
||||
struct time_node *n = Curl_node_elem(e);
|
||||
if(n->eid == eid) {
|
||||
Curl_llist_remove(timeoutlist, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3523,9 +3505,9 @@ multi_addtimeout(struct Curl_easy *data,
|
||||
struct curltime *stamp,
|
||||
expire_id eid)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
struct time_node *node;
|
||||
struct Curl_llist_element *prev = NULL;
|
||||
struct Curl_llist_node *prev = NULL;
|
||||
size_t n;
|
||||
struct Curl_llist *timeoutlist = &data->state.timeoutlist;
|
||||
|
||||
@ -3538,8 +3520,8 @@ multi_addtimeout(struct Curl_easy *data,
|
||||
n = Curl_llist_count(timeoutlist);
|
||||
if(n) {
|
||||
/* find the correct spot in the list */
|
||||
for(e = timeoutlist->head; e; e = e->next) {
|
||||
struct time_node *check = (struct time_node *)e->ptr;
|
||||
for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
|
||||
struct time_node *check = Curl_node_elem(e);
|
||||
timediff_t diff = Curl_timediff(check->time, node->time);
|
||||
if(diff > 0)
|
||||
break;
|
||||
@ -3661,10 +3643,8 @@ void Curl_expire_clear(struct Curl_easy *data)
|
||||
if(rc)
|
||||
infof(data, "Internal error clearing splay node = %d", rc);
|
||||
|
||||
/* flush the timeout list too */
|
||||
while(list->size > 0) {
|
||||
Curl_llist_remove(list, list->tail, NULL);
|
||||
}
|
||||
/* clear the timeout list too */
|
||||
Curl_llist_destroy(list, NULL);
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
infof(data, "Expire cleared");
|
||||
@ -3726,10 +3706,10 @@ static void move_pending_to_connect(struct Curl_multi *multi,
|
||||
DEBUGASSERT(data->mstate == MSTATE_PENDING);
|
||||
|
||||
/* Remove this node from the pending list */
|
||||
Curl_llist_remove(&multi->pending, &data->multi_queue, NULL);
|
||||
Curl_node_remove(&data->multi_queue);
|
||||
|
||||
/* put it into the process list */
|
||||
link_easy(multi, data);
|
||||
Curl_llist_append(&multi->process, data, &data->multi_queue);
|
||||
|
||||
multistate(data, MSTATE_CONNECT);
|
||||
|
||||
@ -3737,7 +3717,7 @@ static void move_pending_to_connect(struct Curl_multi *multi,
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
/* process_pending_handles() moves a handle from PENDING back into the main
|
||||
/* process_pending_handles() moves a handle from PENDING back into the process
|
||||
list and change state to CONNECT.
|
||||
|
||||
We do not move all transfers because that can be a significant amount.
|
||||
@ -3753,9 +3733,9 @@ static void move_pending_to_connect(struct Curl_multi *multi,
|
||||
*/
|
||||
static void process_pending_handles(struct Curl_multi *multi)
|
||||
{
|
||||
struct Curl_llist_element *e = multi->pending.head;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&multi->pending);
|
||||
if(e) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
move_pending_to_connect(multi, data);
|
||||
}
|
||||
}
|
||||
@ -3783,9 +3763,9 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
|
||||
(multi->num_easy + 1));
|
||||
if(a) {
|
||||
unsigned int i = 0;
|
||||
struct Curl_llist_element *e;
|
||||
for(e = multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *data = e->ptr;
|
||||
struct Curl_llist_node *e;
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
DEBUGASSERT(i < multi->num_easy);
|
||||
if(!data->state.internal)
|
||||
a[i++] = data;
|
||||
|
@ -33,7 +33,7 @@
|
||||
struct connectdata;
|
||||
|
||||
struct Curl_message {
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||
struct CURLMsg extmsg;
|
||||
};
|
||||
@ -92,7 +92,7 @@ struct Curl_multi {
|
||||
|
||||
struct Curl_llist msglist; /* a list of messages from completed transfers */
|
||||
|
||||
/* Each added easy handle is in ONE of these three lists */
|
||||
/* Each added easy handle is added to ONE of these three lists */
|
||||
struct Curl_llist process; /* not in PENDING or MSGSENT */
|
||||
struct Curl_llist pending; /* in PENDING */
|
||||
struct Curl_llist msgsent; /* in MSGSENT */
|
||||
|
16
lib/url.c
16
lib/url.c
@ -539,6 +539,9 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&data->state.httphdrs, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(result) {
|
||||
@ -551,7 +554,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
}
|
||||
else
|
||||
*curl = data;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -895,7 +897,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
bool foundPendingCandidate = FALSE;
|
||||
bool canmultiplex = FALSE;
|
||||
struct connectbundle *bundle;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
|
||||
#ifdef USE_NTLM
|
||||
bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) &&
|
||||
@ -952,12 +954,12 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conn_list);
|
||||
while(curr) {
|
||||
struct connectdata *check = curr->ptr;
|
||||
struct connectdata *check = Curl_node_elem(curr);
|
||||
/* Get next node now. We might remove a dead `check` connection which
|
||||
* would invalidate `curr` as well. */
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
|
||||
/* Note that if we use an HTTP proxy in normal mode (no tunneling), we
|
||||
* check connections to that proxy and not to the actual remote server.
|
||||
@ -987,8 +989,8 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
else {
|
||||
/* Could multiplex, but not when check belongs to another multi */
|
||||
struct Curl_llist_element *e = check->easyq.head;
|
||||
struct Curl_easy *entry = e->ptr;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&check->easyq);
|
||||
struct Curl_easy *entry = Curl_node_elem(e);
|
||||
if(entry->multi != data->multi)
|
||||
continue;
|
||||
}
|
||||
|
@ -797,7 +797,7 @@ struct ldapconninfo;
|
||||
* unique for an entire connection.
|
||||
*/
|
||||
struct connectdata {
|
||||
struct Curl_llist_element bundle_node; /* conncache */
|
||||
struct Curl_llist_node bundle_node; /* conncache */
|
||||
|
||||
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
|
||||
void *closesocket_client;
|
||||
@ -806,7 +806,7 @@ struct connectdata {
|
||||
handle is still used by one or more easy handles and can only used by any
|
||||
other easy handle without careful consideration (== only for
|
||||
multiplexing) and it cannot be used by another multi handle! */
|
||||
#define CONN_INUSE(c) ((c)->easyq.size)
|
||||
#define CONN_INUSE(c) Curl_llist_count(&(c)->easyq)
|
||||
|
||||
/**** Fields set when inited and not modified again */
|
||||
curl_off_t connection_id; /* Contains a unique number to make it easier to
|
||||
@ -1194,7 +1194,7 @@ typedef enum {
|
||||
* One instance for each timeout an easy handle can set.
|
||||
*/
|
||||
struct time_node {
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
struct curltime time;
|
||||
expire_id eid;
|
||||
};
|
||||
@ -1910,8 +1910,8 @@ struct Curl_easy {
|
||||
curl_off_t id;
|
||||
|
||||
struct connectdata *conn;
|
||||
struct Curl_llist_element multi_queue; /* for multihandle list management */
|
||||
struct Curl_llist_element conn_queue; /* list per connectdata */
|
||||
struct Curl_llist_node multi_queue; /* for multihandle list management */
|
||||
struct Curl_llist_node conn_queue; /* list per connectdata */
|
||||
|
||||
CURLMstate mstate; /* the handle's state */
|
||||
CURLcode result; /* previous result */
|
||||
|
@ -274,10 +274,10 @@ static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
|
||||
return data;
|
||||
}
|
||||
else {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
DEBUGASSERT(data->multi);
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn != data->conn)
|
||||
continue;
|
||||
stream = H3_STREAM_CTX(ctx, sdata);
|
||||
|
@ -669,10 +669,10 @@ static struct cf_osslq_stream *cf_osslq_get_qstream(struct Curl_cfilter *cf,
|
||||
return &ctx->h3.s_qpack_dec;
|
||||
}
|
||||
else {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
DEBUGASSERT(data->multi);
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn != data->conn)
|
||||
continue;
|
||||
stream = H3_STREAM_CTX(ctx, sdata);
|
||||
@ -1423,12 +1423,12 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
if(ctx->h3.conn) {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
struct h3_stream_ctx *stream;
|
||||
/* PULL all open streams */
|
||||
DEBUGASSERT(data->multi);
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn == data->conn && CURL_WANT_RECV(sdata)) {
|
||||
stream = H3_STREAM_CTX(ctx, sdata);
|
||||
if(stream && !stream->closed &&
|
||||
@ -1454,9 +1454,9 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
|
||||
struct h3_stream_ctx *stream;
|
||||
|
||||
if(ctx->h3.conn) {
|
||||
struct Curl_llist_element *e;
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
struct Curl_llist_node *e;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn == data->conn) {
|
||||
stream = H3_STREAM_CTX(ctx, sdata);
|
||||
if(stream && stream->s.ssl && stream->s.send_blocked &&
|
||||
|
@ -177,11 +177,11 @@ static void check_resumes(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct cf_quiche_ctx *ctx = cf->ctx;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
DEBUGASSERT(data->multi);
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn == data->conn) {
|
||||
struct stream_ctx *stream = H3_STREAM_CTX(ctx, sdata);
|
||||
if(stream && stream->quic_flow_blocked) {
|
||||
@ -277,10 +277,10 @@ static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
|
||||
return data;
|
||||
}
|
||||
else {
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
DEBUGASSERT(data->multi);
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata->conn != data->conn)
|
||||
continue;
|
||||
stream = H3_STREAM_CTX(ctx, sdata);
|
||||
@ -297,12 +297,12 @@ static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
|
||||
static void cf_quiche_expire_conn_closed(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
|
||||
DEBUGASSERT(data->multi);
|
||||
CURL_TRC_CF(data, cf, "conn closed, expire all transfers");
|
||||
for(e = data->multi->process.head; e; e = e->next) {
|
||||
struct Curl_easy *sdata = e->ptr;
|
||||
for(e = Curl_llist_head(&data->multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *sdata = Curl_node_elem(e);
|
||||
if(sdata == data || sdata->conn != data->conn)
|
||||
continue;
|
||||
CURL_TRC_CF(sdata, cf, "conn closed, expire transfer");
|
||||
|
@ -52,14 +52,14 @@ UNITTEST_START
|
||||
int unusedData_case1 = 1;
|
||||
int unusedData_case2 = 2;
|
||||
int unusedData_case3 = 3;
|
||||
struct Curl_llist_element case1_list;
|
||||
struct Curl_llist_element case2_list;
|
||||
struct Curl_llist_element case3_list;
|
||||
struct Curl_llist_element case4_list;
|
||||
struct Curl_llist_element *head;
|
||||
struct Curl_llist_element *element_next;
|
||||
struct Curl_llist_element *element_prev;
|
||||
struct Curl_llist_element *to_remove;
|
||||
struct Curl_llist_node case1_list;
|
||||
struct Curl_llist_node case2_list;
|
||||
struct Curl_llist_node case3_list;
|
||||
struct Curl_llist_node case4_list;
|
||||
struct Curl_llist_node *head;
|
||||
struct Curl_llist_node *element_next;
|
||||
struct Curl_llist_node *element_prev;
|
||||
struct Curl_llist_node *to_remove;
|
||||
size_t llist_size = Curl_llist_count(&llist);
|
||||
|
||||
/**
|
||||
@ -73,11 +73,9 @@ UNITTEST_START
|
||||
* 4: list dtor will be NULL
|
||||
*/
|
||||
|
||||
fail_unless(llist.size == 0, "list initial size should be zero");
|
||||
fail_unless(llist.head == NULL, "list head should initiate to NULL");
|
||||
fail_unless(llist.tail == NULL, "list tail should initiate to NULL");
|
||||
fail_unless(llist.dtor == test_Curl_llist_dtor,
|
||||
"list dtor should initiate to test_Curl_llist_dtor");
|
||||
fail_unless(Curl_llist_count(&llist) == 0, "list initial size should be zero");
|
||||
fail_unless(Curl_llist_head(&llist) == NULL, "list head should initiate to NULL");
|
||||
fail_unless(Curl_llist_tail(&llist) == NULL, "list tail should initiate to NULL");
|
||||
|
||||
/**
|
||||
* testing Curl_llist_insert_next
|
||||
@ -89,15 +87,15 @@ UNITTEST_START
|
||||
* 3: list tail will be the same as list head
|
||||
*/
|
||||
|
||||
Curl_llist_insert_next(&llist, llist.head, &unusedData_case1, &case1_list);
|
||||
Curl_llist_insert_next(&llist, Curl_llist_head(&llist), &unusedData_case1, &case1_list);
|
||||
|
||||
fail_unless(Curl_llist_count(&llist) == 1,
|
||||
"List size should be 1 after adding a new element");
|
||||
/* test that the list head data holds my unusedData */
|
||||
fail_unless(llist.head->ptr == &unusedData_case1,
|
||||
fail_unless(Curl_node_elem(Curl_llist_head(&llist)) == &unusedData_case1,
|
||||
"head ptr should be first entry");
|
||||
/* same goes for the list tail */
|
||||
fail_unless(llist.tail == llist.head,
|
||||
fail_unless(Curl_llist_tail(&llist) == Curl_llist_head(&llist),
|
||||
"tail and head should be the same");
|
||||
|
||||
/**
|
||||
@ -109,11 +107,12 @@ UNITTEST_START
|
||||
* 2: the list tail should be our newly created element
|
||||
*/
|
||||
|
||||
Curl_llist_insert_next(&llist, llist.head,
|
||||
Curl_llist_insert_next(&llist, Curl_llist_head(&llist),
|
||||
&unusedData_case3, &case3_list);
|
||||
fail_unless(llist.head->next->ptr == &unusedData_case3,
|
||||
fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
|
||||
&unusedData_case3,
|
||||
"the node next to head is not getting set correctly");
|
||||
fail_unless(llist.tail->ptr == &unusedData_case3,
|
||||
fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case3,
|
||||
"the list tail is not getting set correctly");
|
||||
|
||||
/**
|
||||
@ -125,15 +124,16 @@ UNITTEST_START
|
||||
* 2: the list tail should different from newly created element
|
||||
*/
|
||||
|
||||
Curl_llist_insert_next(&llist, llist.head,
|
||||
Curl_llist_insert_next(&llist, Curl_llist_head(&llist),
|
||||
&unusedData_case2, &case2_list);
|
||||
fail_unless(llist.head->next->ptr == &unusedData_case2,
|
||||
fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
|
||||
&unusedData_case2,
|
||||
"the node next to head is not getting set correctly");
|
||||
/* better safe than sorry, check that the tail isn't corrupted */
|
||||
fail_unless(llist.tail->ptr != &unusedData_case2,
|
||||
fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) != &unusedData_case2,
|
||||
"the list tail is not getting set correctly");
|
||||
|
||||
/* unit tests for Curl_llist_remove */
|
||||
/* unit tests for Curl_node_remove */
|
||||
|
||||
/**
|
||||
* case 1:
|
||||
@ -144,19 +144,19 @@ UNITTEST_START
|
||||
* 3: "new" head's previous will be NULL
|
||||
*/
|
||||
|
||||
head = llist.head;
|
||||
head = Curl_llist_head(&llist);
|
||||
abort_unless(head, "llist.head is NULL");
|
||||
element_next = head->next;
|
||||
element_next = Curl_node_next(head);
|
||||
llist_size = Curl_llist_count(&llist);
|
||||
|
||||
Curl_llist_remove(&llist, llist.head, NULL);
|
||||
Curl_node_remove(Curl_llist_head(&llist));
|
||||
|
||||
fail_unless(Curl_llist_count(&llist) == (llist_size-1),
|
||||
"llist size not decremented as expected");
|
||||
fail_unless(llist.head == element_next,
|
||||
"llist new head not modified properly");
|
||||
abort_unless(llist.head, "llist.head is NULL");
|
||||
fail_unless(llist.head->prev == NULL,
|
||||
"llist size not decremented as expected");
|
||||
fail_unless(Curl_llist_head(&llist) == element_next,
|
||||
"llist new head not modified properly");
|
||||
abort_unless(Curl_llist_head(&llist), "llist.head is NULL");
|
||||
fail_unless(Curl_node_prev(Curl_llist_head(&llist)) == NULL,
|
||||
"new head previous not set to null");
|
||||
|
||||
/**
|
||||
@ -169,20 +169,20 @@ UNITTEST_START
|
||||
* 2: element->previous->next will be element->next
|
||||
* 3: element->next->previous will be element->previous
|
||||
*/
|
||||
Curl_llist_insert_next(&llist, llist.head, &unusedData_case3,
|
||||
Curl_llist_insert_next(&llist, Curl_llist_head(&llist), &unusedData_case3,
|
||||
&case4_list);
|
||||
llist_size = Curl_llist_count(&llist);
|
||||
fail_unless(llist_size == 3, "should be 3 list members");
|
||||
|
||||
to_remove = llist.head->next;
|
||||
to_remove = Curl_node_next(Curl_llist_head(&llist));
|
||||
abort_unless(to_remove, "to_remove is NULL");
|
||||
element_next = to_remove->next;
|
||||
element_prev = to_remove->prev;
|
||||
Curl_llist_remove(&llist, to_remove, NULL);
|
||||
fail_unless(element_prev->next == element_next,
|
||||
element_next = Curl_node_next(to_remove);
|
||||
element_prev = Curl_node_prev(to_remove);
|
||||
Curl_node_uremove(to_remove, NULL);
|
||||
fail_unless(Curl_node_next(element_prev) == element_next,
|
||||
"element previous->next is not being adjusted");
|
||||
abort_unless(element_next, "element_next is NULL");
|
||||
fail_unless(element_next->prev == element_prev,
|
||||
fail_unless(Curl_node_prev(element_next) == element_prev,
|
||||
"element next->previous is not being adjusted");
|
||||
|
||||
/**
|
||||
@ -195,10 +195,10 @@ UNITTEST_START
|
||||
* 4: list->tail will be tail->previous
|
||||
*/
|
||||
|
||||
to_remove = llist.tail;
|
||||
element_prev = to_remove->prev;
|
||||
Curl_llist_remove(&llist, to_remove, NULL);
|
||||
fail_unless(llist.tail == element_prev,
|
||||
to_remove = Curl_llist_tail(&llist);
|
||||
element_prev = Curl_node_prev(to_remove);
|
||||
Curl_node_remove(to_remove);
|
||||
fail_unless(Curl_llist_tail(&llist) == element_prev,
|
||||
"llist tail is not being adjusted when removing tail");
|
||||
|
||||
/**
|
||||
@ -210,11 +210,11 @@ UNITTEST_START
|
||||
* 3: list tail will be null
|
||||
*/
|
||||
|
||||
to_remove = llist.head;
|
||||
Curl_llist_remove(&llist, to_remove, NULL);
|
||||
fail_unless(llist.head == NULL,
|
||||
to_remove = Curl_llist_head(&llist);
|
||||
Curl_node_remove(to_remove);
|
||||
fail_unless(Curl_llist_head(&llist) == NULL,
|
||||
"llist head is not NULL while the llist is empty");
|
||||
fail_unless(llist.tail == NULL,
|
||||
fail_unless(Curl_llist_tail(&llist) == NULL,
|
||||
"llist tail is not NULL while the llist is empty");
|
||||
|
||||
/**
|
||||
@ -229,10 +229,10 @@ UNITTEST_START
|
||||
fail_unless(Curl_llist_count(&llist) == 1,
|
||||
"List size should be 1 after appending a new element");
|
||||
/* test that the list head data holds my unusedData */
|
||||
fail_unless(llist.head->ptr == &unusedData_case1,
|
||||
fail_unless(Curl_node_elem(Curl_llist_head(&llist)) == &unusedData_case1,
|
||||
"head ptr should be first entry");
|
||||
/* same goes for the list tail */
|
||||
fail_unless(llist.tail == llist.head,
|
||||
fail_unless(Curl_llist_tail(&llist) == Curl_llist_head(&llist),
|
||||
"tail and head should be the same");
|
||||
|
||||
/**
|
||||
@ -244,9 +244,10 @@ UNITTEST_START
|
||||
* 2: the list tail should be the newly created element
|
||||
*/
|
||||
Curl_llist_append(&llist, &unusedData_case2, &case2_list);
|
||||
fail_unless(llist.head->next->ptr == &unusedData_case2,
|
||||
fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
|
||||
&unusedData_case2,
|
||||
"the node next to head is not getting set correctly");
|
||||
fail_unless(llist.tail->ptr == &unusedData_case2,
|
||||
fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case2,
|
||||
"the list tail is not getting set correctly");
|
||||
|
||||
/**
|
||||
@ -258,13 +259,12 @@ UNITTEST_START
|
||||
* 2: the list tail should be the newly created element
|
||||
*/
|
||||
Curl_llist_append(&llist, &unusedData_case3, &case3_list);
|
||||
fail_unless(llist.head->next->ptr == &unusedData_case2,
|
||||
fail_unless(Curl_node_elem(Curl_node_next(Curl_llist_head(&llist))) ==
|
||||
&unusedData_case2,
|
||||
"the node next to head did not stay the same");
|
||||
fail_unless(llist.tail->ptr == &unusedData_case3,
|
||||
fail_unless(Curl_node_elem(Curl_llist_tail(&llist)) == &unusedData_case3,
|
||||
"the list tail is not getting set correctly");
|
||||
|
||||
|
||||
|
||||
Curl_llist_destroy(&llist, NULL);
|
||||
Curl_llist_destroy(&llist_destination, NULL);
|
||||
}
|
||||
|
@ -57,51 +57,51 @@ UNITTEST_START
|
||||
fail_if(!curl, "curl_easy_init");
|
||||
goto fail;
|
||||
}
|
||||
fail_unless(asi->list.size == 4, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 4, "wrong number of entries");
|
||||
msnprintf(outname, sizeof(outname), "%s-out", arg);
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:8080\"\r\n",
|
||||
ALPN_h1, "example.org", 8080);
|
||||
fail_if(result, "Curl_altsvc_parse() failed!");
|
||||
fail_unless(asi->list.size == 5, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 5, "wrong number of entries");
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi, "h3=\":8080\"\r\n",
|
||||
ALPN_h1, "2.example.org", 8080);
|
||||
fail_if(result, "Curl_altsvc_parse(2) failed!");
|
||||
fail_unless(asi->list.size == 6, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 6, "wrong number of entries");
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi,
|
||||
"h2=\"example.com:8080\", h3=\"yesyes.com\"\r\n",
|
||||
ALPN_h1, "3.example.org", 8080);
|
||||
fail_if(result, "Curl_altsvc_parse(3) failed!");
|
||||
/* that one should make two entries */
|
||||
fail_unless(asi->list.size == 8, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 8, "wrong number of entries");
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi,
|
||||
"h2=\"example.com:443\"; ma = 120;\r\n",
|
||||
ALPN_h2, "example.org", 80);
|
||||
fail_if(result, "Curl_altsvc_parse(4) failed!");
|
||||
fail_unless(asi->list.size == 9, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 9, "wrong number of entries");
|
||||
|
||||
/* quoted 'ma' value */
|
||||
result = Curl_altsvc_parse(curl, asi,
|
||||
"h2=\"example.net:443\"; ma=\"180\";\r\n",
|
||||
ALPN_h2, "example.net", 80);
|
||||
fail_if(result, "Curl_altsvc_parse(4) failed!");
|
||||
fail_unless(asi->list.size == 10, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 10, "wrong number of entries");
|
||||
|
||||
result =
|
||||
Curl_altsvc_parse(curl, asi,
|
||||
"h2=\":443\", h3=\":443\"; ma = 120; persist = 1\r\n",
|
||||
ALPN_h1, "curl.se", 80);
|
||||
fail_if(result, "Curl_altsvc_parse(5) failed!");
|
||||
fail_unless(asi->list.size == 12, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 12, "wrong number of entries");
|
||||
|
||||
/* clear that one again and decrease the counter */
|
||||
result = Curl_altsvc_parse(curl, asi, "clear;\r\n",
|
||||
ALPN_h1, "curl.se", 80);
|
||||
fail_if(result, "Curl_altsvc_parse(6) failed!");
|
||||
fail_unless(asi->list.size == 10, "wrong number of entries");
|
||||
fail_unless(Curl_llist_count(&asi->list) == 10, "wrong number of entries");
|
||||
|
||||
Curl_altsvc_save(curl, asi, outname);
|
||||
|
||||
|
@ -118,6 +118,7 @@ static void showsts(struct stsentry *e, const char *chost)
|
||||
}
|
||||
|
||||
UNITTEST_START
|
||||
{
|
||||
CURLcode result;
|
||||
struct stsentry *e;
|
||||
struct hsts *h = Curl_hsts_init();
|
||||
@ -159,7 +160,7 @@ UNITTEST_START
|
||||
showsts(e, chost);
|
||||
}
|
||||
|
||||
printf("Number of entries: %zu\n", h->list.size);
|
||||
printf("Number of entries: %zu\n", Curl_llist_count(&h->list));
|
||||
|
||||
/* verify that it is exists for 7 seconds */
|
||||
chost = "expire.example";
|
||||
@ -174,6 +175,6 @@ UNITTEST_START
|
||||
Curl_hsts_cleanup(&h);
|
||||
curl_easy_cleanup(easy);
|
||||
curl_global_cleanup();
|
||||
|
||||
}
|
||||
UNITTEST_STOP
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user