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