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