xref: /curl/lib/multi.c (revision 7f7ad97b)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 #include "curl_setup.h"
26 
27 #include <curl/curl.h>
28 
29 #include "urldata.h"
30 #include "transfer.h"
31 #include "url.h"
32 #include "cfilters.h"
33 #include "connect.h"
34 #include "progress.h"
35 #include "easyif.h"
36 #include "share.h"
37 #include "psl.h"
38 #include "multiif.h"
39 #include "sendf.h"
40 #include "timeval.h"
41 #include "http.h"
42 #include "select.h"
43 #include "warnless.h"
44 #include "speedcheck.h"
45 #include "conncache.h"
46 #include "multihandle.h"
47 #include "sigpipe.h"
48 #include "vtls/vtls.h"
49 #include "http_proxy.h"
50 #include "http2.h"
51 #include "socketpair.h"
52 #include "socks.h"
53 /* The last 3 #include files should be in this order */
54 #include "curl_printf.h"
55 #include "curl_memory.h"
56 #include "memdebug.h"
57 
58 /*
59   CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
60   to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes.  Still, every
61   CURL handle takes 45-50 K memory, therefore this 3K are not significant.
62 */
63 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
64 #define CURL_SOCKET_HASH_TABLE_SIZE 911
65 #endif
66 
67 #ifndef CURL_CONNECTION_HASH_SIZE
68 #define CURL_CONNECTION_HASH_SIZE 97
69 #endif
70 
71 #ifndef CURL_DNS_HASH_SIZE
72 #define CURL_DNS_HASH_SIZE 71
73 #endif
74 
75 #define CURL_MULTI_HANDLE 0x000bab1e
76 
77 #ifdef DEBUGBUILD
78 /* On a debug build, we want to fail hard on multi handles that
79  * are not NULL, but no longer have the MAGIC touch. This gives
80  * us early warning on things only discovered by valgrind otherwise. */
81 #define GOOD_MULTI_HANDLE(x) \
82   (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE: \
83   (DEBUGASSERT(!(x)), FALSE))
84 #else
85 #define GOOD_MULTI_HANDLE(x) \
86   ((x) && (x)->magic == CURL_MULTI_HANDLE)
87 #endif
88 
89 static void move_pending_to_connect(struct Curl_multi *multi,
90                                     struct Curl_easy *data);
91 static CURLMcode singlesocket(struct Curl_multi *multi,
92                               struct Curl_easy *data);
93 static CURLMcode add_next_timeout(struct curltime now,
94                                   struct Curl_multi *multi,
95                                   struct Curl_easy *d);
96 static CURLMcode multi_timeout(struct Curl_multi *multi,
97                                long *timeout_ms);
98 static void process_pending_handles(struct Curl_multi *multi);
99 static void multi_xfer_bufs_free(struct Curl_multi *multi);
100 
101 #ifdef DEBUGBUILD
102 static const char * const multi_statename[]={
103   "INIT",
104   "PENDING",
105   "SETUP",
106   "CONNECT",
107   "RESOLVING",
108   "CONNECTING",
109   "TUNNELING",
110   "PROTOCONNECT",
111   "PROTOCONNECTING",
112   "DO",
113   "DOING",
114   "DOING_MORE",
115   "DID",
116   "PERFORMING",
117   "RATELIMITING",
118   "DONE",
119   "COMPLETED",
120   "MSGSENT",
121 };
122 #endif
123 
124 /* function pointer called once when switching TO a state */
125 typedef void (*init_multistate_func)(struct Curl_easy *data);
126 
127 /* called in DID state, before PERFORMING state */
before_perform(struct Curl_easy * data)128 static void before_perform(struct Curl_easy *data)
129 {
130   data->req.chunk = FALSE;
131   Curl_pgrsTime(data, TIMER_PRETRANSFER);
132 }
133 
init_completed(struct Curl_easy * data)134 static void init_completed(struct Curl_easy *data)
135 {
136   /* this is a completed transfer */
137 
138   /* Important: reset the conn pointer so that we don't point to memory
139      that could be freed anytime */
140   Curl_detach_connection(data);
141   Curl_expire_clear(data); /* stop all timers */
142 }
143 
144 /* always use this function to change state, to make debugging easier */
mstate(struct Curl_easy * data,CURLMstate state,int lineno)145 static void mstate(struct Curl_easy *data, CURLMstate state
146 #ifdef DEBUGBUILD
147                    , int lineno
148 #endif
149 )
150 {
151   CURLMstate oldstate = data->mstate;
152   static const init_multistate_func finit[MSTATE_LAST] = {
153     NULL,              /* INIT */
154     NULL,              /* PENDING */
155     NULL,              /* SETUP */
156     Curl_init_CONNECT, /* CONNECT */
157     NULL,              /* RESOLVING */
158     NULL,              /* CONNECTING */
159     NULL,              /* TUNNELING */
160     NULL,              /* PROTOCONNECT */
161     NULL,              /* PROTOCONNECTING */
162     NULL,              /* DO */
163     NULL,              /* DOING */
164     NULL,              /* DOING_MORE */
165     before_perform,    /* DID */
166     NULL,              /* PERFORMING */
167     NULL,              /* RATELIMITING */
168     NULL,              /* DONE */
169     init_completed,    /* COMPLETED */
170     NULL               /* MSGSENT */
171   };
172 
173 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
174   (void) lineno;
175 #endif
176 
177   if(oldstate == state)
178     /* don't bother when the new state is the same as the old state */
179     return;
180 
181   data->mstate = state;
182 
183 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
184   if(data->mstate >= MSTATE_PENDING &&
185      data->mstate < MSTATE_COMPLETED) {
186     infof(data,
187           "STATE: %s => %s handle %p; line %d",
188           multi_statename[oldstate], multi_statename[data->mstate],
189           (void *)data, lineno);
190   }
191 #endif
192 
193   if(state == MSTATE_COMPLETED) {
194     /* changing to COMPLETED means there's one less easy handle 'alive' */
195     DEBUGASSERT(data->multi->num_alive > 0);
196     data->multi->num_alive--;
197     if(!data->multi->num_alive) {
198       /* free the transfer buffer when we have no more active transfers */
199       multi_xfer_bufs_free(data->multi);
200     }
201   }
202 
203   /* if this state has an init-function, run it */
204   if(finit[state])
205     finit[state](data);
206 }
207 
208 #ifndef DEBUGBUILD
209 #define multistate(x,y) mstate(x,y)
210 #else
211 #define multistate(x,y) mstate(x,y, __LINE__)
212 #endif
213 
214 /*
215  * We add one of these structs to the sockhash for each socket
216  */
217 
218 struct Curl_sh_entry {
219   struct Curl_hash transfers; /* hash of transfers using this socket */
220   unsigned int action;  /* what combined action READ/WRITE this socket waits
221                            for */
222   unsigned int users; /* number of transfers using this */
223   void *socketp; /* settable by users with curl_multi_assign() */
224   unsigned int readers; /* this many transfers want to read */
225   unsigned int writers; /* this many transfers want to write */
226 };
227 
228 /* look up a given socket in the socket hash, skip invalid sockets */
sh_getentry(struct Curl_hash * sh,curl_socket_t s)229 static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
230                                          curl_socket_t s)
231 {
232   if(s != CURL_SOCKET_BAD) {
233     /* only look for proper sockets */
234     return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
235   }
236   return NULL;
237 }
238 
239 #define TRHASH_SIZE 13
trhash(void * key,size_t key_length,size_t slots_num)240 static size_t trhash(void *key, size_t key_length, size_t slots_num)
241 {
242   size_t keyval = (size_t)*(struct Curl_easy **)key;
243   (void) key_length;
244 
245   return (keyval % slots_num);
246 }
247 
trhash_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)248 static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
249 {
250   (void)k1_len;
251   (void)k2_len;
252 
253   return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2;
254 }
255 
trhash_dtor(void * nada)256 static void trhash_dtor(void *nada)
257 {
258   (void)nada;
259 }
260 
261 /*
262  * The sockhash has its own separate subhash in each entry that need to be
263  * safely destroyed first.
264  */
sockhash_destroy(struct Curl_hash * h)265 static void sockhash_destroy(struct Curl_hash *h)
266 {
267   struct Curl_hash_iterator iter;
268   struct Curl_hash_element *he;
269 
270   DEBUGASSERT(h);
271   Curl_hash_start_iterate(h, &iter);
272   he = Curl_hash_next_element(&iter);
273   while(he) {
274     struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
275     Curl_hash_destroy(&sh->transfers);
276     he = Curl_hash_next_element(&iter);
277   }
278   Curl_hash_destroy(h);
279 }
280 
281 
282 /* make sure this socket is present in the hash for this handle */
sh_addentry(struct Curl_hash * sh,curl_socket_t s)283 static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
284                                          curl_socket_t s)
285 {
286   struct Curl_sh_entry *there = sh_getentry(sh, s);
287   struct Curl_sh_entry *check;
288 
289   if(there) {
290     /* it is present, return fine */
291     return there;
292   }
293 
294   /* not present, add it */
295   check = calloc(1, sizeof(struct Curl_sh_entry));
296   if(!check)
297     return NULL; /* major failure */
298 
299   Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
300                  trhash_dtor);
301 
302   /* make/add new hash entry */
303   if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
304     Curl_hash_destroy(&check->transfers);
305     free(check);
306     return NULL; /* major failure */
307   }
308 
309   return check; /* things are good in sockhash land */
310 }
311 
312 
313 /* delete the given socket + handle from the hash */
sh_delentry(struct Curl_sh_entry * entry,struct Curl_hash * sh,curl_socket_t s)314 static void sh_delentry(struct Curl_sh_entry *entry,
315                         struct Curl_hash *sh, curl_socket_t s)
316 {
317   Curl_hash_destroy(&entry->transfers);
318 
319   /* We remove the hash entry. This will end up in a call to
320      sh_freeentry(). */
321   Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
322 }
323 
324 /*
325  * free a sockhash entry
326  */
sh_freeentry(void * freethis)327 static void sh_freeentry(void *freethis)
328 {
329   struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
330 
331   free(p);
332 }
333 
fd_key_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)334 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
335 {
336   (void) k1_len; (void) k2_len;
337 
338   return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
339 }
340 
hash_fd(void * key,size_t key_length,size_t slots_num)341 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
342 {
343   curl_socket_t fd = *((curl_socket_t *) key);
344   (void) key_length;
345 
346   return (fd % slots_num);
347 }
348 
349 /*
350  * sh_init() creates a new socket hash and returns the handle for it.
351  *
352  * Quote from README.multi_socket:
353  *
354  * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
355  * is somewhat of a bottle neck. Its current implementation may be a bit too
356  * limiting. It simply has a fixed-size array, and on each entry in the array
357  * it has a linked list with entries. So the hash only checks which list to
358  * scan through. The code I had used so for used a list with merely 7 slots
359  * (as that is what the DNS hash uses) but with 7000 connections that would
360  * make an average of 1000 nodes in each list to run through. I upped that to
361  * 97 slots (I believe a prime is suitable) and noticed a significant speed
362  * increase.  I need to reconsider the hash implementation or use a rather
363  * large default value like this. At 9000 connections I was still below 10us
364  * per call."
365  *
366  */
sh_init(struct Curl_hash * hash,int hashsize)367 static void sh_init(struct Curl_hash *hash, int hashsize)
368 {
369   Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
370                  sh_freeentry);
371 }
372 
373 /*
374  * multi_addmsg()
375  *
376  * Called when a transfer is completed. Adds the given msg pointer to
377  * the list kept in the multi handle.
378  */
multi_addmsg(struct Curl_multi * multi,struct Curl_message * msg)379 static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
380 {
381   Curl_llist_append(&multi->msglist, msg, &msg->list);
382 }
383 
Curl_multi_handle(int hashsize,int chashsize,int dnssize)384 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
385                                      int chashsize, /* connection hash */
386                                      int dnssize) /* dns hash */
387 {
388   struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
389 
390   if(!multi)
391     return NULL;
392 
393   multi->magic = CURL_MULTI_HANDLE;
394 
395   Curl_init_dnscache(&multi->hostcache, dnssize);
396 
397   sh_init(&multi->sockhash, hashsize);
398 
399   if(Curl_conncache_init(&multi->conn_cache, chashsize))
400     goto error;
401 
402   Curl_llist_init(&multi->msglist, NULL);
403   Curl_llist_init(&multi->pending, NULL);
404   Curl_llist_init(&multi->msgsent, NULL);
405 
406   multi->multiplexing = TRUE;
407   multi->max_concurrent_streams = 100;
408 
409 #ifdef USE_WINSOCK
410   multi->wsa_event = WSACreateEvent();
411   if(multi->wsa_event == WSA_INVALID_EVENT)
412     goto error;
413 #else
414 #ifdef ENABLE_WAKEUP
415   if(wakeup_create(multi->wakeup_pair) < 0) {
416     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
417     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
418   }
419   else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
420           curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
421     wakeup_close(multi->wakeup_pair[0]);
422     wakeup_close(multi->wakeup_pair[1]);
423     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
424     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
425   }
426 #endif
427 #endif
428 
429   return multi;
430 
431 error:
432 
433   sockhash_destroy(&multi->sockhash);
434   Curl_hash_destroy(&multi->hostcache);
435   Curl_conncache_destroy(&multi->conn_cache);
436   free(multi);
437   return NULL;
438 }
439 
curl_multi_init(void)440 struct Curl_multi *curl_multi_init(void)
441 {
442   return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
443                            CURL_CONNECTION_HASH_SIZE,
444                            CURL_DNS_HASH_SIZE);
445 }
446 
447 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
multi_warn_debug(struct Curl_multi * multi,struct Curl_easy * data)448 static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
449 {
450   if(!multi->warned) {
451     infof(data, "!!! WARNING !!!");
452     infof(data, "This is a debug build of libcurl, "
453           "do not use in production.");
454     multi->warned = true;
455   }
456 }
457 #else
458 #define multi_warn_debug(x,y) Curl_nop_stmt
459 #endif
460 
461 /* returns TRUE if the easy handle is supposed to be present in the main link
462    list */
in_main_list(struct Curl_easy * data)463 static bool in_main_list(struct Curl_easy *data)
464 {
465   return ((data->mstate != MSTATE_PENDING) &&
466           (data->mstate != MSTATE_MSGSENT));
467 }
468 
link_easy(struct Curl_multi * multi,struct Curl_easy * data)469 static void link_easy(struct Curl_multi *multi,
470                       struct Curl_easy *data)
471 {
472   /* We add the new easy entry last in the list. */
473   data->next = NULL; /* end of the line */
474   if(multi->easyp) {
475     struct Curl_easy *last = multi->easylp;
476     last->next = data;
477     data->prev = last;
478     multi->easylp = data; /* the new last node */
479   }
480   else {
481     /* first node, make prev NULL! */
482     data->prev = NULL;
483     multi->easylp = multi->easyp = data; /* both first and last */
484   }
485 }
486 
487 /* unlink the given easy handle from the linked list of easy handles */
unlink_easy(struct Curl_multi * multi,struct Curl_easy * data)488 static void unlink_easy(struct Curl_multi *multi,
489                         struct Curl_easy *data)
490 {
491   /* make the previous node point to our next */
492   if(data->prev)
493     data->prev->next = data->next;
494   else
495     multi->easyp = data->next; /* point to first node */
496 
497   /* make our next point to our previous node */
498   if(data->next)
499     data->next->prev = data->prev;
500   else
501     multi->easylp = data->prev; /* point to last node */
502 
503   data->prev = data->next = NULL;
504 }
505 
506 
curl_multi_add_handle(struct Curl_multi * multi,struct Curl_easy * data)507 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
508                                 struct Curl_easy *data)
509 {
510   CURLMcode rc;
511   /* First, make some basic checks that the CURLM handle is a good handle */
512   if(!GOOD_MULTI_HANDLE(multi))
513     return CURLM_BAD_HANDLE;
514 
515   /* Verify that we got a somewhat good easy handle too */
516   if(!GOOD_EASY_HANDLE(data))
517     return CURLM_BAD_EASY_HANDLE;
518 
519   /* Prevent users from adding same easy handle more than once and prevent
520      adding to more than one multi stack */
521   if(data->multi)
522     return CURLM_ADDED_ALREADY;
523 
524   if(multi->in_callback)
525     return CURLM_RECURSIVE_API_CALL;
526 
527   if(multi->dead) {
528     /* a "dead" handle cannot get added transfers while any existing easy
529        handles are still alive - but if there are none alive anymore, it is
530        fine to start over and unmark the "deadness" of this handle */
531     if(multi->num_alive)
532       return CURLM_ABORTED_BY_CALLBACK;
533     multi->dead = FALSE;
534   }
535 
536   if(data->multi_easy) {
537     /* if this easy handle was previously used for curl_easy_perform(), there
538        is a private multi handle here that we can kill */
539     curl_multi_cleanup(data->multi_easy);
540     data->multi_easy = NULL;
541   }
542 
543   /* Initialize timeout list for this handle */
544   Curl_llist_init(&data->state.timeoutlist, NULL);
545 
546   /*
547    * No failure allowed in this function beyond this point. And no
548    * modification of easy nor multi handle allowed before this except for
549    * potential multi's connection cache growing which won't be undone in this
550    * function no matter what.
551    */
552   if(data->set.errorbuffer)
553     data->set.errorbuffer[0] = 0;
554 
555   /* make the Curl_easy refer back to this multi handle - before Curl_expire()
556      is called. */
557   data->multi = multi;
558 
559   /* Set the timeout for this handle to expire really soon so that it will
560      be taken care of even when this handle is added in the midst of operation
561      when only the curl_multi_socket() API is used. During that flow, only
562      sockets that time-out or have actions will be dealt with. Since this
563      handle has no action yet, we make sure it times out to get things to
564      happen. */
565   Curl_expire(data, 0, EXPIRE_RUN_NOW);
566 
567   /* A somewhat crude work-around for a little glitch in Curl_update_timer()
568      that happens if the lastcall time is set to the same time when the handle
569      is removed as when the next handle is added, as then the check in
570      Curl_update_timer() that prevents calling the application multiple times
571      with the same timer info will not trigger and then the new handle's
572      timeout will not be notified to the app.
573 
574      The work-around is thus simply to clear the 'lastcall' variable to force
575      Curl_update_timer() to always trigger a callback to the app when a new
576      easy handle is added */
577   memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
578 
579   rc = Curl_update_timer(multi);
580   if(rc)
581     return rc;
582 
583   /* set the easy handle */
584   multistate(data, MSTATE_INIT);
585 
586   /* for multi interface connections, we share DNS cache automatically if the
587      easy handle's one is currently not set. */
588   if(!data->dns.hostcache ||
589      (data->dns.hostcachetype == HCACHE_NONE)) {
590     data->dns.hostcache = &multi->hostcache;
591     data->dns.hostcachetype = HCACHE_MULTI;
592   }
593 
594   /* Point to the shared or multi handle connection cache */
595   if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
596     data->state.conn_cache = &data->share->conn_cache;
597   else
598     data->state.conn_cache = &multi->conn_cache;
599   data->state.lastconnect_id = -1;
600 
601 #ifdef USE_LIBPSL
602   /* Do the same for PSL. */
603   if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
604     data->psl = &data->share->psl;
605   else
606     data->psl = &multi->psl;
607 #endif
608 
609   link_easy(multi, data);
610 
611   /* increase the node-counter */
612   multi->num_easy++;
613 
614   /* increase the alive-counter */
615   multi->num_alive++;
616 
617   CONNCACHE_LOCK(data);
618   /* The closure handle only ever has default timeouts set. To improve the
619      state somewhat we clone the timeouts from each added handle so that the
620      closure handle always has the same timeouts as the most recently added
621      easy handle. */
622   data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
623   data->state.conn_cache->closure_handle->set.server_response_timeout =
624     data->set.server_response_timeout;
625   data->state.conn_cache->closure_handle->set.no_signal =
626     data->set.no_signal;
627   data->id = data->state.conn_cache->next_easy_id++;
628   if(data->state.conn_cache->next_easy_id <= 0)
629     data->state.conn_cache->next_easy_id = 0;
630   CONNCACHE_UNLOCK(data);
631 
632   multi_warn_debug(multi, data);
633 
634   return CURLM_OK;
635 }
636 
637 #if 0
638 /* Debug-function, used like this:
639  *
640  * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
641  *
642  * Enable the hash print function first by editing hash.c
643  */
644 static void debug_print_sock_hash(void *p)
645 {
646   struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
647 
648   fprintf(stderr, " [readers %u][writers %u]",
649           sh->readers, sh->writers);
650 }
651 #endif
652 
multi_done(struct Curl_easy * data,CURLcode status,bool premature)653 static CURLcode multi_done(struct Curl_easy *data,
654                            CURLcode status,  /* an error if this is called
655                                                 after an error was detected */
656                            bool premature)
657 {
658   CURLcode result, r2;
659   struct connectdata *conn = data->conn;
660 
661 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
662   DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
663                multi_statename[data->mstate],
664                (int)status, (int)premature, data->state.done));
665 #else
666   DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
667                (int)status, (int)premature, data->state.done));
668 #endif
669 
670   if(data->state.done)
671     /* Stop if multi_done() has already been called */
672     return CURLE_OK;
673 
674   /* Stop the resolver and free its own resources (but not dns_entry yet). */
675   Curl_resolver_kill(data);
676 
677   /* Cleanup possible redirect junk */
678   Curl_safefree(data->req.newurl);
679   Curl_safefree(data->req.location);
680 
681   switch(status) {
682   case CURLE_ABORTED_BY_CALLBACK:
683   case CURLE_READ_ERROR:
684   case CURLE_WRITE_ERROR:
685     /* When we're aborted due to a callback return code it basically have to
686        be counted as premature as there is trouble ahead if we don't. We have
687        many callbacks and protocols work differently, we could potentially do
688        this more fine-grained in the future. */
689     premature = TRUE;
690     FALLTHROUGH();
691   default:
692     break;
693   }
694 
695   /* this calls the protocol-specific function pointer previously set */
696   if(conn->handler->done)
697     result = conn->handler->done(data, status, premature);
698   else
699     result = status;
700 
701   if(CURLE_ABORTED_BY_CALLBACK != result) {
702     /* avoid this if we already aborted by callback to avoid this calling
703        another callback */
704     int rc = Curl_pgrsDone(data);
705     if(!result && rc)
706       result = CURLE_ABORTED_BY_CALLBACK;
707   }
708 
709   /* Make sure that transfer client writes are really done now. */
710   r2 = Curl_xfer_write_done(data, premature);
711   if(r2 && !result)
712     result = r2;
713 
714   /* Inform connection filters that this transfer is done */
715   Curl_conn_ev_data_done(data, premature);
716 
717   process_pending_handles(data->multi); /* connection / multiplex */
718 
719   if(!result)
720     result = Curl_req_done(&data->req, data, premature);
721 
722   CONNCACHE_LOCK(data);
723   Curl_detach_connection(data);
724   if(CONN_INUSE(conn)) {
725     /* Stop if still used. */
726     CONNCACHE_UNLOCK(data);
727     DEBUGF(infof(data, "Connection still in use %zu, "
728                  "no more multi_done now!",
729                  conn->easyq.size));
730     return CURLE_OK;
731   }
732 
733   data->state.done = TRUE; /* called just now! */
734 
735   if(conn->dns_entry) {
736     Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
737     conn->dns_entry = NULL;
738   }
739   Curl_hostcache_prune(data);
740 
741   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
742      forced us to close this connection. This is ignored for requests taking
743      place in a NTLM/NEGOTIATE authentication handshake
744 
745      if conn->bits.close is TRUE, it means that the connection should be
746      closed in spite of all our efforts to be nice, due to protocol
747      restrictions in our or the server's end
748 
749      if premature is TRUE, it means this connection was said to be DONE before
750      the entire request operation is complete and thus we can't know in what
751      state it is for reusing, so we're forced to close it. In a perfect world
752      we can add code that keep track of if we really must close it here or not,
753      but currently we have no such detail knowledge.
754   */
755 
756   data->state.recent_conn_id = conn->connection_id;
757   if((data->set.reuse_forbid
758 #if defined(USE_NTLM)
759       && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
760            conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
761 #endif
762 #if defined(USE_SPNEGO)
763       && !(conn->http_negotiate_state == GSS_AUTHRECV ||
764            conn->proxy_negotiate_state == GSS_AUTHRECV)
765 #endif
766      ) || conn->bits.close
767        || (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
768     DEBUGF(infof(data, "multi_done, not reusing connection=%"
769                        CURL_FORMAT_CURL_OFF_T ", forbid=%d"
770                        ", close=%d, premature=%d, conn_multiplex=%d",
771                  conn->connection_id,
772                  data->set.reuse_forbid, conn->bits.close, premature,
773                  Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
774     connclose(conn, "disconnecting");
775     Curl_conncache_remove_conn(data, conn, FALSE);
776     CONNCACHE_UNLOCK(data);
777     Curl_disconnect(data, conn, premature);
778   }
779   else {
780     char buffer[256];
781     const char *host =
782 #ifndef CURL_DISABLE_PROXY
783       conn->bits.socksproxy ?
784       conn->socks_proxy.host.dispname :
785       conn->bits.httpproxy ? conn->http_proxy.host.dispname :
786 #endif
787       conn->bits.conn_to_host ? conn->conn_to_host.dispname :
788       conn->host.dispname;
789     /* create string before returning the connection */
790     curl_off_t connection_id = conn->connection_id;
791     msnprintf(buffer, sizeof(buffer),
792               "Connection #%" CURL_FORMAT_CURL_OFF_T " to host %s left intact",
793               connection_id, host);
794     /* the connection is no longer in use by this transfer */
795     CONNCACHE_UNLOCK(data);
796     if(Curl_conncache_return_conn(data, conn)) {
797       /* remember the most recently used connection */
798       data->state.lastconnect_id = connection_id;
799       data->state.recent_conn_id = connection_id;
800       infof(data, "%s", buffer);
801     }
802     else
803       data->state.lastconnect_id = -1;
804   }
805 
806   return result;
807 }
808 
close_connect_only(struct Curl_easy * data,struct connectdata * conn,void * param)809 static int close_connect_only(struct Curl_easy *data,
810                               struct connectdata *conn, void *param)
811 {
812   (void)param;
813   if(data->state.lastconnect_id != conn->connection_id)
814     return 0;
815 
816   if(!conn->connect_only)
817     return 1;
818 
819   connclose(conn, "Removing connect-only easy handle");
820 
821   return 1;
822 }
823 
curl_multi_remove_handle(struct Curl_multi * multi,struct Curl_easy * data)824 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
825                                    struct Curl_easy *data)
826 {
827   struct Curl_easy *easy = data;
828   bool premature;
829   struct Curl_llist_element *e;
830   CURLMcode rc;
831 
832   /* First, make some basic checks that the CURLM handle is a good handle */
833   if(!GOOD_MULTI_HANDLE(multi))
834     return CURLM_BAD_HANDLE;
835 
836   /* Verify that we got a somewhat good easy handle too */
837   if(!GOOD_EASY_HANDLE(data))
838     return CURLM_BAD_EASY_HANDLE;
839 
840   /* Prevent users from trying to remove same easy handle more than once */
841   if(!data->multi)
842     return CURLM_OK; /* it is already removed so let's say it is fine! */
843 
844   /* Prevent users from trying to remove an easy handle from the wrong multi */
845   if(data->multi != multi)
846     return CURLM_BAD_EASY_HANDLE;
847 
848   if(multi->in_callback)
849     return CURLM_RECURSIVE_API_CALL;
850 
851   premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE;
852 
853   /* If the 'state' is not INIT or COMPLETED, we might need to do something
854      nice to put the easy_handle in a good known state when this returns. */
855   if(premature) {
856     /* this handle is "alive" so we need to count down the total number of
857        alive connections when this is removed */
858     multi->num_alive--;
859   }
860 
861   if(data->conn &&
862      data->mstate > MSTATE_DO &&
863      data->mstate < MSTATE_COMPLETED) {
864     /* Set connection owner so that the DONE function closes it.  We can
865        safely do this here since connection is killed. */
866     streamclose(data->conn, "Removed with partial response");
867   }
868 
869   if(data->conn) {
870     /* multi_done() clears the association between the easy handle and the
871        connection.
872 
873        Note that this ignores the return code simply because there's
874        nothing really useful to do with it anyway! */
875     (void)multi_done(data, data->result, premature);
876   }
877 
878   /* The timer must be shut down before data->multi is set to NULL, else the
879      timenode will remain in the splay tree after curl_easy_cleanup is
880      called. Do it after multi_done() in case that sets another time! */
881   Curl_expire_clear(data);
882 
883   if(data->connect_queue.ptr) {
884     /* the handle is in the pending or msgsent lists, so go ahead and remove
885        it */
886     if(data->mstate == MSTATE_PENDING)
887       Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
888     else
889       Curl_llist_remove(&multi->msgsent, &data->connect_queue, NULL);
890   }
891   if(in_main_list(data))
892     unlink_easy(multi, data);
893 
894   if(data->dns.hostcachetype == HCACHE_MULTI) {
895     /* stop using the multi handle's DNS cache, *after* the possible
896        multi_done() call above */
897     data->dns.hostcache = NULL;
898     data->dns.hostcachetype = HCACHE_NONE;
899   }
900 
901   Curl_wildcard_dtor(&data->wildcard);
902 
903   /* change state without using multistate(), only to make singlesocket() do
904      what we want */
905   data->mstate = MSTATE_COMPLETED;
906 
907   /* This ignores the return code even in case of problems because there's
908      nothing more to do about that, here */
909   (void)singlesocket(multi, easy); /* to let the application know what sockets
910                                       that vanish with this handle */
911 
912   /* Remove the association between the connection and the handle */
913   Curl_detach_connection(data);
914 
915   if(data->set.connect_only && !data->multi_easy) {
916     /* This removes a handle that was part the multi interface that used
917        CONNECT_ONLY, that connection is now left alive but since this handle
918        has bits.close set nothing can use that transfer anymore and it is
919        forbidden from reuse. And this easy handle cannot find the connection
920        anymore once removed from the multi handle
921 
922        Better close the connection here, at once.
923     */
924     struct connectdata *c;
925     curl_socket_t s;
926     s = Curl_getconnectinfo(data, &c);
927     if((s != CURL_SOCKET_BAD) && c) {
928       Curl_conncache_remove_conn(data, c, TRUE);
929       Curl_disconnect(data, c, TRUE);
930     }
931   }
932 
933   if(data->state.lastconnect_id != -1) {
934     /* Mark any connect-only connection for closure */
935     Curl_conncache_foreach(data, data->state.conn_cache,
936                            NULL, close_connect_only);
937   }
938 
939 #ifdef USE_LIBPSL
940   /* Remove the PSL association. */
941   if(data->psl == &multi->psl)
942     data->psl = NULL;
943 #endif
944 
945   /* as this was using a shared connection cache we clear the pointer to that
946      since we're not part of that multi handle anymore */
947   data->state.conn_cache = NULL;
948 
949   data->multi = NULL; /* clear the association to this multi handle */
950 
951   /* make sure there's no pending message in the queue sent from this easy
952      handle */
953   for(e = multi->msglist.head; e; e = e->next) {
954     struct Curl_message *msg = e->ptr;
955 
956     if(msg->extmsg.easy_handle == easy) {
957       Curl_llist_remove(&multi->msglist, e, NULL);
958       /* there can only be one from this specific handle */
959       break;
960     }
961   }
962 
963   /* NOTE NOTE NOTE
964      We do not touch the easy handle here! */
965   multi->num_easy--; /* one less to care about now */
966 
967   process_pending_handles(multi);
968 
969   rc = Curl_update_timer(multi);
970   if(rc)
971     return rc;
972   return CURLM_OK;
973 }
974 
975 /* Return TRUE if the application asked for multiplexing */
Curl_multiplex_wanted(const struct Curl_multi * multi)976 bool Curl_multiplex_wanted(const struct Curl_multi *multi)
977 {
978   return (multi && (multi->multiplexing));
979 }
980 
981 /*
982  * Curl_detach_connection() removes the given transfer from the connection.
983  *
984  * This is the only function that should clear data->conn. This will
985  * occasionally be called with the data->conn pointer already cleared.
986  */
Curl_detach_connection(struct Curl_easy * data)987 void Curl_detach_connection(struct Curl_easy *data)
988 {
989   struct connectdata *conn = data->conn;
990   if(conn) {
991     Curl_conn_ev_data_detach(conn, data);
992     Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
993   }
994   data->conn = NULL;
995 }
996 
997 /*
998  * Curl_attach_connection() attaches this transfer to this connection.
999  *
1000  * This is the only function that should assign data->conn
1001  */
Curl_attach_connection(struct Curl_easy * data,struct connectdata * conn)1002 void Curl_attach_connection(struct Curl_easy *data,
1003                              struct connectdata *conn)
1004 {
1005   DEBUGASSERT(!data->conn);
1006   DEBUGASSERT(conn);
1007   data->conn = conn;
1008   Curl_llist_append(&conn->easyq, data, &data->conn_queue);
1009   if(conn->handler && conn->handler->attach)
1010     conn->handler->attach(data, conn);
1011   Curl_conn_ev_data_attach(conn, data);
1012 }
1013 
connecting_getsock(struct Curl_easy * data,curl_socket_t * socks)1014 static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
1015 {
1016   struct connectdata *conn = data->conn;
1017   (void)socks;
1018   /* Not using `conn->sockfd` as `Curl_xfer_setup()` initializes
1019    * that *after* the connect. */
1020   if(conn && conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD) {
1021     /* Default is to wait to something from the server */
1022     socks[0] = conn->sock[FIRSTSOCKET];
1023     return GETSOCK_READSOCK(0);
1024   }
1025   return GETSOCK_BLANK;
1026 }
1027 
protocol_getsock(struct Curl_easy * data,curl_socket_t * socks)1028 static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
1029 {
1030   struct connectdata *conn = data->conn;
1031   if(conn && conn->handler->proto_getsock)
1032     return conn->handler->proto_getsock(data, conn, socks);
1033   else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
1034     /* Default is to wait to something from the server */
1035     socks[0] = conn->sockfd;
1036     return GETSOCK_READSOCK(0);
1037   }
1038   return GETSOCK_BLANK;
1039 }
1040 
domore_getsock(struct Curl_easy * data,curl_socket_t * socks)1041 static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
1042 {
1043   struct connectdata *conn = data->conn;
1044   if(conn && conn->handler->domore_getsock)
1045     return conn->handler->domore_getsock(data, conn, socks);
1046   else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
1047     /* Default is that we want to send something to the server */
1048     socks[0] = conn->sockfd;
1049     return GETSOCK_WRITESOCK(0);
1050   }
1051   return GETSOCK_BLANK;
1052 }
1053 
doing_getsock(struct Curl_easy * data,curl_socket_t * socks)1054 static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
1055 {
1056   struct connectdata *conn = data->conn;
1057   if(conn && conn->handler->doing_getsock)
1058     return conn->handler->doing_getsock(data, conn, socks);
1059   else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
1060     /* Default is that we want to send something to the server */
1061     socks[0] = conn->sockfd;
1062     return GETSOCK_WRITESOCK(0);
1063   }
1064   return GETSOCK_BLANK;
1065 }
1066 
perform_getsock(struct Curl_easy * data,curl_socket_t * sock)1067 static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
1068 {
1069   struct connectdata *conn = data->conn;
1070 
1071   if(!conn)
1072     return GETSOCK_BLANK;
1073   else if(conn->handler->perform_getsock)
1074     return conn->handler->perform_getsock(data, conn, sock);
1075   else {
1076     /* Default is to obey the data->req.keepon flags for send/recv */
1077     int bitmap = GETSOCK_BLANK;
1078     unsigned sockindex = 0;
1079     if(CURL_WANT_RECV(data)) {
1080       DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
1081       bitmap |= GETSOCK_READSOCK(sockindex);
1082       sock[sockindex] = conn->sockfd;
1083     }
1084 
1085     if(CURL_WANT_SEND(data)) {
1086       if((conn->sockfd != conn->writesockfd) ||
1087          bitmap == GETSOCK_BLANK) {
1088         /* only if they are not the same socket and we have a readable
1089            one, we increase index */
1090         if(bitmap != GETSOCK_BLANK)
1091           sockindex++; /* increase index if we need two entries */
1092 
1093         DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
1094         sock[sockindex] = conn->writesockfd;
1095       }
1096       bitmap |= GETSOCK_WRITESOCK(sockindex);
1097     }
1098     return bitmap;
1099   }
1100 }
1101 
1102 /* Initializes `poll_set` with the current socket poll actions needed
1103  * for transfer `data`. */
multi_getsock(struct Curl_easy * data,struct easy_pollset * ps)1104 static void multi_getsock(struct Curl_easy *data,
1105                           struct easy_pollset *ps)
1106 {
1107   /* The no connection case can happen when this is called from
1108      curl_multi_remove_handle() => singlesocket() => multi_getsock().
1109   */
1110   Curl_pollset_reset(data, ps);
1111   if(!data->conn)
1112     return;
1113 
1114   switch(data->mstate) {
1115   case MSTATE_INIT:
1116   case MSTATE_PENDING:
1117   case MSTATE_SETUP:
1118   case MSTATE_CONNECT:
1119     /* nothing to poll for yet */
1120     break;
1121 
1122   case MSTATE_RESOLVING:
1123     Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
1124     /* connection filters are not involved in this phase */
1125     break;
1126 
1127   case MSTATE_CONNECTING:
1128   case MSTATE_TUNNELING:
1129     Curl_pollset_add_socks(data, ps, connecting_getsock);
1130     Curl_conn_adjust_pollset(data, ps);
1131     break;
1132 
1133   case MSTATE_PROTOCONNECT:
1134   case MSTATE_PROTOCONNECTING:
1135     Curl_pollset_add_socks(data, ps, protocol_getsock);
1136     Curl_conn_adjust_pollset(data, ps);
1137     break;
1138 
1139   case MSTATE_DO:
1140   case MSTATE_DOING:
1141     Curl_pollset_add_socks(data, ps, doing_getsock);
1142     Curl_conn_adjust_pollset(data, ps);
1143     break;
1144 
1145   case MSTATE_DOING_MORE:
1146     Curl_pollset_add_socks(data, ps, domore_getsock);
1147     Curl_conn_adjust_pollset(data, ps);
1148     break;
1149 
1150   case MSTATE_DID: /* same as PERFORMING in regard to polling */
1151   case MSTATE_PERFORMING:
1152     Curl_pollset_add_socks(data, ps, perform_getsock);
1153     Curl_conn_adjust_pollset(data, ps);
1154     break;
1155 
1156   case MSTATE_RATELIMITING:
1157     /* we need to let time pass, ignore socket(s) */
1158     break;
1159 
1160   case MSTATE_DONE:
1161   case MSTATE_COMPLETED:
1162   case MSTATE_MSGSENT:
1163     /* nothing more to poll for */
1164     break;
1165 
1166   default:
1167     failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
1168     DEBUGASSERT(0);
1169     break;
1170   }
1171 }
1172 
curl_multi_fdset(struct Curl_multi * multi,fd_set * read_fd_set,fd_set * write_fd_set,fd_set * exc_fd_set,int * max_fd)1173 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
1174                            fd_set *read_fd_set, fd_set *write_fd_set,
1175                            fd_set *exc_fd_set, int *max_fd)
1176 {
1177   /* Scan through all the easy handles to get the file descriptors set.
1178      Some easy handles may not have connected to the remote host yet,
1179      and then we must make sure that is done. */
1180   struct Curl_easy *data;
1181   int this_max_fd = -1;
1182   struct easy_pollset ps;
1183   unsigned int i;
1184   (void)exc_fd_set; /* not used */
1185 
1186   if(!GOOD_MULTI_HANDLE(multi))
1187     return CURLM_BAD_HANDLE;
1188 
1189   if(multi->in_callback)
1190     return CURLM_RECURSIVE_API_CALL;
1191 
1192   memset(&ps, 0, sizeof(ps));
1193   for(data = multi->easyp; data; data = data->next) {
1194     multi_getsock(data, &ps);
1195 
1196     for(i = 0; i < ps.num; i++) {
1197       if(!FDSET_SOCK(ps.sockets[i]))
1198         /* pretend it doesn't exist */
1199         continue;
1200       if(ps.actions[i] & CURL_POLL_IN)
1201         FD_SET(ps.sockets[i], read_fd_set);
1202       if(ps.actions[i] & CURL_POLL_OUT)
1203         FD_SET(ps.sockets[i], write_fd_set);
1204       if((int)ps.sockets[i] > this_max_fd)
1205         this_max_fd = (int)ps.sockets[i];
1206     }
1207   }
1208 
1209   *max_fd = this_max_fd;
1210 
1211   return CURLM_OK;
1212 }
1213 
curl_multi_waitfds(struct Curl_multi * multi,struct curl_waitfd * ufds,unsigned int size,unsigned int * fd_count)1214 CURLMcode curl_multi_waitfds(struct Curl_multi *multi,
1215                              struct curl_waitfd *ufds,
1216                              unsigned int size,
1217                              unsigned int *fd_count)
1218 {
1219   struct Curl_easy *data;
1220   unsigned int nfds = 0;
1221   struct easy_pollset ps;
1222   unsigned int i;
1223   CURLMcode result = CURLM_OK;
1224   struct curl_waitfd *ufd;
1225   unsigned int j;
1226 
1227   if(!ufds)
1228     return CURLM_BAD_FUNCTION_ARGUMENT;
1229 
1230   if(!GOOD_MULTI_HANDLE(multi))
1231     return CURLM_BAD_HANDLE;
1232 
1233   if(multi->in_callback)
1234     return CURLM_RECURSIVE_API_CALL;
1235 
1236   memset(&ps, 0, sizeof(ps));
1237   for(data = multi->easyp; data; data = data->next) {
1238     multi_getsock(data, &ps);
1239 
1240     for(i = 0; i < ps.num; i++) {
1241       if(nfds < size) {
1242         curl_socket_t fd = ps.sockets[i];
1243         int fd_idx = -1;
1244 
1245         /* Simple linear search to skip an already added descriptor */
1246         for(j = 0; j < nfds; j++) {
1247           if(ufds[j].fd == fd) {
1248             fd_idx = (int)j;
1249             break;
1250           }
1251         }
1252 
1253         if(fd_idx < 0) {
1254           ufd = &ufds[nfds++];
1255           ufd->fd = ps.sockets[i];
1256           ufd->events = 0;
1257         }
1258         else
1259           ufd = &ufds[fd_idx];
1260 
1261         if(ps.actions[i] & CURL_POLL_IN)
1262           ufd->events |= CURL_WAIT_POLLIN;
1263         if(ps.actions[i] & CURL_POLL_OUT)
1264           ufd->events |= CURL_WAIT_POLLOUT;
1265       }
1266       else
1267         return CURLM_OUT_OF_MEMORY;
1268     }
1269   }
1270 
1271   if(fd_count)
1272     *fd_count = nfds;
1273   return result;
1274 }
1275 
1276 #ifdef USE_WINSOCK
1277 /* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets can't
1278  * be reset this way because an empty datagram would be sent. #9203
1279  *
1280  * "On Windows the internal state of FD_WRITE as returned from
1281  * WSAEnumNetworkEvents is only reset after successful send()."
1282  */
reset_socket_fdwrite(curl_socket_t s)1283 static void reset_socket_fdwrite(curl_socket_t s)
1284 {
1285   int t;
1286   int l = (int)sizeof(t);
1287   if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
1288     send(s, NULL, 0, 0);
1289 }
1290 #endif
1291 
ufds_increase(struct pollfd ** pfds,unsigned int * pfds_len,unsigned int inc,bool * is_malloced)1292 static CURLMcode ufds_increase(struct pollfd **pfds, unsigned int *pfds_len,
1293                                unsigned int inc, bool *is_malloced)
1294 {
1295   struct pollfd *new_fds, *old_fds = *pfds;
1296   unsigned int new_len = *pfds_len + inc;
1297 
1298   new_fds = calloc(new_len, sizeof(struct pollfd));
1299   if(!new_fds) {
1300     if(*is_malloced)
1301       free(old_fds);
1302     *pfds = NULL;
1303     *pfds_len = 0;
1304     return CURLM_OUT_OF_MEMORY;
1305   }
1306   memcpy(new_fds, old_fds, (*pfds_len) * sizeof(struct pollfd));
1307   if(*is_malloced)
1308     free(old_fds);
1309   *pfds = new_fds;
1310   *pfds_len = new_len;
1311   *is_malloced = TRUE;
1312   return CURLM_OK;
1313 }
1314 
1315 #define NUM_POLLS_ON_STACK 10
1316 
multi_wait(struct Curl_multi * multi,struct curl_waitfd extra_fds[],unsigned int extra_nfds,int timeout_ms,int * ret,bool extrawait,bool use_wakeup)1317 static CURLMcode multi_wait(struct Curl_multi *multi,
1318                             struct curl_waitfd extra_fds[],
1319                             unsigned int extra_nfds,
1320                             int timeout_ms,
1321                             int *ret,
1322                             bool extrawait, /* when no socket, wait */
1323                             bool use_wakeup)
1324 {
1325   struct Curl_easy *data;
1326   struct easy_pollset ps;
1327   size_t i;
1328   long timeout_internal;
1329   int retcode = 0;
1330   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1331   struct pollfd *ufds = &a_few_on_stack[0];
1332   unsigned int ufds_len = NUM_POLLS_ON_STACK;
1333   unsigned int nfds = 0, curl_nfds = 0; /* how many ufds are in use */
1334   bool ufds_malloc = FALSE;
1335 #ifdef USE_WINSOCK
1336   WSANETWORKEVENTS wsa_events;
1337   DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1338 #endif
1339 #ifndef ENABLE_WAKEUP
1340   (void)use_wakeup;
1341 #endif
1342 
1343   if(!GOOD_MULTI_HANDLE(multi))
1344     return CURLM_BAD_HANDLE;
1345 
1346   if(multi->in_callback)
1347     return CURLM_RECURSIVE_API_CALL;
1348 
1349   if(timeout_ms < 0)
1350     return CURLM_BAD_FUNCTION_ARGUMENT;
1351 
1352   /* If the internally desired timeout is actually shorter than requested from
1353      the outside, then use the shorter time! But only if the internal timer
1354      is actually larger than -1! */
1355   (void)multi_timeout(multi, &timeout_internal);
1356   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1357     timeout_ms = (int)timeout_internal;
1358 
1359   memset(ufds, 0, ufds_len * sizeof(struct pollfd));
1360   memset(&ps, 0, sizeof(ps));
1361 
1362   /* Add the curl handles to our pollfds first */
1363   for(data = multi->easyp; data; data = data->next) {
1364     multi_getsock(data, &ps);
1365 
1366     for(i = 0; i < ps.num; i++) {
1367       short events = 0;
1368 #ifdef USE_WINSOCK
1369       long mask = 0;
1370 #endif
1371       if(ps.actions[i] & CURL_POLL_IN) {
1372 #ifdef USE_WINSOCK
1373         mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1374 #endif
1375         events |= POLLIN;
1376       }
1377       if(ps.actions[i] & CURL_POLL_OUT) {
1378 #ifdef USE_WINSOCK
1379         mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1380         reset_socket_fdwrite(ps.sockets[i]);
1381 #endif
1382         events |= POLLOUT;
1383       }
1384       if(events) {
1385         if(nfds && ps.sockets[i] == ufds[nfds-1].fd) {
1386           ufds[nfds-1].events |= events;
1387         }
1388         else {
1389           if(nfds >= ufds_len) {
1390             if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
1391               return CURLM_OUT_OF_MEMORY;
1392           }
1393           DEBUGASSERT(nfds < ufds_len);
1394           ufds[nfds].fd = ps.sockets[i];
1395           ufds[nfds].events = events;
1396           ++nfds;
1397         }
1398       }
1399 #ifdef USE_WINSOCK
1400       if(mask) {
1401         if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
1402           if(ufds_malloc)
1403             free(ufds);
1404           return CURLM_INTERNAL_ERROR;
1405         }
1406       }
1407 #endif
1408     }
1409   }
1410 
1411   curl_nfds = nfds; /* what curl internally used in ufds */
1412 
1413   /* Add external file descriptions from poll-like struct curl_waitfd */
1414   for(i = 0; i < extra_nfds; i++) {
1415 #ifdef USE_WINSOCK
1416     long mask = 0;
1417     if(extra_fds[i].events & CURL_WAIT_POLLIN)
1418       mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1419     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1420       mask |= FD_OOB;
1421     if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1422       mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1423       reset_socket_fdwrite(extra_fds[i].fd);
1424     }
1425     if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1426       if(ufds_malloc)
1427         free(ufds);
1428       return CURLM_INTERNAL_ERROR;
1429     }
1430 #endif
1431     if(nfds >= ufds_len) {
1432       if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
1433         return CURLM_OUT_OF_MEMORY;
1434     }
1435     DEBUGASSERT(nfds < ufds_len);
1436     ufds[nfds].fd = extra_fds[i].fd;
1437     ufds[nfds].events = 0;
1438     if(extra_fds[i].events & CURL_WAIT_POLLIN)
1439       ufds[nfds].events |= POLLIN;
1440     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1441       ufds[nfds].events |= POLLPRI;
1442     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1443       ufds[nfds].events |= POLLOUT;
1444     ++nfds;
1445   }
1446 
1447 #ifdef ENABLE_WAKEUP
1448 #ifndef USE_WINSOCK
1449   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1450     if(nfds >= ufds_len) {
1451       if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
1452         return CURLM_OUT_OF_MEMORY;
1453     }
1454     DEBUGASSERT(nfds < ufds_len);
1455     ufds[nfds].fd = multi->wakeup_pair[0];
1456     ufds[nfds].events = POLLIN;
1457     ++nfds;
1458   }
1459 #endif
1460 #endif
1461 
1462 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1463   if(nfds || use_wakeup) {
1464 #else
1465   if(nfds) {
1466 #endif
1467     int pollrc;
1468 #ifdef USE_WINSOCK
1469     if(nfds)
1470       pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1471     else
1472       pollrc = 0;
1473 #else
1474     pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1475 #endif
1476     if(pollrc < 0)
1477       return CURLM_UNRECOVERABLE_POLL;
1478 
1479     if(pollrc > 0) {
1480       retcode = pollrc;
1481 #ifdef USE_WINSOCK
1482     }
1483     else { /* now wait... if not ready during the pre-check (pollrc == 0) */
1484       WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1485     }
1486     /* With WinSock, we have to run the following section unconditionally
1487        to call WSAEventSelect(fd, event, 0) on all the sockets */
1488     {
1489 #endif
1490       /* copy revents results from the poll to the curl_multi_wait poll
1491          struct, the bit values of the actual underlying poll() implementation
1492          may not be the same as the ones in the public libcurl API! */
1493       for(i = 0; i < extra_nfds; i++) {
1494         unsigned r = ufds[curl_nfds + i].revents;
1495         unsigned short mask = 0;
1496 #ifdef USE_WINSOCK
1497         curl_socket_t s = extra_fds[i].fd;
1498         wsa_events.lNetworkEvents = 0;
1499         if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
1500           if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1501             mask |= CURL_WAIT_POLLIN;
1502           if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1503             mask |= CURL_WAIT_POLLOUT;
1504           if(wsa_events.lNetworkEvents & FD_OOB)
1505             mask |= CURL_WAIT_POLLPRI;
1506           if(ret && !pollrc && wsa_events.lNetworkEvents)
1507             retcode++;
1508         }
1509         WSAEventSelect(s, multi->wsa_event, 0);
1510         if(!pollrc) {
1511           extra_fds[i].revents = mask;
1512           continue;
1513         }
1514 #endif
1515         if(r & POLLIN)
1516           mask |= CURL_WAIT_POLLIN;
1517         if(r & POLLOUT)
1518           mask |= CURL_WAIT_POLLOUT;
1519         if(r & POLLPRI)
1520           mask |= CURL_WAIT_POLLPRI;
1521         extra_fds[i].revents = mask;
1522       }
1523 
1524 #ifdef USE_WINSOCK
1525       /* Count up all our own sockets that had activity,
1526          and remove them from the event. */
1527       if(curl_nfds) {
1528 
1529         for(data = multi->easyp; data; data = data->next) {
1530           multi_getsock(data, &ps);
1531 
1532           for(i = 0; i < ps.num; i++) {
1533             wsa_events.lNetworkEvents = 0;
1534             if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
1535                                     &wsa_events) == 0) {
1536               if(ret && !pollrc && wsa_events.lNetworkEvents)
1537                 retcode++;
1538             }
1539             WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
1540           }
1541         }
1542       }
1543 
1544       WSAResetEvent(multi->wsa_event);
1545 #else
1546 #ifdef ENABLE_WAKEUP
1547       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1548         if(ufds[curl_nfds + extra_nfds].revents & POLLIN) {
1549           char buf[64];
1550           ssize_t nread;
1551           while(1) {
1552             /* the reading socket is non-blocking, try to read
1553                data from it until it receives an error (except EINTR).
1554                In normal cases it will get EAGAIN or EWOULDBLOCK
1555                when there is no more data, breaking the loop. */
1556             nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1557             if(nread <= 0) {
1558               if(nread < 0 && EINTR == SOCKERRNO)
1559                 continue;
1560               break;
1561             }
1562           }
1563           /* do not count the wakeup socket into the returned value */
1564           retcode--;
1565         }
1566       }
1567 #endif
1568 #endif
1569     }
1570   }
1571 
1572   if(ufds_malloc)
1573     free(ufds);
1574   if(ret)
1575     *ret = retcode;
1576 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1577   if(extrawait && !nfds && !use_wakeup) {
1578 #else
1579   if(extrawait && !nfds) {
1580 #endif
1581     long sleep_ms = 0;
1582 
1583     /* Avoid busy-looping when there's nothing particular to wait for */
1584     if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1585       if(sleep_ms > timeout_ms)
1586         sleep_ms = timeout_ms;
1587       /* when there are no easy handles in the multi, this holds a -1
1588          timeout */
1589       else if(sleep_ms < 0)
1590         sleep_ms = timeout_ms;
1591       Curl_wait_ms(sleep_ms);
1592     }
1593   }
1594 
1595   return CURLM_OK;
1596 }
1597 
1598 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1599                           struct curl_waitfd extra_fds[],
1600                           unsigned int extra_nfds,
1601                           int timeout_ms,
1602                           int *ret)
1603 {
1604   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1605                     FALSE);
1606 }
1607 
1608 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1609                           struct curl_waitfd extra_fds[],
1610                           unsigned int extra_nfds,
1611                           int timeout_ms,
1612                           int *ret)
1613 {
1614   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1615                     TRUE);
1616 }
1617 
1618 CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1619 {
1620   /* this function is usually called from another thread,
1621      it has to be careful only to access parts of the
1622      Curl_multi struct that are constant */
1623 
1624   /* GOOD_MULTI_HANDLE can be safely called */
1625   if(!GOOD_MULTI_HANDLE(multi))
1626     return CURLM_BAD_HANDLE;
1627 
1628 #ifdef ENABLE_WAKEUP
1629 #ifdef USE_WINSOCK
1630   if(WSASetEvent(multi->wsa_event))
1631     return CURLM_OK;
1632 #else
1633   /* the wakeup_pair variable is only written during init and cleanup,
1634      making it safe to access from another thread after the init part
1635      and before cleanup */
1636   if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1637     char buf[1];
1638     buf[0] = 1;
1639     while(1) {
1640       /* swrite() is not thread-safe in general, because concurrent calls
1641          can have their messages interleaved, but in this case the content
1642          of the messages does not matter, which makes it ok to call.
1643 
1644          The write socket is set to non-blocking, this way this function
1645          cannot block, making it safe to call even from the same thread
1646          that will call curl_multi_wait(). If swrite() returns that it
1647          would block, it's considered successful because it means that
1648          previous calls to this function will wake up the poll(). */
1649       if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1650         int err = SOCKERRNO;
1651         int return_success;
1652 #ifdef USE_WINSOCK
1653         return_success = WSAEWOULDBLOCK == err;
1654 #else
1655         if(EINTR == err)
1656           continue;
1657         return_success = EWOULDBLOCK == err || EAGAIN == err;
1658 #endif
1659         if(!return_success)
1660           return CURLM_WAKEUP_FAILURE;
1661       }
1662       return CURLM_OK;
1663     }
1664   }
1665 #endif
1666 #endif
1667   return CURLM_WAKEUP_FAILURE;
1668 }
1669 
1670 /*
1671  * multi_ischanged() is called
1672  *
1673  * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1674  * => CONNECT action.
1675  *
1676  * Set 'clear' to TRUE to have it also clear the state variable.
1677  */
1678 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1679 {
1680   bool retval = multi->recheckstate;
1681   if(clear)
1682     multi->recheckstate = FALSE;
1683   return retval;
1684 }
1685 
1686 /*
1687  * Curl_multi_connchanged() is called to tell that there is a connection in
1688  * this multi handle that has changed state (multiplexing become possible, the
1689  * number of allowed streams changed or similar), and a subsequent use of this
1690  * multi handle should move CONNECT_PEND handles back to CONNECT to have them
1691  * retry.
1692  */
1693 void Curl_multi_connchanged(struct Curl_multi *multi)
1694 {
1695   multi->recheckstate = TRUE;
1696 }
1697 
1698 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1699                                  struct Curl_easy *data,
1700                                  struct connectdata *conn)
1701 {
1702   CURLMcode rc;
1703 
1704   if(multi->in_callback)
1705     return CURLM_RECURSIVE_API_CALL;
1706 
1707   rc = curl_multi_add_handle(multi, data);
1708   if(!rc) {
1709     struct SingleRequest *k = &data->req;
1710 
1711     /* pass in NULL for 'conn' here since we don't want to init the
1712        connection, only this transfer */
1713     Curl_init_do(data, NULL);
1714 
1715     /* take this handle to the perform state right away */
1716     multistate(data, MSTATE_PERFORMING);
1717     Curl_attach_connection(data, conn);
1718     k->keepon |= KEEP_RECV; /* setup to receive! */
1719   }
1720   return rc;
1721 }
1722 
1723 static CURLcode multi_do(struct Curl_easy *data, bool *done)
1724 {
1725   CURLcode result = CURLE_OK;
1726   struct connectdata *conn = data->conn;
1727 
1728   DEBUGASSERT(conn);
1729   DEBUGASSERT(conn->handler);
1730 
1731   if(conn->handler->do_it)
1732     result = conn->handler->do_it(data, done);
1733 
1734   return result;
1735 }
1736 
1737 /*
1738  * multi_do_more() is called during the DO_MORE multi state. It is basically a
1739  * second stage DO state which (wrongly) was introduced to support FTP's
1740  * second connection.
1741  *
1742  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1743  * DOING state there's more work to do!
1744  */
1745 
1746 static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1747 {
1748   CURLcode result = CURLE_OK;
1749   struct connectdata *conn = data->conn;
1750 
1751   *complete = 0;
1752 
1753   if(conn->handler->do_more)
1754     result = conn->handler->do_more(data, complete);
1755 
1756   return result;
1757 }
1758 
1759 /*
1760  * Check whether a timeout occurred, and handle it if it did
1761  */
1762 static bool multi_handle_timeout(struct Curl_easy *data,
1763                                  struct curltime *now,
1764                                  bool *stream_error,
1765                                  CURLcode *result,
1766                                  bool connect_timeout)
1767 {
1768   timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout);
1769   if(timeout_ms < 0) {
1770     /* Handle timed out */
1771     struct curltime since;
1772     if(connect_timeout)
1773       since = data->progress.t_startsingle;
1774     else
1775       since = data->progress.t_startop;
1776     if(data->mstate == MSTATE_RESOLVING)
1777       failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1778             " milliseconds", Curl_timediff(*now, since));
1779     else if(data->mstate == MSTATE_CONNECTING)
1780       failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1781             " milliseconds", Curl_timediff(*now, since));
1782     else {
1783       struct SingleRequest *k = &data->req;
1784       if(k->size != -1) {
1785         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1786               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1787               CURL_FORMAT_CURL_OFF_T " bytes received",
1788               Curl_timediff(*now, since), k->bytecount, k->size);
1789       }
1790       else {
1791         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1792               " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1793               " bytes received", Curl_timediff(*now, since), k->bytecount);
1794       }
1795     }
1796     *result = CURLE_OPERATION_TIMEDOUT;
1797     if(data->conn) {
1798       /* Force connection closed if the connection has indeed been used */
1799       if(data->mstate > MSTATE_DO) {
1800         streamclose(data->conn, "Disconnect due to timeout");
1801         *stream_error = TRUE;
1802       }
1803       (void)multi_done(data, *result, TRUE);
1804     }
1805     return TRUE;
1806   }
1807 
1808   return FALSE;
1809 }
1810 
1811 /*
1812  * We are doing protocol-specific connecting and this is being called over and
1813  * over from the multi interface until the connection phase is done on
1814  * protocol layer.
1815  */
1816 
1817 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1818 {
1819   CURLcode result = CURLE_OK;
1820   struct connectdata *conn = data->conn;
1821 
1822   if(conn && conn->handler->connecting) {
1823     *done = FALSE;
1824     result = conn->handler->connecting(data, done);
1825   }
1826   else
1827     *done = TRUE;
1828 
1829   return result;
1830 }
1831 
1832 /*
1833  * We are DOING this is being called over and over from the multi interface
1834  * until the DOING phase is done on protocol layer.
1835  */
1836 
1837 static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1838 {
1839   CURLcode result = CURLE_OK;
1840   struct connectdata *conn = data->conn;
1841 
1842   if(conn && conn->handler->doing) {
1843     *done = FALSE;
1844     result = conn->handler->doing(data, done);
1845   }
1846   else
1847     *done = TRUE;
1848 
1849   return result;
1850 }
1851 
1852 /*
1853  * We have discovered that the TCP connection has been successful, we can now
1854  * proceed with some action.
1855  *
1856  */
1857 static CURLcode protocol_connect(struct Curl_easy *data,
1858                                  bool *protocol_done)
1859 {
1860   CURLcode result = CURLE_OK;
1861   struct connectdata *conn = data->conn;
1862   DEBUGASSERT(conn);
1863   DEBUGASSERT(protocol_done);
1864 
1865   *protocol_done = FALSE;
1866 
1867   if(Curl_conn_is_connected(conn, FIRSTSOCKET)
1868      && conn->bits.protoconnstart) {
1869     /* We already are connected, get back. This may happen when the connect
1870        worked fine in the first call, like when we connect to a local server
1871        or proxy. Note that we don't know if the protocol is actually done.
1872 
1873        Unless this protocol doesn't have any protocol-connect callback, as
1874        then we know we're done. */
1875     if(!conn->handler->connecting)
1876       *protocol_done = TRUE;
1877 
1878     return CURLE_OK;
1879   }
1880 
1881   if(!conn->bits.protoconnstart) {
1882     if(conn->handler->connect_it) {
1883       /* is there a protocol-specific connect() procedure? */
1884 
1885       /* Call the protocol-specific connect function */
1886       result = conn->handler->connect_it(data, protocol_done);
1887     }
1888     else
1889       *protocol_done = TRUE;
1890 
1891     /* it has started, possibly even completed but that knowledge isn't stored
1892        in this bit! */
1893     if(!result)
1894       conn->bits.protoconnstart = TRUE;
1895   }
1896 
1897   return result; /* pass back status */
1898 }
1899 
1900 static void set_in_callback(struct Curl_multi *multi, bool value)
1901 {
1902   multi->in_callback = value;
1903 }
1904 
1905 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1906                                  struct curltime *nowp,
1907                                  struct Curl_easy *data)
1908 {
1909   struct Curl_message *msg = NULL;
1910   bool connected;
1911   bool async;
1912   bool protocol_connected = FALSE;
1913   bool dophase_done = FALSE;
1914   CURLMcode rc;
1915   CURLcode result = CURLE_OK;
1916   timediff_t recv_timeout_ms;
1917   timediff_t send_timeout_ms;
1918   int control;
1919 
1920   if(!GOOD_EASY_HANDLE(data))
1921     return CURLM_BAD_EASY_HANDLE;
1922 
1923   if(multi->dead) {
1924     /* a multi-level callback returned error before, meaning every individual
1925      transfer now has failed */
1926     result = CURLE_ABORTED_BY_CALLBACK;
1927     Curl_posttransfer(data);
1928     multi_done(data, result, FALSE);
1929     multistate(data, MSTATE_COMPLETED);
1930   }
1931 
1932   multi_warn_debug(multi, data);
1933 
1934   do {
1935     /* A "stream" here is a logical stream if the protocol can handle that
1936        (HTTP/2), or the full connection for older protocols */
1937     bool stream_error = FALSE;
1938     rc = CURLM_OK;
1939 
1940     if(multi_ischanged(multi, TRUE)) {
1941       DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
1942       process_pending_handles(multi); /* multiplexed */
1943     }
1944 
1945     if(data->mstate > MSTATE_CONNECT &&
1946        data->mstate < MSTATE_COMPLETED) {
1947       /* Make sure we set the connection's current owner */
1948       DEBUGASSERT(data->conn);
1949       if(!data->conn)
1950         return CURLM_INTERNAL_ERROR;
1951     }
1952 
1953     /* Wait for the connect state as only then is the start time stored, but
1954        we must not check already completed handles */
1955     if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) &&
1956        multi_handle_timeout(data, nowp, &stream_error, &result, FALSE))
1957       /* Skip the statemachine and go directly to error handling section. */
1958       goto statemachine_end;
1959 
1960     switch(data->mstate) {
1961     case MSTATE_INIT:
1962       /* Transitional state. init this transfer. A handle never comes
1963          back to this state. */
1964       result = Curl_pretransfer(data);
1965       if(result)
1966         break;
1967 
1968       /* after init, go SETUP */
1969       multistate(data, MSTATE_SETUP);
1970       (void)Curl_pgrsTime(data, TIMER_STARTOP);
1971       FALLTHROUGH();
1972 
1973     case MSTATE_SETUP:
1974       /* Transitional state. Setup things for a new transfer. The handle
1975          can come back to this state on a redirect. */
1976       *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1977       if(data->set.timeout)
1978         Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1979       if(data->set.connecttimeout)
1980         /* Since a connection might go to pending and back to CONNECT several
1981            times before it actually takes off, we need to set the timeout once
1982            in SETUP before we enter CONNECT the first time. */
1983         Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1984 
1985       multistate(data, MSTATE_CONNECT);
1986       FALLTHROUGH();
1987 
1988     case MSTATE_CONNECT:
1989       /* Connect. We want to get a connection identifier filled in. This state
1990          can be entered from SETUP and from PENDING. */
1991       result = Curl_connect(data, &async, &connected);
1992       if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1993         /* There was no connection available. We will go to the pending
1994            state and wait for an available connection. */
1995         multistate(data, MSTATE_PENDING);
1996 
1997         /* add this handle to the list of connect-pending handles */
1998         Curl_llist_append(&multi->pending, data, &data->connect_queue);
1999         /* unlink from the main list */
2000         unlink_easy(multi, data);
2001         result = CURLE_OK;
2002         break;
2003       }
2004       else
2005         process_pending_handles(data->multi);
2006 
2007       if(!result) {
2008         *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
2009         if(async)
2010           /* We're now waiting for an asynchronous name lookup */
2011           multistate(data, MSTATE_RESOLVING);
2012         else {
2013           /* after the connect has been sent off, go WAITCONNECT unless the
2014              protocol connect is already done and we can go directly to
2015              WAITDO or DO! */
2016           rc = CURLM_CALL_MULTI_PERFORM;
2017 
2018           if(connected)
2019             multistate(data, MSTATE_PROTOCONNECT);
2020           else {
2021             multistate(data, MSTATE_CONNECTING);
2022           }
2023         }
2024       }
2025       break;
2026 
2027     case MSTATE_RESOLVING:
2028       /* awaiting an asynch name resolve to complete */
2029     {
2030       struct Curl_dns_entry *dns = NULL;
2031       struct connectdata *conn = data->conn;
2032       const char *hostname;
2033 
2034       DEBUGASSERT(conn);
2035 #ifndef CURL_DISABLE_PROXY
2036       if(conn->bits.httpproxy)
2037         hostname = conn->http_proxy.host.name;
2038       else
2039 #endif
2040         if(conn->bits.conn_to_host)
2041           hostname = conn->conn_to_host.name;
2042       else
2043         hostname = conn->host.name;
2044 
2045       /* check if we have the name resolved by now */
2046       dns = Curl_fetch_addr(data, hostname, conn->primary.remote_port);
2047 
2048       if(dns) {
2049 #ifdef CURLRES_ASYNCH
2050         data->state.async.dns = dns;
2051         data->state.async.done = TRUE;
2052 #endif
2053         result = CURLE_OK;
2054         infof(data, "Hostname '%s' was found in DNS cache", hostname);
2055       }
2056 
2057       if(!dns)
2058         result = Curl_resolv_check(data, &dns);
2059 
2060       /* Update sockets here, because the socket(s) may have been
2061          closed and the application thus needs to be told, even if it
2062          is likely that the same socket(s) will again be used further
2063          down.  If the name has not yet been resolved, it is likely
2064          that new sockets have been opened in an attempt to contact
2065          another resolver. */
2066       rc = singlesocket(multi, data);
2067       if(rc)
2068         return rc;
2069 
2070       if(dns) {
2071         /* Perform the next step in the connection phase, and then move on
2072            to the WAITCONNECT state */
2073         result = Curl_once_resolved(data, &connected);
2074 
2075         if(result)
2076           /* if Curl_once_resolved() returns failure, the connection struct
2077              is already freed and gone */
2078           data->conn = NULL; /* no more connection */
2079         else {
2080           /* call again please so that we get the next socket setup */
2081           rc = CURLM_CALL_MULTI_PERFORM;
2082           if(connected)
2083             multistate(data, MSTATE_PROTOCONNECT);
2084           else {
2085             multistate(data, MSTATE_CONNECTING);
2086           }
2087         }
2088       }
2089 
2090       if(result) {
2091         /* failure detected */
2092         stream_error = TRUE;
2093         break;
2094       }
2095     }
2096     break;
2097 
2098 #ifndef CURL_DISABLE_HTTP
2099     case MSTATE_TUNNELING:
2100       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
2101       DEBUGASSERT(data->conn);
2102       result = Curl_http_connect(data, &protocol_connected);
2103 #ifndef CURL_DISABLE_PROXY
2104       if(data->conn->bits.proxy_connect_closed) {
2105         rc = CURLM_CALL_MULTI_PERFORM;
2106         /* connect back to proxy again */
2107         result = CURLE_OK;
2108         multi_done(data, CURLE_OK, FALSE);
2109         multistate(data, MSTATE_CONNECT);
2110       }
2111       else
2112 #endif
2113         if(!result) {
2114           rc = CURLM_CALL_MULTI_PERFORM;
2115           /* initiate protocol connect phase */
2116           multistate(data, MSTATE_PROTOCONNECT);
2117         }
2118       else
2119         stream_error = TRUE;
2120       break;
2121 #endif
2122 
2123     case MSTATE_CONNECTING:
2124       /* awaiting a completion of an asynch TCP connect */
2125       DEBUGASSERT(data->conn);
2126       result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
2127       if(connected && !result) {
2128         rc = CURLM_CALL_MULTI_PERFORM;
2129         multistate(data, MSTATE_PROTOCONNECT);
2130       }
2131       else if(result) {
2132         /* failure detected */
2133         Curl_posttransfer(data);
2134         multi_done(data, result, TRUE);
2135         stream_error = TRUE;
2136         break;
2137       }
2138       break;
2139 
2140     case MSTATE_PROTOCONNECT:
2141       if(!result && data->conn->bits.reuse) {
2142         /* ftp seems to hang when protoconnect on reused connection
2143          * since we handle PROTOCONNECT in general inside the filers, it
2144          * seems wrong to restart this on a reused connection. */
2145         multistate(data, MSTATE_DO);
2146         rc = CURLM_CALL_MULTI_PERFORM;
2147         break;
2148       }
2149       if(!result)
2150         result = protocol_connect(data, &protocol_connected);
2151       if(!result && !protocol_connected) {
2152         /* switch to waiting state */
2153         multistate(data, MSTATE_PROTOCONNECTING);
2154         rc = CURLM_CALL_MULTI_PERFORM;
2155       }
2156       else if(!result) {
2157         /* protocol connect has completed, go WAITDO or DO */
2158         multistate(data, MSTATE_DO);
2159         rc = CURLM_CALL_MULTI_PERFORM;
2160       }
2161       else {
2162         /* failure detected */
2163         Curl_posttransfer(data);
2164         multi_done(data, result, TRUE);
2165         stream_error = TRUE;
2166       }
2167       break;
2168 
2169     case MSTATE_PROTOCONNECTING:
2170       /* protocol-specific connect phase */
2171       result = protocol_connecting(data, &protocol_connected);
2172       if(!result && protocol_connected) {
2173         /* after the connect has completed, go WAITDO or DO */
2174         multistate(data, MSTATE_DO);
2175         rc = CURLM_CALL_MULTI_PERFORM;
2176       }
2177       else if(result) {
2178         /* failure detected */
2179         Curl_posttransfer(data);
2180         multi_done(data, result, TRUE);
2181         stream_error = TRUE;
2182       }
2183       break;
2184 
2185     case MSTATE_DO:
2186       if(data->set.fprereq) {
2187         int prereq_rc;
2188 
2189         /* call the prerequest callback function */
2190         Curl_set_in_callback(data, true);
2191         prereq_rc = data->set.fprereq(data->set.prereq_userp,
2192                                       data->info.primary.remote_ip,
2193                                       data->info.primary.local_ip,
2194                                       data->info.primary.remote_port,
2195                                       data->info.primary.local_port);
2196         Curl_set_in_callback(data, false);
2197         if(prereq_rc != CURL_PREREQFUNC_OK) {
2198           failf(data, "operation aborted by pre-request callback");
2199           /* failure in pre-request callback - don't do any other processing */
2200           result = CURLE_ABORTED_BY_CALLBACK;
2201           Curl_posttransfer(data);
2202           multi_done(data, result, FALSE);
2203           stream_error = TRUE;
2204           break;
2205         }
2206       }
2207 
2208       if(data->set.connect_only == 1) {
2209         /* keep connection open for application to use the socket */
2210         connkeep(data->conn, "CONNECT_ONLY");
2211         multistate(data, MSTATE_DONE);
2212         result = CURLE_OK;
2213         rc = CURLM_CALL_MULTI_PERFORM;
2214       }
2215       else {
2216         /* Perform the protocol's DO action */
2217         result = multi_do(data, &dophase_done);
2218 
2219         /* When multi_do() returns failure, data->conn might be NULL! */
2220 
2221         if(!result) {
2222           if(!dophase_done) {
2223 #ifndef CURL_DISABLE_FTP
2224             /* some steps needed for wildcard matching */
2225             if(data->state.wildcardmatch) {
2226               struct WildcardData *wc = data->wildcard;
2227               if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2228                 /* skip some states if it is important */
2229                 multi_done(data, CURLE_OK, FALSE);
2230 
2231                 /* if there's no connection left, skip the DONE state */
2232                 multistate(data, data->conn ?
2233                            MSTATE_DONE : MSTATE_COMPLETED);
2234                 rc = CURLM_CALL_MULTI_PERFORM;
2235                 break;
2236               }
2237             }
2238 #endif
2239             /* DO was not completed in one function call, we must continue
2240                DOING... */
2241             multistate(data, MSTATE_DOING);
2242             rc = CURLM_CALL_MULTI_PERFORM;
2243           }
2244 
2245           /* after DO, go DO_DONE... or DO_MORE */
2246           else if(data->conn->bits.do_more) {
2247             /* we're supposed to do more, but we need to sit down, relax
2248                and wait a little while first */
2249             multistate(data, MSTATE_DOING_MORE);
2250             rc = CURLM_CALL_MULTI_PERFORM;
2251           }
2252           else {
2253             /* we're done with the DO, now DID */
2254             multistate(data, MSTATE_DID);
2255             rc = CURLM_CALL_MULTI_PERFORM;
2256           }
2257         }
2258         else if((CURLE_SEND_ERROR == result) &&
2259                 data->conn->bits.reuse) {
2260           /*
2261            * In this situation, a connection that we were trying to use
2262            * may have unexpectedly died.  If possible, send the connection
2263            * back to the CONNECT phase so we can try again.
2264            */
2265           char *newurl = NULL;
2266           followtype follow = FOLLOW_NONE;
2267           CURLcode drc;
2268 
2269           drc = Curl_retry_request(data, &newurl);
2270           if(drc) {
2271             /* a failure here pretty much implies an out of memory */
2272             result = drc;
2273             stream_error = TRUE;
2274           }
2275 
2276           Curl_posttransfer(data);
2277           drc = multi_done(data, result, FALSE);
2278 
2279           /* When set to retry the connection, we must go back to the CONNECT
2280            * state */
2281           if(newurl) {
2282             if(!drc || (drc == CURLE_SEND_ERROR)) {
2283               follow = FOLLOW_RETRY;
2284               drc = Curl_follow(data, newurl, follow);
2285               if(!drc) {
2286                 multistate(data, MSTATE_SETUP);
2287                 rc = CURLM_CALL_MULTI_PERFORM;
2288                 result = CURLE_OK;
2289               }
2290               else {
2291                 /* Follow failed */
2292                 result = drc;
2293               }
2294             }
2295             else {
2296               /* done didn't return OK or SEND_ERROR */
2297               result = drc;
2298             }
2299           }
2300           else {
2301             /* Have error handler disconnect conn if we can't retry */
2302             stream_error = TRUE;
2303           }
2304           free(newurl);
2305         }
2306         else {
2307           /* failure detected */
2308           Curl_posttransfer(data);
2309           if(data->conn)
2310             multi_done(data, result, FALSE);
2311           stream_error = TRUE;
2312         }
2313       }
2314       break;
2315 
2316     case MSTATE_DOING:
2317       /* we continue DOING until the DO phase is complete */
2318       DEBUGASSERT(data->conn);
2319       result = protocol_doing(data, &dophase_done);
2320       if(!result) {
2321         if(dophase_done) {
2322           /* after DO, go DO_DONE or DO_MORE */
2323           multistate(data, data->conn->bits.do_more?
2324                      MSTATE_DOING_MORE : MSTATE_DID);
2325           rc = CURLM_CALL_MULTI_PERFORM;
2326         } /* dophase_done */
2327       }
2328       else {
2329         /* failure detected */
2330         Curl_posttransfer(data);
2331         multi_done(data, result, FALSE);
2332         stream_error = TRUE;
2333       }
2334       break;
2335 
2336     case MSTATE_DOING_MORE:
2337       /*
2338        * When we are connected, DOING MORE and then go DID
2339        */
2340       DEBUGASSERT(data->conn);
2341       result = multi_do_more(data, &control);
2342 
2343       if(!result) {
2344         if(control) {
2345           /* if positive, advance to DO_DONE
2346              if negative, go back to DOING */
2347           multistate(data, control == 1?
2348                      MSTATE_DID : MSTATE_DOING);
2349           rc = CURLM_CALL_MULTI_PERFORM;
2350         }
2351         /* else
2352            stay in DO_MORE */
2353       }
2354       else {
2355         /* failure detected */
2356         Curl_posttransfer(data);
2357         multi_done(data, result, FALSE);
2358         stream_error = TRUE;
2359       }
2360       break;
2361 
2362     case MSTATE_DID:
2363       DEBUGASSERT(data->conn);
2364       if(data->conn->bits.multiplex)
2365         /* Check if we can move pending requests to send pipe */
2366         process_pending_handles(multi); /*  multiplexed */
2367 
2368       /* Only perform the transfer if there's a good socket to work with.
2369          Having both BAD is a signal to skip immediately to DONE */
2370       if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2371          (data->conn->writesockfd != CURL_SOCKET_BAD))
2372         multistate(data, MSTATE_PERFORMING);
2373       else {
2374 #ifndef CURL_DISABLE_FTP
2375         if(data->state.wildcardmatch &&
2376            ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2377           data->wildcard->state = CURLWC_DONE;
2378         }
2379 #endif
2380         multistate(data, MSTATE_DONE);
2381       }
2382       rc = CURLM_CALL_MULTI_PERFORM;
2383       break;
2384 
2385     case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2386       DEBUGASSERT(data->conn);
2387       /* if both rates are within spec, resume transfer */
2388       if(Curl_pgrsUpdate(data))
2389         result = CURLE_ABORTED_BY_CALLBACK;
2390       else
2391         result = Curl_speedcheck(data, *nowp);
2392 
2393       if(result) {
2394         if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2395            result != CURLE_HTTP2_STREAM)
2396           streamclose(data->conn, "Transfer returned error");
2397 
2398         Curl_posttransfer(data);
2399         multi_done(data, result, TRUE);
2400       }
2401       else {
2402         send_timeout_ms = 0;
2403         if(data->set.max_send_speed)
2404           send_timeout_ms =
2405             Curl_pgrsLimitWaitTime(data->progress.uploaded,
2406                                    data->progress.ul_limit_size,
2407                                    data->set.max_send_speed,
2408                                    data->progress.ul_limit_start,
2409                                    *nowp);
2410 
2411         recv_timeout_ms = 0;
2412         if(data->set.max_recv_speed)
2413           recv_timeout_ms =
2414             Curl_pgrsLimitWaitTime(data->progress.downloaded,
2415                                    data->progress.dl_limit_size,
2416                                    data->set.max_recv_speed,
2417                                    data->progress.dl_limit_start,
2418                                    *nowp);
2419 
2420         if(!send_timeout_ms && !recv_timeout_ms) {
2421           multistate(data, MSTATE_PERFORMING);
2422           Curl_ratelimit(data, *nowp);
2423         }
2424         else if(send_timeout_ms >= recv_timeout_ms)
2425           Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2426         else
2427           Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2428       }
2429       break;
2430 
2431     case MSTATE_PERFORMING:
2432     {
2433       char *newurl = NULL;
2434       bool retry = FALSE;
2435       /* check if over send speed */
2436       send_timeout_ms = 0;
2437       if(data->set.max_send_speed)
2438         send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2439                                                  data->progress.ul_limit_size,
2440                                                  data->set.max_send_speed,
2441                                                  data->progress.ul_limit_start,
2442                                                  *nowp);
2443 
2444       /* check if over recv speed */
2445       recv_timeout_ms = 0;
2446       if(data->set.max_recv_speed)
2447         recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2448                                                  data->progress.dl_limit_size,
2449                                                  data->set.max_recv_speed,
2450                                                  data->progress.dl_limit_start,
2451                                                  *nowp);
2452 
2453       if(send_timeout_ms || recv_timeout_ms) {
2454         Curl_ratelimit(data, *nowp);
2455         multistate(data, MSTATE_RATELIMITING);
2456         if(send_timeout_ms >= recv_timeout_ms)
2457           Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2458         else
2459           Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2460         break;
2461       }
2462 
2463       /* read/write data if it is ready to do so */
2464       result = Curl_readwrite(data);
2465 
2466       if(data->req.done || (result == CURLE_RECV_ERROR)) {
2467         /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2468          * condition and the server closed the reused connection exactly when
2469          * we wanted to use it, so figure out if that is indeed the case.
2470          */
2471         CURLcode ret = Curl_retry_request(data, &newurl);
2472         if(!ret)
2473           retry = (newurl)?TRUE:FALSE;
2474         else if(!result)
2475           result = ret;
2476 
2477         if(retry) {
2478           /* if we are to retry, set the result to OK and consider the
2479              request as done */
2480           result = CURLE_OK;
2481           data->req.done = TRUE;
2482         }
2483       }
2484       else if((CURLE_HTTP2_STREAM == result) &&
2485               Curl_h2_http_1_1_error(data)) {
2486         CURLcode ret = Curl_retry_request(data, &newurl);
2487 
2488         if(!ret) {
2489           infof(data, "Downgrades to HTTP/1.1");
2490           streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2491           data->state.httpwant = CURL_HTTP_VERSION_1_1;
2492           /* clear the error message bit too as we ignore the one we got */
2493           data->state.errorbuf = FALSE;
2494           if(!newurl)
2495             /* typically for HTTP_1_1_REQUIRED error on first flight */
2496             newurl = strdup(data->state.url);
2497           /* if we are to retry, set the result to OK and consider the request
2498              as done */
2499           retry = TRUE;
2500           result = CURLE_OK;
2501           data->req.done = TRUE;
2502         }
2503         else
2504           result = ret;
2505       }
2506 
2507       if(result) {
2508         /*
2509          * The transfer phase returned error, we mark the connection to get
2510          * closed to prevent being reused. This is because we can't possibly
2511          * know if the connection is in a good shape or not now.  Unless it is
2512          * a protocol which uses two "channels" like FTP, as then the error
2513          * happened in the data connection.
2514          */
2515 
2516         if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2517            result != CURLE_HTTP2_STREAM)
2518           streamclose(data->conn, "Transfer returned error");
2519 
2520         Curl_posttransfer(data);
2521         multi_done(data, result, TRUE);
2522       }
2523       else if(data->req.done && !Curl_cwriter_is_paused(data)) {
2524 
2525         /* call this even if the readwrite function returned error */
2526         Curl_posttransfer(data);
2527 
2528         /* When we follow redirects or is set to retry the connection, we must
2529            to go back to the CONNECT state */
2530         if(data->req.newurl || retry) {
2531           followtype follow = FOLLOW_NONE;
2532           if(!retry) {
2533             /* if the URL is a follow-location and not just a retried request
2534                then figure out the URL here */
2535             free(newurl);
2536             newurl = data->req.newurl;
2537             data->req.newurl = NULL;
2538             follow = FOLLOW_REDIR;
2539           }
2540           else
2541             follow = FOLLOW_RETRY;
2542           (void)multi_done(data, CURLE_OK, FALSE);
2543           /* multi_done() might return CURLE_GOT_NOTHING */
2544           result = Curl_follow(data, newurl, follow);
2545           if(!result) {
2546             multistate(data, MSTATE_SETUP);
2547             rc = CURLM_CALL_MULTI_PERFORM;
2548           }
2549         }
2550         else {
2551           /* after the transfer is done, go DONE */
2552 
2553           /* but first check to see if we got a location info even though we're
2554              not following redirects */
2555           if(data->req.location) {
2556             free(newurl);
2557             newurl = data->req.location;
2558             data->req.location = NULL;
2559             result = Curl_follow(data, newurl, FOLLOW_FAKE);
2560             if(result) {
2561               stream_error = TRUE;
2562               result = multi_done(data, result, TRUE);
2563             }
2564           }
2565 
2566           if(!result) {
2567             multistate(data, MSTATE_DONE);
2568             rc = CURLM_CALL_MULTI_PERFORM;
2569           }
2570         }
2571       }
2572       else if(data->state.select_bits) {
2573         /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2574            won't get stuck on this transfer at the expense of other concurrent
2575            transfers */
2576         Curl_expire(data, 0, EXPIRE_RUN_NOW);
2577       }
2578       free(newurl);
2579       break;
2580     }
2581 
2582     case MSTATE_DONE:
2583       /* this state is highly transient, so run another loop after this */
2584       rc = CURLM_CALL_MULTI_PERFORM;
2585 
2586       if(data->conn) {
2587         CURLcode res;
2588 
2589         if(data->conn->bits.multiplex)
2590           /* Check if we can move pending requests to connection */
2591           process_pending_handles(multi); /* multiplexing */
2592 
2593         /* post-transfer command */
2594         res = multi_done(data, result, FALSE);
2595 
2596         /* allow a previously set error code take precedence */
2597         if(!result)
2598           result = res;
2599       }
2600 
2601 #ifndef CURL_DISABLE_FTP
2602       if(data->state.wildcardmatch) {
2603         if(data->wildcard->state != CURLWC_DONE) {
2604           /* if a wildcard is set and we are not ending -> lets start again
2605              with MSTATE_INIT */
2606           multistate(data, MSTATE_INIT);
2607           break;
2608         }
2609       }
2610 #endif
2611       /* after we have DONE what we're supposed to do, go COMPLETED, and
2612          it doesn't matter what the multi_done() returned! */
2613       multistate(data, MSTATE_COMPLETED);
2614       break;
2615 
2616     case MSTATE_COMPLETED:
2617       break;
2618 
2619     case MSTATE_PENDING:
2620     case MSTATE_MSGSENT:
2621       /* handles in these states should NOT be in this list */
2622       DEBUGASSERT(0);
2623       break;
2624 
2625     default:
2626       return CURLM_INTERNAL_ERROR;
2627     }
2628 
2629     if(data->mstate >= MSTATE_CONNECT &&
2630        data->mstate < MSTATE_DO &&
2631        rc != CURLM_CALL_MULTI_PERFORM &&
2632        !multi_ischanged(multi, false)) {
2633       /* We now handle stream timeouts if and only if this will be the last
2634        * loop iteration. We only check this on the last iteration to ensure
2635        * that if we know we have additional work to do immediately
2636        * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2637        * declaring the connection timed out as we may almost have a completed
2638        * connection. */
2639       multi_handle_timeout(data, nowp, &stream_error, &result, FALSE);
2640     }
2641 
2642 statemachine_end:
2643 
2644     if(data->mstate < MSTATE_COMPLETED) {
2645       if(result) {
2646         /*
2647          * If an error was returned, and we aren't in completed state now,
2648          * then we go to completed and consider this transfer aborted.
2649          */
2650 
2651         /* NOTE: no attempt to disconnect connections must be made
2652            in the case blocks above - cleanup happens only here */
2653 
2654         /* Check if we can move pending requests to send pipe */
2655         process_pending_handles(multi); /* connection */
2656 
2657         if(data->conn) {
2658           if(stream_error) {
2659             /* Don't attempt to send data over a connection that timed out */
2660             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2661             struct connectdata *conn = data->conn;
2662 
2663             /* This is where we make sure that the conn pointer is reset.
2664                We don't have to do this in every case block above where a
2665                failure is detected */
2666             Curl_detach_connection(data);
2667 
2668             /* remove connection from cache */
2669             Curl_conncache_remove_conn(data, conn, TRUE);
2670 
2671             /* disconnect properly */
2672             Curl_disconnect(data, conn, dead_connection);
2673           }
2674         }
2675         else if(data->mstate == MSTATE_CONNECT) {
2676           /* Curl_connect() failed */
2677           (void)Curl_posttransfer(data);
2678         }
2679 
2680         multistate(data, MSTATE_COMPLETED);
2681         rc = CURLM_CALL_MULTI_PERFORM;
2682       }
2683       /* if there's still a connection to use, call the progress function */
2684       else if(data->conn && Curl_pgrsUpdate(data)) {
2685         /* aborted due to progress callback return code must close the
2686            connection */
2687         result = CURLE_ABORTED_BY_CALLBACK;
2688         streamclose(data->conn, "Aborted by callback");
2689 
2690         /* if not yet in DONE state, go there, otherwise COMPLETED */
2691         multistate(data, (data->mstate < MSTATE_DONE)?
2692                    MSTATE_DONE: MSTATE_COMPLETED);
2693         rc = CURLM_CALL_MULTI_PERFORM;
2694       }
2695     }
2696 
2697     if(MSTATE_COMPLETED == data->mstate) {
2698       if(data->set.fmultidone) {
2699         /* signal via callback instead */
2700         data->set.fmultidone(data, result);
2701       }
2702       else {
2703         /* now fill in the Curl_message with this info */
2704         msg = &data->msg;
2705 
2706         msg->extmsg.msg = CURLMSG_DONE;
2707         msg->extmsg.easy_handle = data;
2708         msg->extmsg.data.result = result;
2709 
2710         multi_addmsg(multi, msg);
2711         DEBUGASSERT(!data->conn);
2712       }
2713       multistate(data, MSTATE_MSGSENT);
2714 
2715       /* add this handle to the list of msgsent handles */
2716       Curl_llist_append(&multi->msgsent, data, &data->connect_queue);
2717       /* unlink from the main list */
2718       unlink_easy(multi, data);
2719       return CURLM_OK;
2720     }
2721   } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2722 
2723   data->result = result;
2724   return rc;
2725 }
2726 
2727 
2728 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2729 {
2730   struct Curl_easy *data;
2731   CURLMcode returncode = CURLM_OK;
2732   struct Curl_tree *t;
2733   struct curltime now = Curl_now();
2734 
2735   if(!GOOD_MULTI_HANDLE(multi))
2736     return CURLM_BAD_HANDLE;
2737 
2738   if(multi->in_callback)
2739     return CURLM_RECURSIVE_API_CALL;
2740 
2741   data = multi->easyp;
2742   if(data) {
2743     CURLMcode result;
2744     bool nosig = data->set.no_signal;
2745     SIGPIPE_VARIABLE(pipe_st);
2746     sigpipe_ignore(data, &pipe_st);
2747     /* Do the loop and only alter the signal ignore state if the next handle
2748        has a different NO_SIGNAL state than the previous */
2749     do {
2750       /* the current node might be unlinked in multi_runsingle(), get the next
2751          pointer now */
2752       struct Curl_easy *datanext = data->next;
2753       if(data->set.no_signal != nosig) {
2754         sigpipe_restore(&pipe_st);
2755         sigpipe_ignore(data, &pipe_st);
2756         nosig = data->set.no_signal;
2757       }
2758       result = multi_runsingle(multi, &now, data);
2759       if(result)
2760         returncode = result;
2761       data = datanext; /* operate on next handle */
2762     } while(data);
2763     sigpipe_restore(&pipe_st);
2764   }
2765 
2766   /*
2767    * Simply remove all expired timers from the splay since handles are dealt
2768    * with unconditionally by this function and curl_multi_timeout() requires
2769    * that already passed/handled expire times are removed from the splay.
2770    *
2771    * It is important that the 'now' value is set at the entry of this function
2772    * and not for the current time as it may have ticked a little while since
2773    * then and then we risk this loop to remove timers that actually have not
2774    * been handled!
2775    */
2776   do {
2777     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2778     if(t) {
2779       /* the removed may have another timeout in queue */
2780       data = t->payload;
2781       if(data->mstate == MSTATE_PENDING) {
2782         bool stream_unused;
2783         CURLcode result_unused;
2784         if(multi_handle_timeout(data, &now, &stream_unused, &result_unused,
2785                                 FALSE)) {
2786           infof(data, "PENDING handle timeout");
2787           move_pending_to_connect(multi, data);
2788         }
2789       }
2790       (void)add_next_timeout(now, multi, t->payload);
2791     }
2792   } while(t);
2793 
2794   *running_handles = multi->num_alive;
2795 
2796   if(CURLM_OK >= returncode)
2797     returncode = Curl_update_timer(multi);
2798 
2799   return returncode;
2800 }
2801 
2802 /* unlink_all_msgsent_handles() detaches all those easy handles from this
2803    multi handle */
2804 static void unlink_all_msgsent_handles(struct Curl_multi *multi)
2805 {
2806   struct Curl_llist_element *e = multi->msgsent.head;
2807   if(e) {
2808     struct Curl_easy *data = e->ptr;
2809     DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
2810     data->multi = NULL;
2811   }
2812 }
2813 
2814 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2815 {
2816   struct Curl_easy *data;
2817   struct Curl_easy *nextdata;
2818 
2819   if(GOOD_MULTI_HANDLE(multi)) {
2820     if(multi->in_callback)
2821       return CURLM_RECURSIVE_API_CALL;
2822 
2823     multi->magic = 0; /* not good anymore */
2824 
2825     unlink_all_msgsent_handles(multi);
2826     process_pending_handles(multi);
2827     /* First remove all remaining easy handles */
2828     data = multi->easyp;
2829     while(data) {
2830       nextdata = data->next;
2831       if(!data->state.done && data->conn)
2832         /* if DONE was never called for this handle */
2833         (void)multi_done(data, CURLE_OK, TRUE);
2834       if(data->dns.hostcachetype == HCACHE_MULTI) {
2835         /* clear out the usage of the shared DNS cache */
2836         Curl_hostcache_clean(data, data->dns.hostcache);
2837         data->dns.hostcache = NULL;
2838         data->dns.hostcachetype = HCACHE_NONE;
2839       }
2840 
2841       /* Clear the pointer to the connection cache */
2842       data->state.conn_cache = NULL;
2843       data->multi = NULL; /* clear the association */
2844 
2845 #ifdef USE_LIBPSL
2846       if(data->psl == &multi->psl)
2847         data->psl = NULL;
2848 #endif
2849 
2850       data = nextdata;
2851     }
2852 
2853     /* Close all the connections in the connection cache */
2854     Curl_conncache_close_all_connections(&multi->conn_cache);
2855 
2856     sockhash_destroy(&multi->sockhash);
2857     Curl_conncache_destroy(&multi->conn_cache);
2858     Curl_hash_destroy(&multi->hostcache);
2859     Curl_psl_destroy(&multi->psl);
2860 
2861 #ifdef USE_WINSOCK
2862     WSACloseEvent(multi->wsa_event);
2863 #else
2864 #ifdef ENABLE_WAKEUP
2865     wakeup_close(multi->wakeup_pair[0]);
2866     wakeup_close(multi->wakeup_pair[1]);
2867 #endif
2868 #endif
2869 
2870 #ifdef USE_SSL
2871     Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
2872 #endif
2873 
2874     multi_xfer_bufs_free(multi);
2875     free(multi);
2876 
2877     return CURLM_OK;
2878   }
2879   return CURLM_BAD_HANDLE;
2880 }
2881 
2882 /*
2883  * curl_multi_info_read()
2884  *
2885  * This function is the primary way for a multi/multi_socket application to
2886  * figure out if a transfer has ended. We MUST make this function as fast as
2887  * possible as it will be polled frequently and we MUST NOT scan any lists in
2888  * here to figure out things. We must scale fine to thousands of handles and
2889  * beyond. The current design is fully O(1).
2890  */
2891 
2892 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2893 {
2894   struct Curl_message *msg;
2895 
2896   *msgs_in_queue = 0; /* default to none */
2897 
2898   if(GOOD_MULTI_HANDLE(multi) &&
2899      !multi->in_callback &&
2900      Curl_llist_count(&multi->msglist)) {
2901     /* there is one or more messages in the list */
2902     struct Curl_llist_element *e;
2903 
2904     /* extract the head of the list to return */
2905     e = multi->msglist.head;
2906 
2907     msg = e->ptr;
2908 
2909     /* remove the extracted entry */
2910     Curl_llist_remove(&multi->msglist, e, NULL);
2911 
2912     *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2913 
2914     return &msg->extmsg;
2915   }
2916   return NULL;
2917 }
2918 
2919 /*
2920  * singlesocket() checks what sockets we deal with and their "action state"
2921  * and if we have a different state in any of those sockets from last time we
2922  * call the callback accordingly.
2923  */
2924 static CURLMcode singlesocket(struct Curl_multi *multi,
2925                               struct Curl_easy *data)
2926 {
2927   struct easy_pollset cur_poll;
2928   unsigned int i;
2929   struct Curl_sh_entry *entry;
2930   curl_socket_t s;
2931   int rc;
2932 
2933   /* Fill in the 'current' struct with the state as it is now: what sockets to
2934      supervise and for what actions */
2935   multi_getsock(data, &cur_poll);
2936 
2937   /* We have 0 .. N sockets already and we get to know about the 0 .. M
2938      sockets we should have from now on. Detect the differences, remove no
2939      longer supervised ones and add new ones */
2940 
2941   /* walk over the sockets we got right now */
2942   for(i = 0; i < cur_poll.num; i++) {
2943     unsigned char cur_action = cur_poll.actions[i];
2944     unsigned char last_action = 0;
2945     int comboaction;
2946 
2947     s = cur_poll.sockets[i];
2948 
2949     /* get it from the hash */
2950     entry = sh_getentry(&multi->sockhash, s);
2951     if(entry) {
2952       /* check if new for this transfer */
2953       unsigned int j;
2954       for(j = 0; j< data->last_poll.num; j++) {
2955         if(s == data->last_poll.sockets[j]) {
2956           last_action = data->last_poll.actions[j];
2957           break;
2958         }
2959       }
2960     }
2961     else {
2962       /* this is a socket we didn't have before, add it to the hash! */
2963       entry = sh_addentry(&multi->sockhash, s);
2964       if(!entry)
2965         /* fatal */
2966         return CURLM_OUT_OF_MEMORY;
2967     }
2968     if(last_action && (last_action != cur_action)) {
2969       /* Socket was used already, but different action now */
2970       if(last_action & CURL_POLL_IN)
2971         entry->readers--;
2972       if(last_action & CURL_POLL_OUT)
2973         entry->writers--;
2974       if(cur_action & CURL_POLL_IN)
2975         entry->readers++;
2976       if(cur_action & CURL_POLL_OUT)
2977         entry->writers++;
2978     }
2979     else if(!last_action) {
2980       /* a new transfer using this socket */
2981       entry->users++;
2982       if(cur_action & CURL_POLL_IN)
2983         entry->readers++;
2984       if(cur_action & CURL_POLL_OUT)
2985         entry->writers++;
2986 
2987       /* add 'data' to the transfer hash on this socket! */
2988       if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2989                         sizeof(struct Curl_easy *), data)) {
2990         Curl_hash_destroy(&entry->transfers);
2991         return CURLM_OUT_OF_MEMORY;
2992       }
2993     }
2994 
2995     comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
2996                    (entry->readers ? CURL_POLL_IN : 0);
2997 
2998     /* socket existed before and has the same action set as before */
2999     if(last_action && ((int)entry->action == comboaction))
3000       /* same, continue */
3001       continue;
3002 
3003     if(multi->socket_cb) {
3004       set_in_callback(multi, TRUE);
3005       rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
3006                             entry->socketp);
3007 
3008       set_in_callback(multi, FALSE);
3009       if(rc == -1) {
3010         multi->dead = TRUE;
3011         return CURLM_ABORTED_BY_CALLBACK;
3012       }
3013     }
3014 
3015     entry->action = comboaction; /* store the current action state */
3016   }
3017 
3018   /* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
3019    * Need to remove the easy handle from the multi->sockhash->transfers and
3020    * remove multi->sockhash entry when this was the last transfer */
3021   for(i = 0; i< data->last_poll.num; i++) {
3022     unsigned int j;
3023     bool stillused = FALSE;
3024     s = data->last_poll.sockets[i];
3025     for(j = 0; j < cur_poll.num; j++) {
3026       if(s == cur_poll.sockets[j]) {
3027         /* this is still supervised */
3028         stillused = TRUE;
3029         break;
3030       }
3031     }
3032     if(stillused)
3033       continue;
3034 
3035     entry = sh_getentry(&multi->sockhash, s);
3036     /* if this is NULL here, the socket has been closed and notified so
3037        already by Curl_multi_closed() */
3038     if(entry) {
3039       unsigned char oldactions = data->last_poll.actions[i];
3040       /* this socket has been removed. Decrease user count */
3041       entry->users--;
3042       if(oldactions & CURL_POLL_OUT)
3043         entry->writers--;
3044       if(oldactions & CURL_POLL_IN)
3045         entry->readers--;
3046       if(!entry->users) {
3047         if(multi->socket_cb) {
3048           set_in_callback(multi, TRUE);
3049           rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3050                                 multi->socket_userp, entry->socketp);
3051           set_in_callback(multi, FALSE);
3052           if(rc == -1) {
3053             multi->dead = TRUE;
3054             return CURLM_ABORTED_BY_CALLBACK;
3055           }
3056         }
3057         sh_delentry(entry, &multi->sockhash, s);
3058       }
3059       else {
3060         /* still users, but remove this handle as a user of this socket */
3061         if(Curl_hash_delete(&entry->transfers, (char *)&data,
3062                             sizeof(struct Curl_easy *))) {
3063           DEBUGASSERT(NULL);
3064         }
3065       }
3066     }
3067   } /* for loop over num */
3068 
3069   /* Remember for next time */
3070   memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
3071   return CURLM_OK;
3072 }
3073 
3074 CURLcode Curl_updatesocket(struct Curl_easy *data)
3075 {
3076   if(singlesocket(data->multi, data))
3077     return CURLE_ABORTED_BY_CALLBACK;
3078   return CURLE_OK;
3079 }
3080 
3081 
3082 /*
3083  * Curl_multi_closed()
3084  *
3085  * Used by the connect code to tell the multi_socket code that one of the
3086  * sockets we were using is about to be closed.  This function will then
3087  * remove it from the sockethash for this handle to make the multi_socket API
3088  * behave properly, especially for the case when libcurl will create another
3089  * socket again and it gets the same file descriptor number.
3090  */
3091 
3092 void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
3093 {
3094   if(data) {
3095     /* if there's still an easy handle associated with this connection */
3096     struct Curl_multi *multi = data->multi;
3097     if(multi) {
3098       /* this is set if this connection is part of a handle that is added to
3099          a multi handle, and only then this is necessary */
3100       struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3101 
3102       if(entry) {
3103         int rc = 0;
3104         if(multi->socket_cb) {
3105           set_in_callback(multi, TRUE);
3106           rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3107                                 multi->socket_userp, entry->socketp);
3108           set_in_callback(multi, FALSE);
3109         }
3110 
3111         /* now remove it from the socket hash */
3112         sh_delentry(entry, &multi->sockhash, s);
3113         if(rc == -1)
3114           /* This just marks the multi handle as "dead" without returning an
3115              error code primarily because this function is used from many
3116              places where propagating an error back is tricky. */
3117           multi->dead = TRUE;
3118       }
3119     }
3120   }
3121 }
3122 
3123 /*
3124  * add_next_timeout()
3125  *
3126  * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
3127  * when it has just been removed from the splay tree because the timeout has
3128  * expired. This function is then to advance in the list to pick the next
3129  * timeout to use (skip the already expired ones) and add this node back to
3130  * the splay tree again.
3131  *
3132  * The splay tree only has each sessionhandle as a single node and the nearest
3133  * timeout is used to sort it on.
3134  */
3135 static CURLMcode add_next_timeout(struct curltime now,
3136                                   struct Curl_multi *multi,
3137                                   struct Curl_easy *d)
3138 {
3139   struct curltime *tv = &d->state.expiretime;
3140   struct Curl_llist *list = &d->state.timeoutlist;
3141   struct Curl_llist_element *e;
3142   struct time_node *node = NULL;
3143 
3144   /* move over the timeout list for this specific handle and remove all
3145      timeouts that are now passed tense and store the next pending
3146      timeout in *tv */
3147   for(e = list->head; e;) {
3148     struct Curl_llist_element *n = e->next;
3149     timediff_t diff;
3150     node = (struct time_node *)e->ptr;
3151     diff = Curl_timediff_us(node->time, now);
3152     if(diff <= 0)
3153       /* remove outdated entry */
3154       Curl_llist_remove(list, e, NULL);
3155     else
3156       /* the list is sorted so get out on the first mismatch */
3157       break;
3158     e = n;
3159   }
3160   e = list->head;
3161   if(!e) {
3162     /* clear the expire times within the handles that we remove from the
3163        splay tree */
3164     tv->tv_sec = 0;
3165     tv->tv_usec = 0;
3166   }
3167   else {
3168     /* copy the first entry to 'tv' */
3169     memcpy(tv, &node->time, sizeof(*tv));
3170 
3171     /* Insert this node again into the splay.  Keep the timer in the list in
3172        case we need to recompute future timers. */
3173     multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3174                                        &d->state.timenode);
3175   }
3176   return CURLM_OK;
3177 }
3178 
3179 static CURLMcode multi_socket(struct Curl_multi *multi,
3180                               bool checkall,
3181                               curl_socket_t s,
3182                               int ev_bitmask,
3183                               int *running_handles)
3184 {
3185   CURLMcode result = CURLM_OK;
3186   struct Curl_easy *data = NULL;
3187   struct Curl_tree *t;
3188   struct curltime now = Curl_now();
3189   bool first = FALSE;
3190   bool nosig = FALSE;
3191   SIGPIPE_VARIABLE(pipe_st);
3192 
3193   if(checkall) {
3194     /* *perform() deals with running_handles on its own */
3195     result = curl_multi_perform(multi, running_handles);
3196 
3197     /* walk through each easy handle and do the socket state change magic
3198        and callbacks */
3199     if(result != CURLM_BAD_HANDLE) {
3200       data = multi->easyp;
3201       while(data && !result) {
3202         result = singlesocket(multi, data);
3203         data = data->next;
3204       }
3205     }
3206 
3207     /* or should we fall-through and do the timer-based stuff? */
3208     return result;
3209   }
3210   if(s != CURL_SOCKET_TIMEOUT) {
3211     struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3212 
3213     if(!entry)
3214       /* Unmatched socket, we can't act on it but we ignore this fact.  In
3215          real-world tests it has been proved that libevent can in fact give
3216          the application actions even though the socket was just previously
3217          asked to get removed, so thus we better survive stray socket actions
3218          and just move on. */
3219       ;
3220     else {
3221       struct Curl_hash_iterator iter;
3222       struct Curl_hash_element *he;
3223 
3224       /* the socket can be shared by many transfers, iterate */
3225       Curl_hash_start_iterate(&entry->transfers, &iter);
3226       for(he = Curl_hash_next_element(&iter); he;
3227           he = Curl_hash_next_element(&iter)) {
3228         data = (struct Curl_easy *)he->ptr;
3229         DEBUGASSERT(data);
3230         DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3231 
3232         if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3233           /* set socket event bitmask if they're not locked */
3234           data->state.select_bits |= (unsigned char)ev_bitmask;
3235 
3236         Curl_expire(data, 0, EXPIRE_RUN_NOW);
3237       }
3238 
3239       /* Now we fall-through and do the timer-based stuff, since we don't want
3240          to force the user to have to deal with timeouts as long as at least
3241          one connection in fact has traffic. */
3242 
3243       data = NULL; /* set data to NULL again to avoid calling
3244                       multi_runsingle() in case there's no need to */
3245       now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3246                            may have taken some time */
3247     }
3248   }
3249   else {
3250     /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3251        Curl_update_timer() to trigger a callback to the app again even if the
3252        same timeout is still the one to run after this call. That handles the
3253        case when the application asks libcurl to run the timeout
3254        prematurely. */
3255     memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3256   }
3257 
3258   /*
3259    * The loop following here will go on as long as there are expire-times left
3260    * to process in the splay and 'data' will be re-assigned for every expired
3261    * handle we deal with.
3262    */
3263   do {
3264     /* the first loop lap 'data' can be NULL */
3265     if(data) {
3266       if(!first) {
3267         first = TRUE;
3268         nosig = data->set.no_signal; /* initial state */
3269         sigpipe_ignore(data, &pipe_st);
3270       }
3271       else if(data->set.no_signal != nosig) {
3272         sigpipe_restore(&pipe_st);
3273         sigpipe_ignore(data, &pipe_st);
3274         nosig = data->set.no_signal; /* remember new state */
3275       }
3276       result = multi_runsingle(multi, &now, data);
3277 
3278       if(CURLM_OK >= result) {
3279         /* get the socket(s) and check if the state has been changed since
3280            last */
3281         result = singlesocket(multi, data);
3282         if(result)
3283           break;
3284       }
3285     }
3286 
3287     /* Check if there's one (more) expired timer to deal with! This function
3288        extracts a matching node if there is one */
3289 
3290     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3291     if(t) {
3292       data = t->payload; /* assign this for next loop */
3293       (void)add_next_timeout(now, multi, t->payload);
3294     }
3295 
3296   } while(t);
3297   if(first)
3298     sigpipe_restore(&pipe_st);
3299 
3300   *running_handles = multi->num_alive;
3301   return result;
3302 }
3303 
3304 #undef curl_multi_setopt
3305 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3306                             CURLMoption option, ...)
3307 {
3308   CURLMcode res = CURLM_OK;
3309   va_list param;
3310   unsigned long uarg;
3311 
3312   if(!GOOD_MULTI_HANDLE(multi))
3313     return CURLM_BAD_HANDLE;
3314 
3315   if(multi->in_callback)
3316     return CURLM_RECURSIVE_API_CALL;
3317 
3318   va_start(param, option);
3319 
3320   switch(option) {
3321   case CURLMOPT_SOCKETFUNCTION:
3322     multi->socket_cb = va_arg(param, curl_socket_callback);
3323     break;
3324   case CURLMOPT_SOCKETDATA:
3325     multi->socket_userp = va_arg(param, void *);
3326     break;
3327   case CURLMOPT_PUSHFUNCTION:
3328     multi->push_cb = va_arg(param, curl_push_callback);
3329     break;
3330   case CURLMOPT_PUSHDATA:
3331     multi->push_userp = va_arg(param, void *);
3332     break;
3333   case CURLMOPT_PIPELINING:
3334     multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
3335     break;
3336   case CURLMOPT_TIMERFUNCTION:
3337     multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3338     break;
3339   case CURLMOPT_TIMERDATA:
3340     multi->timer_userp = va_arg(param, void *);
3341     break;
3342   case CURLMOPT_MAXCONNECTS:
3343     uarg = va_arg(param, unsigned long);
3344     if(uarg <= UINT_MAX)
3345       multi->maxconnects = (unsigned int)uarg;
3346     break;
3347   case CURLMOPT_MAX_HOST_CONNECTIONS:
3348     multi->max_host_connections = va_arg(param, long);
3349     break;
3350   case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3351     multi->max_total_connections = va_arg(param, long);
3352     break;
3353     /* options formerly used for pipelining */
3354   case CURLMOPT_MAX_PIPELINE_LENGTH:
3355     break;
3356   case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3357     break;
3358   case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3359     break;
3360   case CURLMOPT_PIPELINING_SITE_BL:
3361     break;
3362   case CURLMOPT_PIPELINING_SERVER_BL:
3363     break;
3364   case CURLMOPT_MAX_CONCURRENT_STREAMS:
3365     {
3366       long streams = va_arg(param, long);
3367       if((streams < 1) || (streams > INT_MAX))
3368         streams = 100;
3369       multi->max_concurrent_streams = (unsigned int)streams;
3370     }
3371     break;
3372   default:
3373     res = CURLM_UNKNOWN_OPTION;
3374     break;
3375   }
3376   va_end(param);
3377   return res;
3378 }
3379 
3380 /* we define curl_multi_socket() in the public multi.h header */
3381 #undef curl_multi_socket
3382 
3383 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3384                             int *running_handles)
3385 {
3386   CURLMcode result;
3387   if(multi->in_callback)
3388     return CURLM_RECURSIVE_API_CALL;
3389   result = multi_socket(multi, FALSE, s, 0, running_handles);
3390   if(CURLM_OK >= result)
3391     result = Curl_update_timer(multi);
3392   return result;
3393 }
3394 
3395 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3396                                    int ev_bitmask, int *running_handles)
3397 {
3398   CURLMcode result;
3399   if(multi->in_callback)
3400     return CURLM_RECURSIVE_API_CALL;
3401   result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3402   if(CURLM_OK >= result)
3403     result = Curl_update_timer(multi);
3404   return result;
3405 }
3406 
3407 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3408 {
3409   CURLMcode result;
3410   if(multi->in_callback)
3411     return CURLM_RECURSIVE_API_CALL;
3412   result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3413   if(CURLM_OK >= result)
3414     result = Curl_update_timer(multi);
3415   return result;
3416 }
3417 
3418 static CURLMcode multi_timeout(struct Curl_multi *multi,
3419                                long *timeout_ms)
3420 {
3421   static const struct curltime tv_zero = {0, 0};
3422 
3423   if(multi->dead) {
3424     *timeout_ms = 0;
3425     return CURLM_OK;
3426   }
3427 
3428   if(multi->timetree) {
3429     /* we have a tree of expire times */
3430     struct curltime now = Curl_now();
3431 
3432     /* splay the lowest to the bottom */
3433     multi->timetree = Curl_splay(tv_zero, multi->timetree);
3434 
3435     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3436       /* some time left before expiration */
3437       timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
3438       /* this should be safe even on 32 bit archs, as we don't use that
3439          overly long timeouts */
3440       *timeout_ms = (long)diff;
3441     }
3442     else
3443       /* 0 means immediately */
3444       *timeout_ms = 0;
3445   }
3446   else
3447     *timeout_ms = -1;
3448 
3449   return CURLM_OK;
3450 }
3451 
3452 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3453                              long *timeout_ms)
3454 {
3455   /* First, make some basic checks that the CURLM handle is a good handle */
3456   if(!GOOD_MULTI_HANDLE(multi))
3457     return CURLM_BAD_HANDLE;
3458 
3459   if(multi->in_callback)
3460     return CURLM_RECURSIVE_API_CALL;
3461 
3462   return multi_timeout(multi, timeout_ms);
3463 }
3464 
3465 /*
3466  * Tell the application it should update its timers, if it subscribes to the
3467  * update timer callback.
3468  */
3469 CURLMcode Curl_update_timer(struct Curl_multi *multi)
3470 {
3471   long timeout_ms;
3472   int rc;
3473 
3474   if(!multi->timer_cb || multi->dead)
3475     return CURLM_OK;
3476   if(multi_timeout(multi, &timeout_ms)) {
3477     return CURLM_OK;
3478   }
3479   if(timeout_ms < 0) {
3480     static const struct curltime none = {0, 0};
3481     if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3482       multi->timer_lastcall = none;
3483       /* there's no timeout now but there was one previously, tell the app to
3484          disable it */
3485       set_in_callback(multi, TRUE);
3486       rc = multi->timer_cb(multi, -1, multi->timer_userp);
3487       set_in_callback(multi, FALSE);
3488       if(rc == -1) {
3489         multi->dead = TRUE;
3490         return CURLM_ABORTED_BY_CALLBACK;
3491       }
3492       return CURLM_OK;
3493     }
3494     return CURLM_OK;
3495   }
3496 
3497   /* When multi_timeout() is done, multi->timetree points to the node with the
3498    * timeout we got the (relative) time-out time for. We can thus easily check
3499    * if this is the same (fixed) time as we got in a previous call and then
3500    * avoid calling the callback again. */
3501   if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3502     return CURLM_OK;
3503 
3504   multi->timer_lastcall = multi->timetree->key;
3505 
3506   set_in_callback(multi, TRUE);
3507   rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3508   set_in_callback(multi, FALSE);
3509   if(rc == -1) {
3510     multi->dead = TRUE;
3511     return CURLM_ABORTED_BY_CALLBACK;
3512   }
3513   return CURLM_OK;
3514 }
3515 
3516 /*
3517  * multi_deltimeout()
3518  *
3519  * Remove a given timestamp from the list of timeouts.
3520  */
3521 static void
3522 multi_deltimeout(struct Curl_easy *data, expire_id eid)
3523 {
3524   struct Curl_llist_element *e;
3525   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3526   /* find and remove the specific node from the list */
3527   for(e = timeoutlist->head; e; e = e->next) {
3528     struct time_node *n = (struct time_node *)e->ptr;
3529     if(n->eid == eid) {
3530       Curl_llist_remove(timeoutlist, e, NULL);
3531       return;
3532     }
3533   }
3534 }
3535 
3536 /*
3537  * multi_addtimeout()
3538  *
3539  * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3540  * of list is always the timeout nearest in time.
3541  *
3542  */
3543 static CURLMcode
3544 multi_addtimeout(struct Curl_easy *data,
3545                  struct curltime *stamp,
3546                  expire_id eid)
3547 {
3548   struct Curl_llist_element *e;
3549   struct time_node *node;
3550   struct Curl_llist_element *prev = NULL;
3551   size_t n;
3552   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3553 
3554   node = &data->state.expires[eid];
3555 
3556   /* copy the timestamp and id */
3557   memcpy(&node->time, stamp, sizeof(*stamp));
3558   node->eid = eid; /* also marks it as in use */
3559 
3560   n = Curl_llist_count(timeoutlist);
3561   if(n) {
3562     /* find the correct spot in the list */
3563     for(e = timeoutlist->head; e; e = e->next) {
3564       struct time_node *check = (struct time_node *)e->ptr;
3565       timediff_t diff = Curl_timediff(check->time, node->time);
3566       if(diff > 0)
3567         break;
3568       prev = e;
3569     }
3570 
3571   }
3572   /* else
3573      this is the first timeout on the list */
3574 
3575   Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3576   return CURLM_OK;
3577 }
3578 
3579 /*
3580  * Curl_expire()
3581  *
3582  * given a number of milliseconds from now to use to set the 'act before
3583  * this'-time for the transfer, to be extracted by curl_multi_timeout()
3584  *
3585  * The timeout will be added to a queue of timeouts if it defines a moment in
3586  * time that is later than the current head of queue.
3587  *
3588  * Expire replaces a former timeout using the same id if already set.
3589  */
3590 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3591 {
3592   struct Curl_multi *multi = data->multi;
3593   struct curltime *nowp = &data->state.expiretime;
3594   struct curltime set;
3595 
3596   /* this is only interesting while there is still an associated multi struct
3597      remaining! */
3598   if(!multi)
3599     return;
3600 
3601   DEBUGASSERT(id < EXPIRE_LAST);
3602 
3603   set = Curl_now();
3604   set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3605   set.tv_usec += (unsigned int)(milli%1000)*1000;
3606 
3607   if(set.tv_usec >= 1000000) {
3608     set.tv_sec++;
3609     set.tv_usec -= 1000000;
3610   }
3611 
3612   /* Remove any timer with the same id just in case. */
3613   multi_deltimeout(data, id);
3614 
3615   /* Add it to the timer list.  It must stay in the list until it has expired
3616      in case we need to recompute the minimum timer later. */
3617   multi_addtimeout(data, &set, id);
3618 
3619   if(nowp->tv_sec || nowp->tv_usec) {
3620     /* This means that the struct is added as a node in the splay tree.
3621        Compare if the new time is earlier, and only remove-old/add-new if it
3622        is. */
3623     timediff_t diff = Curl_timediff(set, *nowp);
3624     int rc;
3625 
3626     if(diff > 0) {
3627       /* The current splay tree entry is sooner than this new expiry time.
3628          We don't need to update our splay tree entry. */
3629       return;
3630     }
3631 
3632     /* Since this is an updated time, we must remove the previous entry from
3633        the splay tree first and then re-add the new value */
3634     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3635                           &multi->timetree);
3636     if(rc)
3637       infof(data, "Internal error removing splay node = %d", rc);
3638   }
3639 
3640   /* Indicate that we are in the splay tree and insert the new timer expiry
3641      value since it is our local minimum. */
3642   *nowp = set;
3643   data->state.timenode.payload = data;
3644   multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3645                                      &data->state.timenode);
3646 }
3647 
3648 /*
3649  * Curl_expire_done()
3650  *
3651  * Removes the expire timer. Marks it as done.
3652  *
3653  */
3654 void Curl_expire_done(struct Curl_easy *data, expire_id id)
3655 {
3656   /* remove the timer, if there */
3657   multi_deltimeout(data, id);
3658 }
3659 
3660 /*
3661  * Curl_expire_clear()
3662  *
3663  * Clear ALL timeout values for this handle.
3664  */
3665 void Curl_expire_clear(struct Curl_easy *data)
3666 {
3667   struct Curl_multi *multi = data->multi;
3668   struct curltime *nowp = &data->state.expiretime;
3669 
3670   /* this is only interesting while there is still an associated multi struct
3671      remaining! */
3672   if(!multi)
3673     return;
3674 
3675   if(nowp->tv_sec || nowp->tv_usec) {
3676     /* Since this is an cleared time, we must remove the previous entry from
3677        the splay tree */
3678     struct Curl_llist *list = &data->state.timeoutlist;
3679     int rc;
3680 
3681     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3682                           &multi->timetree);
3683     if(rc)
3684       infof(data, "Internal error clearing splay node = %d", rc);
3685 
3686     /* flush the timeout list too */
3687     while(list->size > 0) {
3688       Curl_llist_remove(list, list->tail, NULL);
3689     }
3690 
3691 #ifdef DEBUGBUILD
3692     infof(data, "Expire cleared");
3693 #endif
3694     nowp->tv_sec = 0;
3695     nowp->tv_usec = 0;
3696   }
3697 }
3698 
3699 
3700 
3701 
3702 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3703                             void *hashp)
3704 {
3705   struct Curl_sh_entry *there = NULL;
3706 
3707   there = sh_getentry(&multi->sockhash, s);
3708 
3709   if(!there)
3710     return CURLM_BAD_SOCKET;
3711 
3712   there->socketp = hashp;
3713 
3714   return CURLM_OK;
3715 }
3716 
3717 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3718 {
3719   return multi ? multi->max_host_connections : 0;
3720 }
3721 
3722 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3723 {
3724   return multi ? multi->max_total_connections : 0;
3725 }
3726 
3727 /*
3728  * When information about a connection has appeared, call this!
3729  */
3730 
3731 void Curl_multiuse_state(struct Curl_easy *data,
3732                          int bundlestate) /* use BUNDLE_* defines */
3733 {
3734   struct connectdata *conn;
3735   DEBUGASSERT(data);
3736   DEBUGASSERT(data->multi);
3737   conn = data->conn;
3738   DEBUGASSERT(conn);
3739   DEBUGASSERT(conn->bundle);
3740 
3741   conn->bundle->multiuse = bundlestate;
3742   process_pending_handles(data->multi);
3743 }
3744 
3745 static void move_pending_to_connect(struct Curl_multi *multi,
3746                                     struct Curl_easy *data)
3747 {
3748   DEBUGASSERT(data->mstate == MSTATE_PENDING);
3749 
3750   /* put it back into the main list */
3751   link_easy(multi, data);
3752 
3753   multistate(data, MSTATE_CONNECT);
3754 
3755   /* Remove this node from the pending list */
3756   Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
3757 
3758   /* Make sure that the handle will be processed soonish. */
3759   Curl_expire(data, 0, EXPIRE_RUN_NOW);
3760 }
3761 
3762 /* process_pending_handles() moves a handle from PENDING back into the main
3763    list and change state to CONNECT.
3764 
3765    We do not move all transfers because that can be a significant amount.
3766    Since this is tried every now and then doing too many too often becomes a
3767    performance problem.
3768 
3769    When there is a change for connection limits like max host connections etc,
3770    this likely only allows one new transfer. When there is a pipewait change,
3771    it can potentially allow hundreds of new transfers.
3772 
3773    We could consider an improvement where we store the queue reason and allow
3774    more pipewait rechecks than others.
3775 */
3776 static void process_pending_handles(struct Curl_multi *multi)
3777 {
3778   struct Curl_llist_element *e = multi->pending.head;
3779   if(e) {
3780     struct Curl_easy *data = e->ptr;
3781     move_pending_to_connect(multi, data);
3782   }
3783 }
3784 
3785 void Curl_set_in_callback(struct Curl_easy *data, bool value)
3786 {
3787   if(data && data->multi)
3788     data->multi->in_callback = value;
3789 }
3790 
3791 bool Curl_is_in_callback(struct Curl_easy *data)
3792 {
3793   return (data && data->multi && data->multi->in_callback);
3794 }
3795 
3796 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3797 {
3798   DEBUGASSERT(multi);
3799   return multi->max_concurrent_streams;
3800 }
3801 
3802 struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
3803 {
3804   struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
3805                                 (multi->num_easy + 1));
3806   if(a) {
3807     unsigned int i = 0;
3808     struct Curl_easy *e = multi->easyp;
3809     while(e) {
3810       DEBUGASSERT(i < multi->num_easy);
3811       if(!e->state.internal)
3812         a[i++] = e;
3813       e = e->next;
3814     }
3815     a[i] = NULL; /* last entry is a NULL */
3816   }
3817   return a;
3818 }
3819 
3820 CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data,
3821                                     char **pbuf, size_t *pbuflen)
3822 {
3823   DEBUGASSERT(data);
3824   DEBUGASSERT(data->multi);
3825   *pbuf = NULL;
3826   *pbuflen = 0;
3827   if(!data->multi) {
3828     failf(data, "transfer has no multi handle");
3829     return CURLE_FAILED_INIT;
3830   }
3831   if(!data->set.buffer_size) {
3832     failf(data, "transfer buffer size is 0");
3833     return CURLE_FAILED_INIT;
3834   }
3835   if(data->multi->xfer_buf_borrowed) {
3836     failf(data, "attempt to borrow xfer_buf when already borrowed");
3837     return CURLE_AGAIN;
3838   }
3839 
3840   if(data->multi->xfer_buf &&
3841      data->set.buffer_size > data->multi->xfer_buf_len) {
3842     /* not large enough, get a new one */
3843     free(data->multi->xfer_buf);
3844     data->multi->xfer_buf = NULL;
3845     data->multi->xfer_buf_len = 0;
3846   }
3847 
3848   if(!data->multi->xfer_buf) {
3849     data->multi->xfer_buf = malloc((size_t)data->set.buffer_size);
3850     if(!data->multi->xfer_buf) {
3851       failf(data, "could not allocate xfer_buf of %zu bytes",
3852             (size_t)data->set.buffer_size);
3853       return CURLE_OUT_OF_MEMORY;
3854     }
3855     data->multi->xfer_buf_len = data->set.buffer_size;
3856   }
3857 
3858   data->multi->xfer_buf_borrowed = TRUE;
3859   *pbuf = data->multi->xfer_buf;
3860   *pbuflen = data->multi->xfer_buf_len;
3861   return CURLE_OK;
3862 }
3863 
3864 void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf)
3865 {
3866   (void)buf;
3867   DEBUGASSERT(data);
3868   DEBUGASSERT(data->multi);
3869   DEBUGASSERT(!buf || data->multi->xfer_buf == buf);
3870   data->multi->xfer_buf_borrowed = FALSE;
3871 }
3872 
3873 CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data,
3874                                       char **pbuf, size_t *pbuflen)
3875 {
3876   DEBUGASSERT(data);
3877   DEBUGASSERT(data->multi);
3878   *pbuf = NULL;
3879   *pbuflen = 0;
3880   if(!data->multi) {
3881     failf(data, "transfer has no multi handle");
3882     return CURLE_FAILED_INIT;
3883   }
3884   if(!data->set.upload_buffer_size) {
3885     failf(data, "transfer upload buffer size is 0");
3886     return CURLE_FAILED_INIT;
3887   }
3888   if(data->multi->xfer_ulbuf_borrowed) {
3889     failf(data, "attempt to borrow xfer_ulbuf when already borrowed");
3890     return CURLE_AGAIN;
3891   }
3892 
3893   if(data->multi->xfer_ulbuf &&
3894      data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) {
3895     /* not large enough, get a new one */
3896     free(data->multi->xfer_ulbuf);
3897     data->multi->xfer_ulbuf = NULL;
3898     data->multi->xfer_ulbuf_len = 0;
3899   }
3900 
3901   if(!data->multi->xfer_ulbuf) {
3902     data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size);
3903     if(!data->multi->xfer_ulbuf) {
3904       failf(data, "could not allocate xfer_ulbuf of %zu bytes",
3905             (size_t)data->set.upload_buffer_size);
3906       return CURLE_OUT_OF_MEMORY;
3907     }
3908     data->multi->xfer_ulbuf_len = data->set.upload_buffer_size;
3909   }
3910 
3911   data->multi->xfer_ulbuf_borrowed = TRUE;
3912   *pbuf = data->multi->xfer_ulbuf;
3913   *pbuflen = data->multi->xfer_ulbuf_len;
3914   return CURLE_OK;
3915 }
3916 
3917 void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf)
3918 {
3919   (void)buf;
3920   DEBUGASSERT(data);
3921   DEBUGASSERT(data->multi);
3922   DEBUGASSERT(!buf || data->multi->xfer_ulbuf == buf);
3923   data->multi->xfer_ulbuf_borrowed = FALSE;
3924 }
3925 
3926 static void multi_xfer_bufs_free(struct Curl_multi *multi)
3927 {
3928   DEBUGASSERT(multi);
3929   Curl_safefree(multi->xfer_buf);
3930   multi->xfer_buf_len = 0;
3931   multi->xfer_buf_borrowed = FALSE;
3932   Curl_safefree(multi->xfer_ulbuf);
3933   multi->xfer_ulbuf_len = 0;
3934   multi->xfer_ulbuf_borrowed = FALSE;
3935 }
3936