]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
llist: remove direct struct accesses, use only functions
authorDaniel Stenberg <daniel@haxx.se>
Sat, 10 Aug 2024 21:27:25 +0000 (23:27 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 12 Aug 2024 11:18:10 +0000 (13:18 +0200)
- 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

27 files changed:
docs/LLIST.md [new file with mode: 0644]
docs/Makefile.am
lib/altsvc.c
lib/altsvc.h
lib/conncache.c
lib/easy.c
lib/fileinfo.h
lib/ftp.c
lib/hash.c
lib/hash.h
lib/headers.c
lib/headers.h
lib/hsts.c
lib/hsts.h
lib/http.c
lib/llist.c
lib/llist.h
lib/multi.c
lib/multihandle.h
lib/url.c
lib/urldata.h
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_osslq.c
lib/vquic/curl_quiche.c
tests/unit/unit1300.c
tests/unit/unit1654.c
tests/unit/unit1660.c

diff --git a/docs/LLIST.md b/docs/LLIST.md
new file mode 100644 (file)
index 0000000..ee9a89b
--- /dev/null
@@ -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.
index e9ef628486055524d2f698d6609a5dc81c978584..5db134b4e0afd2855ef7a8284478d78a35dcd473 100644 (file)
@@ -81,6 +81,7 @@ EXTRA_DIST =                                    \
  INSTALL.md                                     \
  INTERNALS.md                                   \
  IPFS.md                                        \
+ LLIST.md                                       \
  KNOWN_BUGS                                     \
  MAIL-ETIQUETTE.md                              \
  MANUAL.md                                      \
index db9749c25841af649b1e0fc2f612503910b995d9..dcedc491c5b2c8b5ed34863677d779efce2ba5b5 100644 (file)
@@ -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;
     }
index 58f1905da61e4a7e4bd832a018861f20c529b509..48999efb3177638c6617edf341f390783a0f87d6 100644 (file)
@@ -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 {
index 5de10de914857d0243626124bb88fc2b4963811e..e0a15cf32c3a268374b6251bd2b074b9ff19d07c 100644 (file)
@@ -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");
 
index 6c4594904b888910741358c2f4aced55548fe383..34e8f90f1261e57d8f0028aba41846e69b692ad9 100644 (file)
@@ -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;
index ce009da06dfbe0bf8d628ed0b4befa4a395aa0fa..0b3f56d9d493eb511a29eb667d96203032ce627c 100644 (file)
@@ -30,7 +30,7 @@
 
 struct fileinfo {
   struct curl_fileinfo info;
-  struct Curl_llist_element list;
+  struct Curl_llist_node list;
   struct dynbuf buf;
 };
 
index 9b2db627068a763e2a3651dfc8439db37c6d9d2a..fcb540a6b12f3476ae6ee384111cbc09301ff0ce 100644 (file)
--- a/lib/ftp.c
+++ b/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;
     }
index df8e2abffe2c3235c70ab9049f703a9bc51c3a81..be36704eb2745e5c6e574380b22bcd67dcd35356 100644 (file)
@@ -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;
index 1cf787525b075294093a2328e7941febb5d3fb7b..b0bc29be390f309b14a9f469c59afefea41fc7cc 100644 (file)
@@ -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,
index 59ac422258454b28b3b5edcc61a0a373c7b0e878..7c60c07985342322b6bcbc6415d1ba250c82bf7f 100644 (file)
@@ -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);
index d9813388c51e7a264c4012f29200d0848f49e923..e11fe9804e5129cd43b26235b98435139cd7d840 100644 (file)
@@ -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.. */
index 8cd77ae3cffa26dc62f687e0cb1ceb4e78fb47f0..a5c216f6de3805cc2a16c4beb6edb62e80ae098f 100644 (file)
@@ -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;
index 21e53a34279e1ab56f05660a426dfe9a31e254f7..1c544f97bd8a081a974a53e934730af9c5a781e7 100644 (file)
@@ -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 */
index 309843a46701df9a65c28c2fb4f5085c6f40a421..9b1fc716308c64e18011c92e58f6946c97bea9e8 100644 (file)
@@ -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
index 716f0cd57624ff00ab793306bd493a6d9df7d3f8..84bcc9f5b668fe10d6d78753dfbecff87e25d005 100644 (file)
 /* 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)
+{
+  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)
 {
-  return list->size;
+  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
index d75582fa970ef751cee869d3de04398bb548cc6a..f12d71e00c538c1c48889af05b313d01d91e12c5 100644 (file)
 #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 */
index 21fc6c0e684e8fe6ff9a4533f84e3a16140fa2ad..e6b323f1ab960106ee7dbb40d33b426193e413f2 100644 (file)
@@ -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;
index 09bfe89a1a60127b36fa9c370e3f8ac64090af9f..0649e623aab9ef8ee2ebf8dea9ddb07ffca7c408 100644 (file)
@@ -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 */
index cd847899ee8eab3da80d24496770c3cee79eb89f..d5d7e2fcca3f36242e6a576f3079311df3086269 100644 (file)
--- a/lib/url.c
+++ b/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;
       }
index d8bff3c9badb71ca3b0c7b56dd7145ab3a9e5a83..2e71abdaf723229d190091b3e41eeee8b07a0772 100644 (file)
@@ -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 */
index e5a80b6c598365dda074dbbb598bc8d0fb67114d..f672bfcaebb7b5a2092306a88b388a9174eb2d8c 100644 (file)
@@ -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);
index c6dbcd6578eab849e7c2c8bf13a821c7f2eda703..46565bee4283fa874244cc399554ba16ee356ab0 100644 (file)
@@ -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 &&
index 2247dd906499a0a3403bb11d513b198423f838c7..fafbb03ee64e0c49e18315e41dbcb23d9a2f09a1 100644 (file)
@@ -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");
index d94cfe17877090a1f86a1dad7d8614ae0f3587fe..e408f5ecc21ae825d12b688761012eba8aa932a2 100644 (file)
@@ -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);
 }
index f7ca3911b6e8e6233dc20a5ab24267ba18d47b70..2f5d1bcc86ebb3ffb4e80aab400dad6fb16d0308 100644 (file)
@@ -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);
 
index 5a126fbc5a12d09563ae9b251c80908ddf736dd9..e14944592c2fbc5e5962c3fbad454053103c7b37 100644 (file)
@@ -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