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