• 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         if(!FDSET_SOCK(sockbunch[i]))
1057           /* pretend it doesn't exist */
1058           continue;
1059         FD_SET(sockbunch[i], read_fd_set);
1060         s = sockbunch[i];
1061       }
1062       if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
1063         if(!FDSET_SOCK(sockbunch[i]))
1064           /* pretend it doesn't exist */
1065           continue;
1066         FD_SET(sockbunch[i], write_fd_set);
1067         s = sockbunch[i];
1068       }
1069       if(s == CURL_SOCKET_BAD)
1070         /* this socket is unused, break out of loop */
1071         break;
1072       if((int)s > this_max_fd)
1073         this_max_fd = (int)s;
1074     }
1075 
1076     data = data->next; /* check next handle */
1077   }
1078 
1079   *max_fd = this_max_fd;
1080 
1081   return CURLM_OK;
1082 }
1083 
1084 #define NUM_POLLS_ON_STACK 10
1085 
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)1086 static CURLMcode multi_wait(struct Curl_multi *multi,
1087                             struct curl_waitfd extra_fds[],
1088                             unsigned int extra_nfds,
1089                             int timeout_ms,
1090                             int *ret,
1091                             bool extrawait, /* when no socket, wait */
1092                             bool use_wakeup)
1093 {
1094   struct Curl_easy *data;
1095   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1096   int bitmap;
1097   unsigned int i;
1098   unsigned int nfds = 0;
1099   unsigned int curlfds;
1100   long timeout_internal;
1101   int retcode = 0;
1102   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1103   struct pollfd *ufds = &a_few_on_stack[0];
1104   bool ufds_malloc = FALSE;
1105 #ifdef USE_WINSOCK
1106   WSANETWORKEVENTS wsa_events;
1107   DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1108 #endif
1109 #ifndef ENABLE_WAKEUP
1110   (void)use_wakeup;
1111 #endif
1112 
1113   if(!GOOD_MULTI_HANDLE(multi))
1114     return CURLM_BAD_HANDLE;
1115 
1116   if(multi->in_callback)
1117     return CURLM_RECURSIVE_API_CALL;
1118 
1119   if(timeout_ms < 0)
1120     return CURLM_BAD_FUNCTION_ARGUMENT;
1121 
1122   /* Count up how many fds we have from the multi handle */
1123   data = multi->easyp;
1124   while(data) {
1125     bitmap = multi_getsock(data, sockbunch);
1126 
1127     for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1128       curl_socket_t s = CURL_SOCKET_BAD;
1129 
1130       if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1131         ++nfds;
1132         s = sockbunch[i];
1133       }
1134       if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1135         ++nfds;
1136         s = sockbunch[i];
1137       }
1138       if(s == CURL_SOCKET_BAD) {
1139         break;
1140       }
1141     }
1142 
1143     data = data->next; /* check next handle */
1144   }
1145 
1146   /* If the internally desired timeout is actually shorter than requested from
1147      the outside, then use the shorter time! But only if the internal timer
1148      is actually larger than -1! */
1149   (void)multi_timeout(multi, &timeout_internal);
1150   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1151     timeout_ms = (int)timeout_internal;
1152 
1153   curlfds = nfds; /* number of internal file descriptors */
1154   nfds += extra_nfds; /* add the externally provided ones */
1155 
1156 #ifdef ENABLE_WAKEUP
1157 #ifdef USE_WINSOCK
1158   if(use_wakeup) {
1159 #else
1160   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1161 #endif
1162     ++nfds;
1163   }
1164 #endif
1165 
1166   if(nfds > NUM_POLLS_ON_STACK) {
1167     /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1168        big, so at 2^29 sockets this value might wrap. When a process gets
1169        the capability to actually handle over 500 million sockets this
1170        calculation needs a integer overflow check. */
1171     ufds = malloc(nfds * sizeof(struct pollfd));
1172     if(!ufds)
1173       return CURLM_OUT_OF_MEMORY;
1174     ufds_malloc = TRUE;
1175   }
1176   nfds = 0;
1177 
1178   /* only do the second loop if we found descriptors in the first stage run
1179      above */
1180 
1181   if(curlfds) {
1182     /* Add the curl handles to our pollfds first */
1183     data = multi->easyp;
1184     while(data) {
1185       bitmap = multi_getsock(data, sockbunch);
1186 
1187       for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1188         curl_socket_t s = CURL_SOCKET_BAD;
1189 #ifdef USE_WINSOCK
1190         long mask = 0;
1191 #endif
1192         if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1193           s = sockbunch[i];
1194 #ifdef USE_WINSOCK
1195           mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1196 #endif
1197           ufds[nfds].fd = s;
1198           ufds[nfds].events = POLLIN;
1199           ++nfds;
1200         }
1201         if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1202           s = sockbunch[i];
1203 #ifdef USE_WINSOCK
1204           mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1205           send(s, NULL, 0, 0); /* reset FD_WRITE */
1206 #endif
1207           ufds[nfds].fd = s;
1208           ufds[nfds].events = POLLOUT;
1209           ++nfds;
1210         }
1211         /* s is only set if either being readable or writable is checked */
1212         if(s == CURL_SOCKET_BAD) {
1213           /* break on entry not checked for being readable or writable */
1214           break;
1215         }
1216 #ifdef USE_WINSOCK
1217         if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
1218           if(ufds_malloc)
1219             free(ufds);
1220           return CURLM_INTERNAL_ERROR;
1221         }
1222 #endif
1223       }
1224 
1225       data = data->next; /* check next handle */
1226     }
1227   }
1228 
1229   /* Add external file descriptions from poll-like struct curl_waitfd */
1230   for(i = 0; i < extra_nfds; i++) {
1231 #ifdef USE_WINSOCK
1232     long mask = 0;
1233     if(extra_fds[i].events & CURL_WAIT_POLLIN)
1234       mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1235     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1236       mask |= FD_OOB;
1237     if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1238       mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1239       send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
1240     }
1241     if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1242       if(ufds_malloc)
1243         free(ufds);
1244       return CURLM_INTERNAL_ERROR;
1245     }
1246 #endif
1247     ufds[nfds].fd = extra_fds[i].fd;
1248     ufds[nfds].events = 0;
1249     if(extra_fds[i].events & CURL_WAIT_POLLIN)
1250       ufds[nfds].events |= POLLIN;
1251     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1252       ufds[nfds].events |= POLLPRI;
1253     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1254       ufds[nfds].events |= POLLOUT;
1255     ++nfds;
1256   }
1257 
1258 #ifdef ENABLE_WAKEUP
1259 #ifndef USE_WINSOCK
1260   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1261     ufds[nfds].fd = multi->wakeup_pair[0];
1262     ufds[nfds].events = POLLIN;
1263     ++nfds;
1264   }
1265 #endif
1266 #endif
1267 
1268 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1269   if(nfds || use_wakeup) {
1270 #else
1271   if(nfds) {
1272 #endif
1273     int pollrc;
1274 #ifdef USE_WINSOCK
1275     if(nfds)
1276       pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1277     else
1278       pollrc = 0;
1279     if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
1280       WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1281 #else
1282     pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1283 #endif
1284 
1285     if(pollrc > 0) {
1286       retcode = pollrc;
1287 #ifdef USE_WINSOCK
1288     }
1289     /* With WinSock, we have to run the following section unconditionally
1290        to call WSAEventSelect(fd, event, 0) on all the sockets */
1291     {
1292 #endif
1293       /* copy revents results from the poll to the curl_multi_wait poll
1294          struct, the bit values of the actual underlying poll() implementation
1295          may not be the same as the ones in the public libcurl API! */
1296       for(i = 0; i < extra_nfds; i++) {
1297         unsigned r = ufds[curlfds + i].revents;
1298         unsigned short mask = 0;
1299 #ifdef USE_WINSOCK
1300         wsa_events.lNetworkEvents = 0;
1301         if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
1302           if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1303             mask |= CURL_WAIT_POLLIN;
1304           if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1305             mask |= CURL_WAIT_POLLOUT;
1306           if(wsa_events.lNetworkEvents & FD_OOB)
1307             mask |= CURL_WAIT_POLLPRI;
1308           if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1309             retcode++;
1310         }
1311         WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
1312         if(pollrc <= 0)
1313           continue;
1314 #endif
1315         if(r & POLLIN)
1316           mask |= CURL_WAIT_POLLIN;
1317         if(r & POLLOUT)
1318           mask |= CURL_WAIT_POLLOUT;
1319         if(r & POLLPRI)
1320           mask |= CURL_WAIT_POLLPRI;
1321         extra_fds[i].revents = mask;
1322       }
1323 
1324 #ifdef USE_WINSOCK
1325       /* Count up all our own sockets that had activity,
1326          and remove them from the event. */
1327       if(curlfds) {
1328         data = multi->easyp;
1329         while(data) {
1330           bitmap = multi_getsock(data, sockbunch);
1331 
1332           for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1333             if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
1334               wsa_events.lNetworkEvents = 0;
1335               if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
1336                 if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1337                   retcode++;
1338               }
1339               WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1340             }
1341             else {
1342               /* break on entry not checked for being readable or writable */
1343               break;
1344             }
1345           }
1346 
1347           data = data->next;
1348         }
1349       }
1350 
1351       WSAResetEvent(multi->wsa_event);
1352 #else
1353 #ifdef ENABLE_WAKEUP
1354       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1355         if(ufds[curlfds + extra_nfds].revents & POLLIN) {
1356           char buf[64];
1357           ssize_t nread;
1358           while(1) {
1359             /* the reading socket is non-blocking, try to read
1360                data from it until it receives an error (except EINTR).
1361                In normal cases it will get EAGAIN or EWOULDBLOCK
1362                when there is no more data, breaking the loop. */
1363             nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
1364             if(nread <= 0) {
1365               if(nread < 0 && EINTR == SOCKERRNO)
1366                 continue;
1367               break;
1368             }
1369           }
1370           /* do not count the wakeup socket into the returned value */
1371           retcode--;
1372         }
1373       }
1374 #endif
1375 #endif
1376     }
1377   }
1378 
1379   if(ufds_malloc)
1380     free(ufds);
1381   if(ret)
1382     *ret = retcode;
1383 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1384   if(extrawait && !nfds && !use_wakeup) {
1385 #else
1386   if(extrawait && !nfds) {
1387 #endif
1388     long sleep_ms = 0;
1389 
1390     /* Avoid busy-looping when there's nothing particular to wait for */
1391     if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1392       if(sleep_ms > timeout_ms)
1393         sleep_ms = timeout_ms;
1394       /* when there are no easy handles in the multi, this holds a -1
1395          timeout */
1396       else if(sleep_ms < 0)
1397         sleep_ms = timeout_ms;
1398       Curl_wait_ms(sleep_ms);
1399     }
1400   }
1401 
1402   return CURLM_OK;
1403 }
1404 
1405 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1406                           struct curl_waitfd extra_fds[],
1407                           unsigned int extra_nfds,
1408                           int timeout_ms,
1409                           int *ret)
1410 {
1411   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1412                     FALSE);
1413 }
1414 
1415 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1416                           struct curl_waitfd extra_fds[],
1417                           unsigned int extra_nfds,
1418                           int timeout_ms,
1419                           int *ret)
1420 {
1421   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1422                     TRUE);
1423 }
1424 
1425 CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1426 {
1427   /* this function is usually called from another thread,
1428      it has to be careful only to access parts of the
1429      Curl_multi struct that are constant */
1430 
1431   /* GOOD_MULTI_HANDLE can be safely called */
1432   if(!GOOD_MULTI_HANDLE(multi))
1433     return CURLM_BAD_HANDLE;
1434 
1435 #ifdef ENABLE_WAKEUP
1436 #ifdef USE_WINSOCK
1437   if(WSASetEvent(multi->wsa_event))
1438     return CURLM_OK;
1439 #else
1440   /* the wakeup_pair variable is only written during init and cleanup,
1441      making it safe to access from another thread after the init part
1442      and before cleanup */
1443   if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1444     char buf[1];
1445     buf[0] = 1;
1446     while(1) {
1447       /* swrite() is not thread-safe in general, because concurrent calls
1448          can have their messages interleaved, but in this case the content
1449          of the messages does not matter, which makes it ok to call.
1450 
1451          The write socket is set to non-blocking, this way this function
1452          cannot block, making it safe to call even from the same thread
1453          that will call curl_multi_wait(). If swrite() returns that it
1454          would block, it's considered successful because it means that
1455          previous calls to this function will wake up the poll(). */
1456       if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1457         int err = SOCKERRNO;
1458         int return_success;
1459 #ifdef USE_WINSOCK
1460         return_success = WSAEWOULDBLOCK == err;
1461 #else
1462         if(EINTR == err)
1463           continue;
1464         return_success = EWOULDBLOCK == err || EAGAIN == err;
1465 #endif
1466         if(!return_success)
1467           return CURLM_WAKEUP_FAILURE;
1468       }
1469       return CURLM_OK;
1470     }
1471   }
1472 #endif
1473 #endif
1474   return CURLM_WAKEUP_FAILURE;
1475 }
1476 
1477 /*
1478  * multi_ischanged() is called
1479  *
1480  * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1481  * => CONNECT action.
1482  *
1483  * Set 'clear' to TRUE to have it also clear the state variable.
1484  */
1485 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1486 {
1487   bool retval = multi->recheckstate;
1488   if(clear)
1489     multi->recheckstate = FALSE;
1490   return retval;
1491 }
1492 
1493 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1494                                  struct Curl_easy *data,
1495                                  struct connectdata *conn)
1496 {
1497   CURLMcode rc;
1498 
1499   if(multi->in_callback)
1500     return CURLM_RECURSIVE_API_CALL;
1501 
1502   rc = curl_multi_add_handle(multi, data);
1503   if(!rc) {
1504     struct SingleRequest *k = &data->req;
1505 
1506     /* pass in NULL for 'conn' here since we don't want to init the
1507        connection, only this transfer */
1508     Curl_init_do(data, NULL);
1509 
1510     /* take this handle to the perform state right away */
1511     multistate(data, MSTATE_PERFORMING);
1512     Curl_attach_connnection(data, conn);
1513     k->keepon |= KEEP_RECV; /* setup to receive! */
1514   }
1515   return rc;
1516 }
1517 
1518 static CURLcode multi_do(struct Curl_easy *data, bool *done)
1519 {
1520   CURLcode result = CURLE_OK;
1521   struct connectdata *conn = data->conn;
1522 
1523   DEBUGASSERT(conn);
1524   DEBUGASSERT(conn->handler);
1525 
1526   if(conn->handler->do_it)
1527     /* generic protocol-specific function pointer set in curl_connect() */
1528     result = conn->handler->do_it(data, done);
1529 
1530   return result;
1531 }
1532 
1533 /*
1534  * multi_do_more() is called during the DO_MORE multi state. It is basically a
1535  * second stage DO state which (wrongly) was introduced to support FTP's
1536  * second connection.
1537  *
1538  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1539  * DOING state there's more work to do!
1540  */
1541 
1542 static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1543 {
1544   CURLcode result = CURLE_OK;
1545   struct connectdata *conn = data->conn;
1546 
1547   *complete = 0;
1548 
1549   if(conn->handler->do_more)
1550     result = conn->handler->do_more(data, complete);
1551 
1552   return result;
1553 }
1554 
1555 /*
1556  * Check whether a timeout occurred, and handle it if it did
1557  */
1558 static bool multi_handle_timeout(struct Curl_easy *data,
1559                                  struct curltime *now,
1560                                  bool *stream_error,
1561                                  CURLcode *result,
1562                                  bool connect_timeout)
1563 {
1564   timediff_t timeout_ms;
1565   timeout_ms = Curl_timeleft(data, now, connect_timeout);
1566 
1567   if(timeout_ms < 0) {
1568     /* Handle timed out */
1569     if(data->mstate == MSTATE_RESOLVING)
1570       failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1571             " milliseconds",
1572             Curl_timediff(*now, data->progress.t_startsingle));
1573     else if(data->mstate == MSTATE_CONNECTING)
1574       failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1575             " milliseconds",
1576             Curl_timediff(*now, data->progress.t_startsingle));
1577     else {
1578       struct SingleRequest *k = &data->req;
1579       if(k->size != -1) {
1580         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1581               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1582               CURL_FORMAT_CURL_OFF_T " bytes received",
1583               Curl_timediff(*now, data->progress.t_startsingle),
1584               k->bytecount, k->size);
1585       }
1586       else {
1587         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1588               " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1589               " bytes received",
1590               Curl_timediff(*now, data->progress.t_startsingle),
1591               k->bytecount);
1592       }
1593     }
1594 
1595     /* Force connection closed if the connection has indeed been used */
1596     if(data->mstate > MSTATE_DO) {
1597       streamclose(data->conn, "Disconnected with pending data");
1598       *stream_error = TRUE;
1599     }
1600     *result = CURLE_OPERATION_TIMEDOUT;
1601     (void)multi_done(data, *result, TRUE);
1602   }
1603 
1604   return (timeout_ms < 0);
1605 }
1606 
1607 /*
1608  * We are doing protocol-specific connecting and this is being called over and
1609  * over from the multi interface until the connection phase is done on
1610  * protocol layer.
1611  */
1612 
1613 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1614 {
1615   CURLcode result = CURLE_OK;
1616   struct connectdata *conn = data->conn;
1617 
1618   if(conn && conn->handler->connecting) {
1619     *done = FALSE;
1620     result = conn->handler->connecting(data, done);
1621   }
1622   else
1623     *done = TRUE;
1624 
1625   return result;
1626 }
1627 
1628 /*
1629  * We are DOING this is being called over and over from the multi interface
1630  * until the DOING phase is done on protocol layer.
1631  */
1632 
1633 static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1634 {
1635   CURLcode result = CURLE_OK;
1636   struct connectdata *conn = data->conn;
1637 
1638   if(conn && conn->handler->doing) {
1639     *done = FALSE;
1640     result = conn->handler->doing(data, done);
1641   }
1642   else
1643     *done = TRUE;
1644 
1645   return result;
1646 }
1647 
1648 /*
1649  * We have discovered that the TCP connection has been successful, we can now
1650  * proceed with some action.
1651  *
1652  */
1653 static CURLcode protocol_connect(struct Curl_easy *data,
1654                                  bool *protocol_done)
1655 {
1656   CURLcode result = CURLE_OK;
1657   struct connectdata *conn = data->conn;
1658   DEBUGASSERT(conn);
1659   DEBUGASSERT(protocol_done);
1660 
1661   *protocol_done = FALSE;
1662 
1663   if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1664     /* We already are connected, get back. This may happen when the connect
1665        worked fine in the first call, like when we connect to a local server
1666        or proxy. Note that we don't know if the protocol is actually done.
1667 
1668        Unless this protocol doesn't have any protocol-connect callback, as
1669        then we know we're done. */
1670     if(!conn->handler->connecting)
1671       *protocol_done = TRUE;
1672 
1673     return CURLE_OK;
1674   }
1675 
1676   if(!conn->bits.protoconnstart) {
1677 #ifndef CURL_DISABLE_PROXY
1678     result = Curl_proxy_connect(data, FIRSTSOCKET);
1679     if(result)
1680       return result;
1681 
1682     if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1683       /* wait for HTTPS proxy SSL initialization to complete */
1684       return CURLE_OK;
1685 
1686     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1687        Curl_connect_ongoing(conn))
1688       /* when using an HTTP tunnel proxy, await complete tunnel establishment
1689          before proceeding further. Return CURLE_OK so we'll be called again */
1690       return CURLE_OK;
1691 #endif
1692     if(conn->handler->connect_it) {
1693       /* is there a protocol-specific connect() procedure? */
1694 
1695       /* Call the protocol-specific connect function */
1696       result = conn->handler->connect_it(data, protocol_done);
1697     }
1698     else
1699       *protocol_done = TRUE;
1700 
1701     /* it has started, possibly even completed but that knowledge isn't stored
1702        in this bit! */
1703     if(!result)
1704       conn->bits.protoconnstart = TRUE;
1705   }
1706 
1707   return result; /* pass back status */
1708 }
1709 
1710 /*
1711  * Curl_preconnect() is called immediately before a connect starts. When a
1712  * redirect is followed, this is then called multiple times during a single
1713  * transfer.
1714  */
1715 CURLcode Curl_preconnect(struct Curl_easy *data)
1716 {
1717   if(!data->state.buffer) {
1718     data->state.buffer = malloc(data->set.buffer_size + 1);
1719     if(!data->state.buffer)
1720       return CURLE_OUT_OF_MEMORY;
1721   }
1722   return CURLE_OK;
1723 }
1724 
1725 
1726 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1727                                  struct curltime *nowp,
1728                                  struct Curl_easy *data)
1729 {
1730   struct Curl_message *msg = NULL;
1731   bool connected;
1732   bool async;
1733   bool protocol_connected = FALSE;
1734   bool dophase_done = FALSE;
1735   bool done = FALSE;
1736   CURLMcode rc;
1737   CURLcode result = CURLE_OK;
1738   timediff_t recv_timeout_ms;
1739   timediff_t send_timeout_ms;
1740   int control;
1741 
1742   if(!GOOD_EASY_HANDLE(data))
1743     return CURLM_BAD_EASY_HANDLE;
1744 
1745   do {
1746     /* A "stream" here is a logical stream if the protocol can handle that
1747        (HTTP/2), or the full connection for older protocols */
1748     bool stream_error = FALSE;
1749     rc = CURLM_OK;
1750 
1751     if(multi_ischanged(multi, TRUE)) {
1752       DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!"));
1753       process_pending_handles(multi); /* multiplexed */
1754     }
1755 
1756     if(data->mstate > MSTATE_CONNECT &&
1757        data->mstate < MSTATE_COMPLETED) {
1758       /* Make sure we set the connection's current owner */
1759       DEBUGASSERT(data->conn);
1760       if(!data->conn)
1761         return CURLM_INTERNAL_ERROR;
1762     }
1763 
1764     if(data->conn &&
1765        (data->mstate >= MSTATE_CONNECT) &&
1766        (data->mstate < MSTATE_COMPLETED)) {
1767       /* Check for overall operation timeout here but defer handling the
1768        * connection timeout to later, to allow for a connection to be set up
1769        * in the window since we last checked timeout. This prevents us
1770        * tearing down a completed connection in the case where we were slow
1771        * to check the timeout (e.g. process descheduled during this loop).
1772        * We set connect_timeout=FALSE to do this. */
1773 
1774       /* we need to wait for the connect state as only then is the start time
1775          stored, but we must not check already completed handles */
1776       if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
1777         /* Skip the statemachine and go directly to error handling section. */
1778         goto statemachine_end;
1779       }
1780     }
1781 
1782     switch(data->mstate) {
1783     case MSTATE_INIT:
1784       /* init this transfer. */
1785       result = Curl_pretransfer(data);
1786 
1787       if(!result) {
1788         /* after init, go CONNECT */
1789         multistate(data, MSTATE_CONNECT);
1790         *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
1791         rc = CURLM_CALL_MULTI_PERFORM;
1792       }
1793       break;
1794 
1795     case MSTATE_PENDING:
1796       /* We will stay here until there is a connection available. Then
1797          we try again in the MSTATE_CONNECT state. */
1798       break;
1799 
1800     case MSTATE_CONNECT:
1801       /* Connect. We want to get a connection identifier filled in. */
1802       /* init this transfer. */
1803       result = Curl_preconnect(data);
1804       if(result)
1805         break;
1806 
1807       *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1808       if(data->set.timeout)
1809         Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1810 
1811       if(data->set.connecttimeout)
1812         Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1813 
1814       result = Curl_connect(data, &async, &protocol_connected);
1815       if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1816         /* There was no connection available. We will go to the pending
1817            state and wait for an available connection. */
1818         multistate(data, MSTATE_PENDING);
1819 
1820         /* add this handle to the list of connect-pending handles */
1821         Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1822                                &data->connect_queue);
1823         result = CURLE_OK;
1824         break;
1825       }
1826       else if(data->state.previouslypending) {
1827         /* this transfer comes from the pending queue so try move another */
1828         infof(data, "Transfer was pending, now try another");
1829         process_pending_handles(data->multi);
1830       }
1831 
1832       if(!result) {
1833         if(async)
1834           /* We're now waiting for an asynchronous name lookup */
1835           multistate(data, MSTATE_RESOLVING);
1836         else {
1837           /* after the connect has been sent off, go WAITCONNECT unless the
1838              protocol connect is already done and we can go directly to
1839              WAITDO or DO! */
1840           rc = CURLM_CALL_MULTI_PERFORM;
1841 
1842           if(protocol_connected)
1843             multistate(data, MSTATE_DO);
1844           else {
1845 #ifndef CURL_DISABLE_HTTP
1846             if(Curl_connect_ongoing(data->conn))
1847               multistate(data, MSTATE_TUNNELING);
1848             else
1849 #endif
1850               multistate(data, MSTATE_CONNECTING);
1851           }
1852         }
1853       }
1854       break;
1855 
1856     case MSTATE_RESOLVING:
1857       /* awaiting an asynch name resolve to complete */
1858     {
1859       struct Curl_dns_entry *dns = NULL;
1860       struct connectdata *conn = data->conn;
1861       const char *hostname;
1862 
1863       DEBUGASSERT(conn);
1864 #ifndef CURL_DISABLE_PROXY
1865       if(conn->bits.httpproxy)
1866         hostname = conn->http_proxy.host.name;
1867       else
1868 #endif
1869         if(conn->bits.conn_to_host)
1870         hostname = conn->conn_to_host.name;
1871       else
1872         hostname = conn->host.name;
1873 
1874       /* check if we have the name resolved by now */
1875       dns = Curl_fetch_addr(data, hostname, (int)conn->port);
1876 
1877       if(dns) {
1878 #ifdef CURLRES_ASYNCH
1879         data->state.async.dns = dns;
1880         data->state.async.done = TRUE;
1881 #endif
1882         result = CURLE_OK;
1883         infof(data, "Hostname '%s' was found in DNS cache", hostname);
1884       }
1885 
1886       if(!dns)
1887         result = Curl_resolv_check(data, &dns);
1888 
1889       /* Update sockets here, because the socket(s) may have been
1890          closed and the application thus needs to be told, even if it
1891          is likely that the same socket(s) will again be used further
1892          down.  If the name has not yet been resolved, it is likely
1893          that new sockets have been opened in an attempt to contact
1894          another resolver. */
1895       singlesocket(multi, data);
1896 
1897       if(dns) {
1898         /* Perform the next step in the connection phase, and then move on
1899            to the WAITCONNECT state */
1900         result = Curl_once_resolved(data, &protocol_connected);
1901 
1902         if(result)
1903           /* if Curl_once_resolved() returns failure, the connection struct
1904              is already freed and gone */
1905           data->conn = NULL; /* no more connection */
1906         else {
1907           /* call again please so that we get the next socket setup */
1908           rc = CURLM_CALL_MULTI_PERFORM;
1909           if(protocol_connected)
1910             multistate(data, MSTATE_DO);
1911           else {
1912 #ifndef CURL_DISABLE_HTTP
1913             if(Curl_connect_ongoing(data->conn))
1914               multistate(data, MSTATE_TUNNELING);
1915             else
1916 #endif
1917               multistate(data, MSTATE_CONNECTING);
1918           }
1919         }
1920       }
1921 
1922       if(result) {
1923         /* failure detected */
1924         stream_error = TRUE;
1925         break;
1926       }
1927     }
1928     break;
1929 
1930 #ifndef CURL_DISABLE_HTTP
1931     case MSTATE_TUNNELING:
1932       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1933       DEBUGASSERT(data->conn);
1934       result = Curl_http_connect(data, &protocol_connected);
1935 #ifndef CURL_DISABLE_PROXY
1936       if(data->conn->bits.proxy_connect_closed) {
1937         rc = CURLM_CALL_MULTI_PERFORM;
1938         /* connect back to proxy again */
1939         result = CURLE_OK;
1940         multi_done(data, CURLE_OK, FALSE);
1941         multistate(data, MSTATE_CONNECT);
1942       }
1943       else
1944 #endif
1945         if(!result) {
1946           if(
1947 #ifndef CURL_DISABLE_PROXY
1948             (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
1949              data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
1950 #endif
1951             Curl_connect_complete(data->conn)) {
1952             rc = CURLM_CALL_MULTI_PERFORM;
1953             /* initiate protocol connect phase */
1954             multistate(data, MSTATE_PROTOCONNECT);
1955           }
1956         }
1957       else
1958         stream_error = TRUE;
1959       break;
1960 #endif
1961 
1962     case MSTATE_CONNECTING:
1963       /* awaiting a completion of an asynch TCP connect */
1964       DEBUGASSERT(data->conn);
1965       result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
1966       if(connected && !result) {
1967 #ifndef CURL_DISABLE_HTTP
1968         if(
1969 #ifndef CURL_DISABLE_PROXY
1970           (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
1971            !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
1972 #endif
1973           Curl_connect_ongoing(data->conn)) {
1974           multistate(data, MSTATE_TUNNELING);
1975           break;
1976         }
1977 #endif
1978         rc = CURLM_CALL_MULTI_PERFORM;
1979 #ifndef CURL_DISABLE_PROXY
1980         multistate(data,
1981                    data->conn->bits.tunnel_proxy?
1982                    MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
1983 #else
1984         multistate(data, MSTATE_PROTOCONNECT);
1985 #endif
1986       }
1987       else if(result) {
1988         /* failure detected */
1989         Curl_posttransfer(data);
1990         multi_done(data, result, TRUE);
1991         stream_error = TRUE;
1992         break;
1993       }
1994       break;
1995 
1996     case MSTATE_PROTOCONNECT:
1997       result = protocol_connect(data, &protocol_connected);
1998       if(!result && !protocol_connected)
1999         /* switch to waiting state */
2000         multistate(data, MSTATE_PROTOCONNECTING);
2001       else if(!result) {
2002         /* protocol connect has completed, go WAITDO or DO */
2003         multistate(data, MSTATE_DO);
2004         rc = CURLM_CALL_MULTI_PERFORM;
2005       }
2006       else {
2007         /* failure detected */
2008         Curl_posttransfer(data);
2009         multi_done(data, result, TRUE);
2010         stream_error = TRUE;
2011       }
2012       break;
2013 
2014     case MSTATE_PROTOCONNECTING:
2015       /* protocol-specific connect phase */
2016       result = protocol_connecting(data, &protocol_connected);
2017       if(!result && protocol_connected) {
2018         /* after the connect has completed, go WAITDO or DO */
2019         multistate(data, MSTATE_DO);
2020         rc = CURLM_CALL_MULTI_PERFORM;
2021       }
2022       else if(result) {
2023         /* failure detected */
2024         Curl_posttransfer(data);
2025         multi_done(data, result, TRUE);
2026         stream_error = TRUE;
2027       }
2028       break;
2029 
2030     case MSTATE_DO:
2031       if(data->set.fprereq) {
2032         int prereq_rc;
2033 
2034         /* call the prerequest callback function */
2035         Curl_set_in_callback(data, true);
2036         prereq_rc = data->set.fprereq(data->set.prereq_userp,
2037                                       data->info.conn_primary_ip,
2038                                       data->info.conn_local_ip,
2039                                       data->info.conn_primary_port,
2040                                       data->info.conn_local_port);
2041         Curl_set_in_callback(data, false);
2042         if(prereq_rc != CURL_PREREQFUNC_OK) {
2043           failf(data, "operation aborted by pre-request callback");
2044           /* failure in pre-request callback - don't do any other processing */
2045           result = CURLE_ABORTED_BY_CALLBACK;
2046           Curl_posttransfer(data);
2047           multi_done(data, result, FALSE);
2048           stream_error = TRUE;
2049           break;
2050         }
2051       }
2052 
2053       if(data->set.connect_only) {
2054         /* keep connection open for application to use the socket */
2055         connkeep(data->conn, "CONNECT_ONLY");
2056         multistate(data, MSTATE_DONE);
2057         result = CURLE_OK;
2058         rc = CURLM_CALL_MULTI_PERFORM;
2059       }
2060       else {
2061         /* Perform the protocol's DO action */
2062         result = multi_do(data, &dophase_done);
2063 
2064         /* When multi_do() returns failure, data->conn might be NULL! */
2065 
2066         if(!result) {
2067           if(!dophase_done) {
2068 #ifndef CURL_DISABLE_FTP
2069             /* some steps needed for wildcard matching */
2070             if(data->state.wildcardmatch) {
2071               struct WildcardData *wc = &data->wildcard;
2072               if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2073                 /* skip some states if it is important */
2074                 multi_done(data, CURLE_OK, FALSE);
2075 
2076                 /* if there's no connection left, skip the DONE state */
2077                 multistate(data, data->conn ?
2078                            MSTATE_DONE : MSTATE_COMPLETED);
2079                 rc = CURLM_CALL_MULTI_PERFORM;
2080                 break;
2081               }
2082             }
2083 #endif
2084             /* DO was not completed in one function call, we must continue
2085                DOING... */
2086             multistate(data, MSTATE_DOING);
2087             rc = CURLM_OK;
2088           }
2089 
2090           /* after DO, go DO_DONE... or DO_MORE */
2091           else if(data->conn->bits.do_more) {
2092             /* we're supposed to do more, but we need to sit down, relax
2093                and wait a little while first */
2094             multistate(data, MSTATE_DOING_MORE);
2095             rc = CURLM_OK;
2096           }
2097           else {
2098             /* we're done with the DO, now DID */
2099             multistate(data, MSTATE_DID);
2100             rc = CURLM_CALL_MULTI_PERFORM;
2101           }
2102         }
2103         else if((CURLE_SEND_ERROR == result) &&
2104                 data->conn->bits.reuse) {
2105           /*
2106            * In this situation, a connection that we were trying to use
2107            * may have unexpectedly died.  If possible, send the connection
2108            * back to the CONNECT phase so we can try again.
2109            */
2110           char *newurl = NULL;
2111           followtype follow = FOLLOW_NONE;
2112           CURLcode drc;
2113 
2114           drc = Curl_retry_request(data, &newurl);
2115           if(drc) {
2116             /* a failure here pretty much implies an out of memory */
2117             result = drc;
2118             stream_error = TRUE;
2119           }
2120 
2121           Curl_posttransfer(data);
2122           drc = multi_done(data, result, FALSE);
2123 
2124           /* When set to retry the connection, we must to go back to
2125            * the CONNECT state */
2126           if(newurl) {
2127             if(!drc || (drc == CURLE_SEND_ERROR)) {
2128               follow = FOLLOW_RETRY;
2129               drc = Curl_follow(data, newurl, follow);
2130               if(!drc) {
2131                 multistate(data, MSTATE_CONNECT);
2132                 rc = CURLM_CALL_MULTI_PERFORM;
2133                 result = CURLE_OK;
2134               }
2135               else {
2136                 /* Follow failed */
2137                 result = drc;
2138               }
2139             }
2140             else {
2141               /* done didn't return OK or SEND_ERROR */
2142               result = drc;
2143             }
2144           }
2145           else {
2146             /* Have error handler disconnect conn if we can't retry */
2147             stream_error = TRUE;
2148           }
2149           free(newurl);
2150         }
2151         else {
2152           /* failure detected */
2153           Curl_posttransfer(data);
2154           if(data->conn)
2155             multi_done(data, result, FALSE);
2156           stream_error = TRUE;
2157         }
2158       }
2159       break;
2160 
2161     case MSTATE_DOING:
2162       /* we continue DOING until the DO phase is complete */
2163       DEBUGASSERT(data->conn);
2164       result = protocol_doing(data, &dophase_done);
2165       if(!result) {
2166         if(dophase_done) {
2167           /* after DO, go DO_DONE or DO_MORE */
2168           multistate(data, data->conn->bits.do_more?
2169                      MSTATE_DOING_MORE : MSTATE_DID);
2170           rc = CURLM_CALL_MULTI_PERFORM;
2171         } /* dophase_done */
2172       }
2173       else {
2174         /* failure detected */
2175         Curl_posttransfer(data);
2176         multi_done(data, result, FALSE);
2177         stream_error = TRUE;
2178       }
2179       break;
2180 
2181     case MSTATE_DOING_MORE:
2182       /*
2183        * When we are connected, DOING MORE and then go DID
2184        */
2185       DEBUGASSERT(data->conn);
2186       result = multi_do_more(data, &control);
2187 
2188       if(!result) {
2189         if(control) {
2190           /* if positive, advance to DO_DONE
2191              if negative, go back to DOING */
2192           multistate(data, control == 1?
2193                      MSTATE_DID : MSTATE_DOING);
2194           rc = CURLM_CALL_MULTI_PERFORM;
2195         }
2196         else
2197           /* stay in DO_MORE */
2198           rc = CURLM_OK;
2199       }
2200       else {
2201         /* failure detected */
2202         Curl_posttransfer(data);
2203         multi_done(data, result, FALSE);
2204         stream_error = TRUE;
2205       }
2206       break;
2207 
2208     case MSTATE_DID:
2209       DEBUGASSERT(data->conn);
2210       if(data->conn->bits.multiplex)
2211         /* Check if we can move pending requests to send pipe */
2212         process_pending_handles(multi); /*  multiplexed */
2213 
2214       /* Only perform the transfer if there's a good socket to work with.
2215          Having both BAD is a signal to skip immediately to DONE */
2216       if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2217          (data->conn->writesockfd != CURL_SOCKET_BAD))
2218         multistate(data, MSTATE_PERFORMING);
2219       else {
2220 #ifndef CURL_DISABLE_FTP
2221         if(data->state.wildcardmatch &&
2222            ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2223           data->wildcard.state = CURLWC_DONE;
2224         }
2225 #endif
2226         multistate(data, MSTATE_DONE);
2227       }
2228       rc = CURLM_CALL_MULTI_PERFORM;
2229       break;
2230 
2231     case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2232       DEBUGASSERT(data->conn);
2233       /* if both rates are within spec, resume transfer */
2234       if(Curl_pgrsUpdate(data))
2235         result = CURLE_ABORTED_BY_CALLBACK;
2236       else
2237         result = Curl_speedcheck(data, *nowp);
2238 
2239       if(result) {
2240         if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2241            result != CURLE_HTTP2_STREAM)
2242           streamclose(data->conn, "Transfer returned error");
2243 
2244         Curl_posttransfer(data);
2245         multi_done(data, result, TRUE);
2246       }
2247       else {
2248         send_timeout_ms = 0;
2249         if(data->set.max_send_speed)
2250           send_timeout_ms =
2251             Curl_pgrsLimitWaitTime(data->progress.uploaded,
2252                                    data->progress.ul_limit_size,
2253                                    data->set.max_send_speed,
2254                                    data->progress.ul_limit_start,
2255                                    *nowp);
2256 
2257         recv_timeout_ms = 0;
2258         if(data->set.max_recv_speed)
2259           recv_timeout_ms =
2260             Curl_pgrsLimitWaitTime(data->progress.downloaded,
2261                                    data->progress.dl_limit_size,
2262                                    data->set.max_recv_speed,
2263                                    data->progress.dl_limit_start,
2264                                    *nowp);
2265 
2266         if(!send_timeout_ms && !recv_timeout_ms) {
2267           multistate(data, MSTATE_PERFORMING);
2268           Curl_ratelimit(data, *nowp);
2269         }
2270         else if(send_timeout_ms >= recv_timeout_ms)
2271           Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2272         else
2273           Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2274       }
2275       break;
2276 
2277     case MSTATE_PERFORMING:
2278     {
2279       char *newurl = NULL;
2280       bool retry = FALSE;
2281       bool comeback = FALSE;
2282       DEBUGASSERT(data->state.buffer);
2283       /* check if over send speed */
2284       send_timeout_ms = 0;
2285       if(data->set.max_send_speed)
2286         send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2287                                                  data->progress.ul_limit_size,
2288                                                  data->set.max_send_speed,
2289                                                  data->progress.ul_limit_start,
2290                                                  *nowp);
2291 
2292       /* check if over recv speed */
2293       recv_timeout_ms = 0;
2294       if(data->set.max_recv_speed)
2295         recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2296                                                  data->progress.dl_limit_size,
2297                                                  data->set.max_recv_speed,
2298                                                  data->progress.dl_limit_start,
2299                                                  *nowp);
2300 
2301       if(send_timeout_ms || recv_timeout_ms) {
2302         Curl_ratelimit(data, *nowp);
2303         multistate(data, MSTATE_RATELIMITING);
2304         if(send_timeout_ms >= recv_timeout_ms)
2305           Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2306         else
2307           Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2308         break;
2309       }
2310 
2311       /* read/write data if it is ready to do so */
2312       result = Curl_readwrite(data->conn, data, &done, &comeback);
2313 
2314       if(done || (result == CURLE_RECV_ERROR)) {
2315         /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2316          * condition and the server closed the re-used connection exactly when
2317          * we wanted to use it, so figure out if that is indeed the case.
2318          */
2319         CURLcode ret = Curl_retry_request(data, &newurl);
2320         if(!ret)
2321           retry = (newurl)?TRUE:FALSE;
2322         else if(!result)
2323           result = ret;
2324 
2325         if(retry) {
2326           /* if we are to retry, set the result to OK and consider the
2327              request as done */
2328           result = CURLE_OK;
2329           done = TRUE;
2330         }
2331       }
2332       else if((CURLE_HTTP2_STREAM == result) &&
2333               Curl_h2_http_1_1_error(data)) {
2334         CURLcode ret = Curl_retry_request(data, &newurl);
2335 
2336         if(!ret) {
2337           infof(data, "Downgrades to HTTP/1.1!");
2338           streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2339           data->state.httpwant = CURL_HTTP_VERSION_1_1;
2340           /* clear the error message bit too as we ignore the one we got */
2341           data->state.errorbuf = FALSE;
2342           if(!newurl)
2343             /* typically for HTTP_1_1_REQUIRED error on first flight */
2344             newurl = strdup(data->state.url);
2345           /* if we are to retry, set the result to OK and consider the request
2346              as done */
2347           retry = TRUE;
2348           result = CURLE_OK;
2349           done = TRUE;
2350         }
2351         else
2352           result = ret;
2353       }
2354 
2355       if(result) {
2356         /*
2357          * The transfer phase returned error, we mark the connection to get
2358          * closed to prevent being re-used. This is because we can't possibly
2359          * know if the connection is in a good shape or not now.  Unless it is
2360          * a protocol which uses two "channels" like FTP, as then the error
2361          * happened in the data connection.
2362          */
2363 
2364         if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2365            result != CURLE_HTTP2_STREAM)
2366           streamclose(data->conn, "Transfer returned error");
2367 
2368         Curl_posttransfer(data);
2369         multi_done(data, result, TRUE);
2370       }
2371       else if(done) {
2372 
2373         /* call this even if the readwrite function returned error */
2374         Curl_posttransfer(data);
2375 
2376         /* When we follow redirects or is set to retry the connection, we must
2377            to go back to the CONNECT state */
2378         if(data->req.newurl || retry) {
2379           followtype follow = FOLLOW_NONE;
2380           if(!retry) {
2381             /* if the URL is a follow-location and not just a retried request
2382                then figure out the URL here */
2383             free(newurl);
2384             newurl = data->req.newurl;
2385             data->req.newurl = NULL;
2386             follow = FOLLOW_REDIR;
2387           }
2388           else
2389             follow = FOLLOW_RETRY;
2390           (void)multi_done(data, CURLE_OK, FALSE);
2391           /* multi_done() might return CURLE_GOT_NOTHING */
2392           result = Curl_follow(data, newurl, follow);
2393           if(!result) {
2394             multistate(data, MSTATE_CONNECT);
2395             rc = CURLM_CALL_MULTI_PERFORM;
2396           }
2397           free(newurl);
2398         }
2399         else {
2400           /* after the transfer is done, go DONE */
2401 
2402           /* but first check to see if we got a location info even though we're
2403              not following redirects */
2404           if(data->req.location) {
2405             free(newurl);
2406             newurl = data->req.location;
2407             data->req.location = NULL;
2408             result = Curl_follow(data, newurl, FOLLOW_FAKE);
2409             free(newurl);
2410             if(result) {
2411               stream_error = TRUE;
2412               result = multi_done(data, result, TRUE);
2413             }
2414           }
2415 
2416           if(!result) {
2417             multistate(data, MSTATE_DONE);
2418             rc = CURLM_CALL_MULTI_PERFORM;
2419           }
2420         }
2421       }
2422       else if(comeback) {
2423         /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2424            won't get stuck on this transfer at the expense of other concurrent
2425            transfers */
2426         Curl_expire(data, 0, EXPIRE_RUN_NOW);
2427         rc = CURLM_OK;
2428       }
2429       break;
2430     }
2431 
2432     case MSTATE_DONE:
2433       /* this state is highly transient, so run another loop after this */
2434       rc = CURLM_CALL_MULTI_PERFORM;
2435 
2436       if(data->conn) {
2437         CURLcode res;
2438 
2439         if(data->conn->bits.multiplex)
2440           /* Check if we can move pending requests to connection */
2441           process_pending_handles(multi); /* multiplexing */
2442 
2443         /* post-transfer command */
2444         res = multi_done(data, result, FALSE);
2445 
2446         /* allow a previously set error code take precedence */
2447         if(!result)
2448           result = res;
2449       }
2450 
2451 #ifndef CURL_DISABLE_FTP
2452       if(data->state.wildcardmatch) {
2453         if(data->wildcard.state != CURLWC_DONE) {
2454           /* if a wildcard is set and we are not ending -> lets start again
2455              with MSTATE_INIT */
2456           multistate(data, MSTATE_INIT);
2457           break;
2458         }
2459       }
2460 #endif
2461       /* after we have DONE what we're supposed to do, go COMPLETED, and
2462          it doesn't matter what the multi_done() returned! */
2463       multistate(data, MSTATE_COMPLETED);
2464       break;
2465 
2466     case MSTATE_COMPLETED:
2467       break;
2468 
2469     case MSTATE_MSGSENT:
2470       data->result = result;
2471       return CURLM_OK; /* do nothing */
2472 
2473     default:
2474       return CURLM_INTERNAL_ERROR;
2475     }
2476 
2477     if(data->conn &&
2478        data->mstate >= MSTATE_CONNECT &&
2479        data->mstate < MSTATE_DO &&
2480        rc != CURLM_CALL_MULTI_PERFORM &&
2481        !multi_ischanged(multi, false)) {
2482       /* We now handle stream timeouts if and only if this will be the last
2483        * loop iteration. We only check this on the last iteration to ensure
2484        * that if we know we have additional work to do immediately
2485        * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2486        * declaring the connection timed out as we may almost have a completed
2487        * connection. */
2488       multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
2489     }
2490 
2491     statemachine_end:
2492 
2493     if(data->mstate < MSTATE_COMPLETED) {
2494       if(result) {
2495         /*
2496          * If an error was returned, and we aren't in completed state now,
2497          * then we go to completed and consider this transfer aborted.
2498          */
2499 
2500         /* NOTE: no attempt to disconnect connections must be made
2501            in the case blocks above - cleanup happens only here */
2502 
2503         /* Check if we can move pending requests to send pipe */
2504         process_pending_handles(multi); /* connection */
2505 
2506         if(data->conn) {
2507           if(stream_error) {
2508             /* Don't attempt to send data over a connection that timed out */
2509             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2510             struct connectdata *conn = data->conn;
2511 
2512             /* This is where we make sure that the conn pointer is reset.
2513                We don't have to do this in every case block above where a
2514                failure is detected */
2515             Curl_detach_connnection(data);
2516 
2517             /* remove connection from cache */
2518             Curl_conncache_remove_conn(data, conn, TRUE);
2519 
2520             /* disconnect properly */
2521             Curl_disconnect(data, conn, dead_connection);
2522           }
2523         }
2524         else if(data->mstate == MSTATE_CONNECT) {
2525           /* Curl_connect() failed */
2526           (void)Curl_posttransfer(data);
2527         }
2528 
2529         multistate(data, MSTATE_COMPLETED);
2530         rc = CURLM_CALL_MULTI_PERFORM;
2531       }
2532       /* if there's still a connection to use, call the progress function */
2533       else if(data->conn && Curl_pgrsUpdate(data)) {
2534         /* aborted due to progress callback return code must close the
2535            connection */
2536         result = CURLE_ABORTED_BY_CALLBACK;
2537         streamclose(data->conn, "Aborted by callback");
2538 
2539         /* if not yet in DONE state, go there, otherwise COMPLETED */
2540         multistate(data, (data->mstate < MSTATE_DONE)?
2541                    MSTATE_DONE: MSTATE_COMPLETED);
2542         rc = CURLM_CALL_MULTI_PERFORM;
2543       }
2544     }
2545 
2546     if(MSTATE_COMPLETED == data->mstate) {
2547       if(data->set.fmultidone) {
2548         /* signal via callback instead */
2549         data->set.fmultidone(data, result);
2550       }
2551       else {
2552         /* now fill in the Curl_message with this info */
2553         msg = &data->msg;
2554 
2555         msg->extmsg.msg = CURLMSG_DONE;
2556         msg->extmsg.easy_handle = data;
2557         msg->extmsg.data.result = result;
2558 
2559         rc = multi_addmsg(multi, msg);
2560         DEBUGASSERT(!data->conn);
2561       }
2562       multistate(data, MSTATE_MSGSENT);
2563     }
2564   } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2565 
2566   data->result = result;
2567   return rc;
2568 }
2569 
2570 
2571 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2572 {
2573   struct Curl_easy *data;
2574   CURLMcode returncode = CURLM_OK;
2575   struct Curl_tree *t;
2576   struct curltime now = Curl_now();
2577 
2578   if(!GOOD_MULTI_HANDLE(multi))
2579     return CURLM_BAD_HANDLE;
2580 
2581   if(multi->in_callback)
2582     return CURLM_RECURSIVE_API_CALL;
2583 
2584   data = multi->easyp;
2585   while(data) {
2586     CURLMcode result;
2587     SIGPIPE_VARIABLE(pipe_st);
2588 
2589     sigpipe_ignore(data, &pipe_st);
2590     result = multi_runsingle(multi, &now, data);
2591     sigpipe_restore(&pipe_st);
2592 
2593     if(result)
2594       returncode = result;
2595 
2596     data = data->next; /* operate on next handle */
2597   }
2598 
2599   /*
2600    * Simply remove all expired timers from the splay since handles are dealt
2601    * with unconditionally by this function and curl_multi_timeout() requires
2602    * that already passed/handled expire times are removed from the splay.
2603    *
2604    * It is important that the 'now' value is set at the entry of this function
2605    * and not for the current time as it may have ticked a little while since
2606    * then and then we risk this loop to remove timers that actually have not
2607    * been handled!
2608    */
2609   do {
2610     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2611     if(t)
2612       /* the removed may have another timeout in queue */
2613       (void)add_next_timeout(now, multi, t->payload);
2614 
2615   } while(t);
2616 
2617   *running_handles = multi->num_alive;
2618 
2619   if(CURLM_OK >= returncode)
2620     Curl_update_timer(multi);
2621 
2622   return returncode;
2623 }
2624 
2625 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2626 {
2627   struct Curl_easy *data;
2628   struct Curl_easy *nextdata;
2629 
2630   if(GOOD_MULTI_HANDLE(multi)) {
2631     if(multi->in_callback)
2632       return CURLM_RECURSIVE_API_CALL;
2633 
2634     multi->magic = 0; /* not good anymore */
2635 
2636     /* First remove all remaining easy handles */
2637     data = multi->easyp;
2638     while(data) {
2639       nextdata = data->next;
2640       if(!data->state.done && data->conn)
2641         /* if DONE was never called for this handle */
2642         (void)multi_done(data, CURLE_OK, TRUE);
2643       if(data->dns.hostcachetype == HCACHE_MULTI) {
2644         /* clear out the usage of the shared DNS cache */
2645         Curl_hostcache_clean(data, data->dns.hostcache);
2646         data->dns.hostcache = NULL;
2647         data->dns.hostcachetype = HCACHE_NONE;
2648       }
2649 
2650       /* Clear the pointer to the connection cache */
2651       data->state.conn_cache = NULL;
2652       data->multi = NULL; /* clear the association */
2653 
2654 #ifdef USE_LIBPSL
2655       if(data->psl == &multi->psl)
2656         data->psl = NULL;
2657 #endif
2658 
2659       data = nextdata;
2660     }
2661 
2662     /* Close all the connections in the connection cache */
2663     Curl_conncache_close_all_connections(&multi->conn_cache);
2664 
2665     Curl_hash_destroy(&multi->sockhash);
2666     Curl_conncache_destroy(&multi->conn_cache);
2667     Curl_llist_destroy(&multi->msglist, NULL);
2668     Curl_llist_destroy(&multi->pending, NULL);
2669 
2670     Curl_hash_destroy(&multi->hostcache);
2671     Curl_psl_destroy(&multi->psl);
2672 
2673 #ifdef USE_WINSOCK
2674     WSACloseEvent(multi->wsa_event);
2675 #else
2676 #ifdef ENABLE_WAKEUP
2677     sclose(multi->wakeup_pair[0]);
2678     sclose(multi->wakeup_pair[1]);
2679 #endif
2680 #endif
2681     free(multi);
2682 
2683     return CURLM_OK;
2684   }
2685   return CURLM_BAD_HANDLE;
2686 }
2687 
2688 /*
2689  * curl_multi_info_read()
2690  *
2691  * This function is the primary way for a multi/multi_socket application to
2692  * figure out if a transfer has ended. We MUST make this function as fast as
2693  * possible as it will be polled frequently and we MUST NOT scan any lists in
2694  * here to figure out things. We must scale fine to thousands of handles and
2695  * beyond. The current design is fully O(1).
2696  */
2697 
2698 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2699 {
2700   struct Curl_message *msg;
2701 
2702   *msgs_in_queue = 0; /* default to none */
2703 
2704   if(GOOD_MULTI_HANDLE(multi) &&
2705      !multi->in_callback &&
2706      Curl_llist_count(&multi->msglist)) {
2707     /* there is one or more messages in the list */
2708     struct Curl_llist_element *e;
2709 
2710     /* extract the head of the list to return */
2711     e = multi->msglist.head;
2712 
2713     msg = e->ptr;
2714 
2715     /* remove the extracted entry */
2716     Curl_llist_remove(&multi->msglist, e, NULL);
2717 
2718     *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2719 
2720     return &msg->extmsg;
2721   }
2722   return NULL;
2723 }
2724 
2725 /*
2726  * singlesocket() checks what sockets we deal with and their "action state"
2727  * and if we have a different state in any of those sockets from last time we
2728  * call the callback accordingly.
2729  */
2730 static CURLMcode singlesocket(struct Curl_multi *multi,
2731                               struct Curl_easy *data)
2732 {
2733   curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
2734   int i;
2735   struct Curl_sh_entry *entry;
2736   curl_socket_t s;
2737   int num;
2738   unsigned int curraction;
2739   unsigned char actions[MAX_SOCKSPEREASYHANDLE];
2740 
2741   for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
2742     socks[i] = CURL_SOCKET_BAD;
2743 
2744   /* Fill in the 'current' struct with the state as it is now: what sockets to
2745      supervise and for what actions */
2746   curraction = multi_getsock(data, socks);
2747 
2748   /* We have 0 .. N sockets already and we get to know about the 0 .. M
2749      sockets we should have from now on. Detect the differences, remove no
2750      longer supervised ones and add new ones */
2751 
2752   /* walk over the sockets we got right now */
2753   for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
2754         (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2755       i++) {
2756     unsigned char action = CURL_POLL_NONE;
2757     unsigned char prevaction = 0;
2758     int comboaction;
2759     bool sincebefore = FALSE;
2760 
2761     s = socks[i];
2762 
2763     /* get it from the hash */
2764     entry = sh_getentry(&multi->sockhash, s);
2765 
2766     if(curraction & GETSOCK_READSOCK(i))
2767       action |= CURL_POLL_IN;
2768     if(curraction & GETSOCK_WRITESOCK(i))
2769       action |= CURL_POLL_OUT;
2770 
2771     actions[i] = action;
2772     if(entry) {
2773       /* check if new for this transfer */
2774       int j;
2775       for(j = 0; j< data->numsocks; j++) {
2776         if(s == data->sockets[j]) {
2777           prevaction = data->actions[j];
2778           sincebefore = TRUE;
2779           break;
2780         }
2781       }
2782     }
2783     else {
2784       /* this is a socket we didn't have before, add it to the hash! */
2785       entry = sh_addentry(&multi->sockhash, s);
2786       if(!entry)
2787         /* fatal */
2788         return CURLM_OUT_OF_MEMORY;
2789     }
2790     if(sincebefore && (prevaction != action)) {
2791       /* Socket was used already, but different action now */
2792       if(prevaction & CURL_POLL_IN)
2793         entry->readers--;
2794       if(prevaction & CURL_POLL_OUT)
2795         entry->writers--;
2796       if(action & CURL_POLL_IN)
2797         entry->readers++;
2798       if(action & CURL_POLL_OUT)
2799         entry->writers++;
2800     }
2801     else if(!sincebefore) {
2802       /* a new user */
2803       entry->users++;
2804       if(action & CURL_POLL_IN)
2805         entry->readers++;
2806       if(action & CURL_POLL_OUT)
2807         entry->writers++;
2808 
2809       /* add 'data' to the transfer hash on this socket! */
2810       if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2811                         sizeof(struct Curl_easy *), data))
2812         return CURLM_OUT_OF_MEMORY;
2813     }
2814 
2815     comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2816                    (entry->readers ? CURL_POLL_IN : 0);
2817 
2818     /* socket existed before and has the same action set as before */
2819     if(sincebefore && ((int)entry->action == comboaction))
2820       /* same, continue */
2821       continue;
2822 
2823     if(multi->socket_cb)
2824       multi->socket_cb(data, s, comboaction, multi->socket_userp,
2825                        entry->socketp);
2826 
2827     entry->action = comboaction; /* store the current action state */
2828   }
2829 
2830   num = i; /* number of sockets */
2831 
2832   /* when we've walked over all the sockets we should have right now, we must
2833      make sure to detect sockets that are removed */
2834   for(i = 0; i< data->numsocks; i++) {
2835     int j;
2836     bool stillused = FALSE;
2837     s = data->sockets[i];
2838     for(j = 0; j < num; j++) {
2839       if(s == socks[j]) {
2840         /* this is still supervised */
2841         stillused = TRUE;
2842         break;
2843       }
2844     }
2845     if(stillused)
2846       continue;
2847 
2848     entry = sh_getentry(&multi->sockhash, s);
2849     /* if this is NULL here, the socket has been closed and notified so
2850        already by Curl_multi_closed() */
2851     if(entry) {
2852       unsigned char oldactions = data->actions[i];
2853       /* this socket has been removed. Decrease user count */
2854       entry->users--;
2855       if(oldactions & CURL_POLL_OUT)
2856         entry->writers--;
2857       if(oldactions & CURL_POLL_IN)
2858         entry->readers--;
2859       if(!entry->users) {
2860         if(multi->socket_cb)
2861           multi->socket_cb(data, s, CURL_POLL_REMOVE,
2862                            multi->socket_userp,
2863                            entry->socketp);
2864         sh_delentry(entry, &multi->sockhash, s);
2865       }
2866       else {
2867         /* still users, but remove this handle as a user of this socket */
2868         if(Curl_hash_delete(&entry->transfers, (char *)&data,
2869                             sizeof(struct Curl_easy *))) {
2870           DEBUGASSERT(NULL);
2871         }
2872       }
2873     }
2874   } /* for loop over numsocks */
2875 
2876   memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2877   memcpy(data->actions, actions, num*sizeof(char));
2878   data->numsocks = num;
2879   return CURLM_OK;
2880 }
2881 
2882 void Curl_updatesocket(struct Curl_easy *data)
2883 {
2884   singlesocket(data->multi, data);
2885 }
2886 
2887 
2888 /*
2889  * Curl_multi_closed()
2890  *
2891  * Used by the connect code to tell the multi_socket code that one of the
2892  * sockets we were using is about to be closed.  This function will then
2893  * remove it from the sockethash for this handle to make the multi_socket API
2894  * behave properly, especially for the case when libcurl will create another
2895  * socket again and it gets the same file descriptor number.
2896  */
2897 
2898 void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
2899 {
2900   if(data) {
2901     /* if there's still an easy handle associated with this connection */
2902     struct Curl_multi *multi = data->multi;
2903     if(multi) {
2904       /* this is set if this connection is part of a handle that is added to
2905          a multi handle, and only then this is necessary */
2906       struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2907 
2908       if(entry) {
2909         if(multi->socket_cb)
2910           multi->socket_cb(data, s, CURL_POLL_REMOVE,
2911                            multi->socket_userp,
2912                            entry->socketp);
2913 
2914         /* now remove it from the socket hash */
2915         sh_delentry(entry, &multi->sockhash, s);
2916       }
2917     }
2918   }
2919 }
2920 
2921 /*
2922  * add_next_timeout()
2923  *
2924  * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
2925  * when it has just been removed from the splay tree because the timeout has
2926  * expired. This function is then to advance in the list to pick the next
2927  * timeout to use (skip the already expired ones) and add this node back to
2928  * the splay tree again.
2929  *
2930  * The splay tree only has each sessionhandle as a single node and the nearest
2931  * timeout is used to sort it on.
2932  */
2933 static CURLMcode add_next_timeout(struct curltime now,
2934                                   struct Curl_multi *multi,
2935                                   struct Curl_easy *d)
2936 {
2937   struct curltime *tv = &d->state.expiretime;
2938   struct Curl_llist *list = &d->state.timeoutlist;
2939   struct Curl_llist_element *e;
2940   struct time_node *node = NULL;
2941 
2942   /* move over the timeout list for this specific handle and remove all
2943      timeouts that are now passed tense and store the next pending
2944      timeout in *tv */
2945   for(e = list->head; e;) {
2946     struct Curl_llist_element *n = e->next;
2947     timediff_t diff;
2948     node = (struct time_node *)e->ptr;
2949     diff = Curl_timediff(node->time, now);
2950     if(diff <= 0)
2951       /* remove outdated entry */
2952       Curl_llist_remove(list, e, NULL);
2953     else
2954       /* the list is sorted so get out on the first mismatch */
2955       break;
2956     e = n;
2957   }
2958   e = list->head;
2959   if(!e) {
2960     /* clear the expire times within the handles that we remove from the
2961        splay tree */
2962     tv->tv_sec = 0;
2963     tv->tv_usec = 0;
2964   }
2965   else {
2966     /* copy the first entry to 'tv' */
2967     memcpy(tv, &node->time, sizeof(*tv));
2968 
2969     /* Insert this node again into the splay.  Keep the timer in the list in
2970        case we need to recompute future timers. */
2971     multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2972                                        &d->state.timenode);
2973   }
2974   return CURLM_OK;
2975 }
2976 
2977 static CURLMcode multi_socket(struct Curl_multi *multi,
2978                               bool checkall,
2979                               curl_socket_t s,
2980                               int ev_bitmask,
2981                               int *running_handles)
2982 {
2983   CURLMcode result = CURLM_OK;
2984   struct Curl_easy *data = NULL;
2985   struct Curl_tree *t;
2986   struct curltime now = Curl_now();
2987 
2988   if(checkall) {
2989     /* *perform() deals with running_handles on its own */
2990     result = curl_multi_perform(multi, running_handles);
2991 
2992     /* walk through each easy handle and do the socket state change magic
2993        and callbacks */
2994     if(result != CURLM_BAD_HANDLE) {
2995       data = multi->easyp;
2996       while(data && !result) {
2997         result = singlesocket(multi, data);
2998         data = data->next;
2999       }
3000     }
3001 
3002     /* or should we fall-through and do the timer-based stuff? */
3003     return result;
3004   }
3005   if(s != CURL_SOCKET_TIMEOUT) {
3006     struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3007 
3008     if(!entry)
3009       /* Unmatched socket, we can't act on it but we ignore this fact.  In
3010          real-world tests it has been proved that libevent can in fact give
3011          the application actions even though the socket was just previously
3012          asked to get removed, so thus we better survive stray socket actions
3013          and just move on. */
3014       ;
3015     else {
3016       struct Curl_hash_iterator iter;
3017       struct Curl_hash_element *he;
3018 
3019       /* the socket can be shared by many transfers, iterate */
3020       Curl_hash_start_iterate(&entry->transfers, &iter);
3021       for(he = Curl_hash_next_element(&iter); he;
3022           he = Curl_hash_next_element(&iter)) {
3023         data = (struct Curl_easy *)he->ptr;
3024         DEBUGASSERT(data);
3025         DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3026 
3027         if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3028           /* set socket event bitmask if they're not locked */
3029           data->conn->cselect_bits = ev_bitmask;
3030 
3031         Curl_expire(data, 0, EXPIRE_RUN_NOW);
3032       }
3033 
3034       /* Now we fall-through and do the timer-based stuff, since we don't want
3035          to force the user to have to deal with timeouts as long as at least
3036          one connection in fact has traffic. */
3037 
3038       data = NULL; /* set data to NULL again to avoid calling
3039                       multi_runsingle() in case there's no need to */
3040       now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3041                            may have taken some time */
3042     }
3043   }
3044   else {
3045     /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3046        Curl_update_timer() to trigger a callback to the app again even if the
3047        same timeout is still the one to run after this call. That handles the
3048        case when the application asks libcurl to run the timeout
3049        prematurely. */
3050     memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3051   }
3052 
3053   /*
3054    * The loop following here will go on as long as there are expire-times left
3055    * to process in the splay and 'data' will be re-assigned for every expired
3056    * handle we deal with.
3057    */
3058   do {
3059     /* the first loop lap 'data' can be NULL */
3060     if(data) {
3061       SIGPIPE_VARIABLE(pipe_st);
3062 
3063       sigpipe_ignore(data, &pipe_st);
3064       result = multi_runsingle(multi, &now, data);
3065       sigpipe_restore(&pipe_st);
3066 
3067       if(CURLM_OK >= result) {
3068         /* get the socket(s) and check if the state has been changed since
3069            last */
3070         result = singlesocket(multi, data);
3071         if(result)
3072           return result;
3073       }
3074     }
3075 
3076     /* Check if there's one (more) expired timer to deal with! This function
3077        extracts a matching node if there is one */
3078 
3079     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3080     if(t) {
3081       data = t->payload; /* assign this for next loop */
3082       (void)add_next_timeout(now, multi, t->payload);
3083     }
3084 
3085   } while(t);
3086 
3087   *running_handles = multi->num_alive;
3088   return result;
3089 }
3090 
3091 #undef curl_multi_setopt
3092 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3093                             CURLMoption option, ...)
3094 {
3095   CURLMcode res = CURLM_OK;
3096   va_list param;
3097 
3098   if(!GOOD_MULTI_HANDLE(multi))
3099     return CURLM_BAD_HANDLE;
3100 
3101   if(multi->in_callback)
3102     return CURLM_RECURSIVE_API_CALL;
3103 
3104   va_start(param, option);
3105 
3106   switch(option) {
3107   case CURLMOPT_SOCKETFUNCTION:
3108     multi->socket_cb = va_arg(param, curl_socket_callback);
3109     break;
3110   case CURLMOPT_SOCKETDATA:
3111     multi->socket_userp = va_arg(param, void *);
3112     break;
3113   case CURLMOPT_PUSHFUNCTION:
3114     multi->push_cb = va_arg(param, curl_push_callback);
3115     break;
3116   case CURLMOPT_PUSHDATA:
3117     multi->push_userp = va_arg(param, void *);
3118     break;
3119   case CURLMOPT_PIPELINING:
3120     multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
3121     break;
3122   case CURLMOPT_TIMERFUNCTION:
3123     multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3124     break;
3125   case CURLMOPT_TIMERDATA:
3126     multi->timer_userp = va_arg(param, void *);
3127     break;
3128   case CURLMOPT_MAXCONNECTS:
3129     multi->maxconnects = va_arg(param, long);
3130     break;
3131   case CURLMOPT_MAX_HOST_CONNECTIONS:
3132     multi->max_host_connections = va_arg(param, long);
3133     break;
3134   case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3135     multi->max_total_connections = va_arg(param, long);
3136     break;
3137     /* options formerly used for pipelining */
3138   case CURLMOPT_MAX_PIPELINE_LENGTH:
3139     break;
3140   case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3141     break;
3142   case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3143     break;
3144   case CURLMOPT_PIPELINING_SITE_BL:
3145     break;
3146   case CURLMOPT_PIPELINING_SERVER_BL:
3147     break;
3148   case CURLMOPT_MAX_CONCURRENT_STREAMS:
3149     {
3150       long streams = va_arg(param, long);
3151       if(streams < 1)
3152         streams = 100;
3153       multi->max_concurrent_streams = curlx_sltoui(streams);
3154     }
3155     break;
3156   default:
3157     res = CURLM_UNKNOWN_OPTION;
3158     break;
3159   }
3160   va_end(param);
3161   return res;
3162 }
3163 
3164 /* we define curl_multi_socket() in the public multi.h header */
3165 #undef curl_multi_socket
3166 
3167 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3168                             int *running_handles)
3169 {
3170   CURLMcode result;
3171   if(multi->in_callback)
3172     return CURLM_RECURSIVE_API_CALL;
3173   result = multi_socket(multi, FALSE, s, 0, running_handles);
3174   if(CURLM_OK >= result)
3175     Curl_update_timer(multi);
3176   return result;
3177 }
3178 
3179 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3180                                    int ev_bitmask, int *running_handles)
3181 {
3182   CURLMcode result;
3183   if(multi->in_callback)
3184     return CURLM_RECURSIVE_API_CALL;
3185   result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3186   if(CURLM_OK >= result)
3187     Curl_update_timer(multi);
3188   return result;
3189 }
3190 
3191 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3192 {
3193   CURLMcode result;
3194   if(multi->in_callback)
3195     return CURLM_RECURSIVE_API_CALL;
3196   result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3197   if(CURLM_OK >= result)
3198     Curl_update_timer(multi);
3199   return result;
3200 }
3201 
3202 static CURLMcode multi_timeout(struct Curl_multi *multi,
3203                                long *timeout_ms)
3204 {
3205   static const struct curltime tv_zero = {0, 0};
3206 
3207   if(multi->timetree) {
3208     /* we have a tree of expire times */
3209     struct curltime now = Curl_now();
3210 
3211     /* splay the lowest to the bottom */
3212     multi->timetree = Curl_splay(tv_zero, multi->timetree);
3213 
3214     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3215       /* some time left before expiration */
3216       timediff_t diff = Curl_timediff(multi->timetree->key, now);
3217       if(diff <= 0)
3218         /*
3219          * Since we only provide millisecond resolution on the returned value
3220          * and the diff might be less than one millisecond here, we don't
3221          * return zero as that may cause short bursts of busyloops on fast
3222          * processors while the diff is still present but less than one
3223          * millisecond! instead we return 1 until the time is ripe.
3224          */
3225         *timeout_ms = 1;
3226       else
3227         /* this should be safe even on 64 bit archs, as we don't use that
3228            overly long timeouts */
3229         *timeout_ms = (long)diff;
3230     }
3231     else
3232       /* 0 means immediately */
3233       *timeout_ms = 0;
3234   }
3235   else
3236     *timeout_ms = -1;
3237 
3238   return CURLM_OK;
3239 }
3240 
3241 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3242                              long *timeout_ms)
3243 {
3244   /* First, make some basic checks that the CURLM handle is a good handle */
3245   if(!GOOD_MULTI_HANDLE(multi))
3246     return CURLM_BAD_HANDLE;
3247 
3248   if(multi->in_callback)
3249     return CURLM_RECURSIVE_API_CALL;
3250 
3251   return multi_timeout(multi, timeout_ms);
3252 }
3253 
3254 /*
3255  * Tell the application it should update its timers, if it subscribes to the
3256  * update timer callback.
3257  */
3258 void Curl_update_timer(struct Curl_multi *multi)
3259 {
3260   long timeout_ms;
3261 
3262   if(!multi->timer_cb)
3263     return;
3264   if(multi_timeout(multi, &timeout_ms)) {
3265     return;
3266   }
3267   if(timeout_ms < 0) {
3268     static const struct curltime none = {0, 0};
3269     if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3270       multi->timer_lastcall = none;
3271       /* there's no timeout now but there was one previously, tell the app to
3272          disable it */
3273       multi->timer_cb(multi, -1, multi->timer_userp);
3274       return;
3275     }
3276     return;
3277   }
3278 
3279   /* When multi_timeout() is done, multi->timetree points to the node with the
3280    * timeout we got the (relative) time-out time for. We can thus easily check
3281    * if this is the same (fixed) time as we got in a previous call and then
3282    * avoid calling the callback again. */
3283   if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3284     return;
3285 
3286   multi->timer_lastcall = multi->timetree->key;
3287 
3288   multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3289 }
3290 
3291 /*
3292  * multi_deltimeout()
3293  *
3294  * Remove a given timestamp from the list of timeouts.
3295  */
3296 static void
3297 multi_deltimeout(struct Curl_easy *data, expire_id eid)
3298 {
3299   struct Curl_llist_element *e;
3300   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3301   /* find and remove the specific node from the list */
3302   for(e = timeoutlist->head; e; e = e->next) {
3303     struct time_node *n = (struct time_node *)e->ptr;
3304     if(n->eid == eid) {
3305       Curl_llist_remove(timeoutlist, e, NULL);
3306       return;
3307     }
3308   }
3309 }
3310 
3311 /*
3312  * multi_addtimeout()
3313  *
3314  * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3315  * of list is always the timeout nearest in time.
3316  *
3317  */
3318 static CURLMcode
3319 multi_addtimeout(struct Curl_easy *data,
3320                  struct curltime *stamp,
3321                  expire_id eid)
3322 {
3323   struct Curl_llist_element *e;
3324   struct time_node *node;
3325   struct Curl_llist_element *prev = NULL;
3326   size_t n;
3327   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3328 
3329   node = &data->state.expires[eid];
3330 
3331   /* copy the timestamp and id */
3332   memcpy(&node->time, stamp, sizeof(*stamp));
3333   node->eid = eid; /* also marks it as in use */
3334 
3335   n = Curl_llist_count(timeoutlist);
3336   if(n) {
3337     /* find the correct spot in the list */
3338     for(e = timeoutlist->head; e; e = e->next) {
3339       struct time_node *check = (struct time_node *)e->ptr;
3340       timediff_t diff = Curl_timediff(check->time, node->time);
3341       if(diff > 0)
3342         break;
3343       prev = e;
3344     }
3345 
3346   }
3347   /* else
3348      this is the first timeout on the list */
3349 
3350   Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3351   return CURLM_OK;
3352 }
3353 
3354 /*
3355  * Curl_expire()
3356  *
3357  * given a number of milliseconds from now to use to set the 'act before
3358  * this'-time for the transfer, to be extracted by curl_multi_timeout()
3359  *
3360  * The timeout will be added to a queue of timeouts if it defines a moment in
3361  * time that is later than the current head of queue.
3362  *
3363  * Expire replaces a former timeout using the same id if already set.
3364  */
3365 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3366 {
3367   struct Curl_multi *multi = data->multi;
3368   struct curltime *nowp = &data->state.expiretime;
3369   struct curltime set;
3370 
3371   /* this is only interesting while there is still an associated multi struct
3372      remaining! */
3373   if(!multi)
3374     return;
3375 
3376   DEBUGASSERT(id < EXPIRE_LAST);
3377 
3378   set = Curl_now();
3379   set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3380   set.tv_usec += (unsigned int)(milli%1000)*1000;
3381 
3382   if(set.tv_usec >= 1000000) {
3383     set.tv_sec++;
3384     set.tv_usec -= 1000000;
3385   }
3386 
3387   /* Remove any timer with the same id just in case. */
3388   multi_deltimeout(data, id);
3389 
3390   /* Add it to the timer list.  It must stay in the list until it has expired
3391      in case we need to recompute the minimum timer later. */
3392   multi_addtimeout(data, &set, id);
3393 
3394   if(nowp->tv_sec || nowp->tv_usec) {
3395     /* This means that the struct is added as a node in the splay tree.
3396        Compare if the new time is earlier, and only remove-old/add-new if it
3397        is. */
3398     timediff_t diff = Curl_timediff(set, *nowp);
3399     int rc;
3400 
3401     if(diff > 0) {
3402       /* The current splay tree entry is sooner than this new expiry time.
3403          We don't need to update our splay tree entry. */
3404       return;
3405     }
3406 
3407     /* Since this is an updated time, we must remove the previous entry from
3408        the splay tree first and then re-add the new value */
3409     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3410                           &multi->timetree);
3411     if(rc)
3412       infof(data, "Internal error removing splay node = %d", rc);
3413   }
3414 
3415   /* Indicate that we are in the splay tree and insert the new timer expiry
3416      value since it is our local minimum. */
3417   *nowp = set;
3418   data->state.timenode.payload = data;
3419   multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3420                                      &data->state.timenode);
3421 }
3422 
3423 /*
3424  * Curl_expire_done()
3425  *
3426  * Removes the expire timer. Marks it as done.
3427  *
3428  */
3429 void Curl_expire_done(struct Curl_easy *data, expire_id id)
3430 {
3431   /* remove the timer, if there */
3432   multi_deltimeout(data, id);
3433 }
3434 
3435 /*
3436  * Curl_expire_clear()
3437  *
3438  * Clear ALL timeout values for this handle.
3439  */
3440 void Curl_expire_clear(struct Curl_easy *data)
3441 {
3442   struct Curl_multi *multi = data->multi;
3443   struct curltime *nowp = &data->state.expiretime;
3444 
3445   /* this is only interesting while there is still an associated multi struct
3446      remaining! */
3447   if(!multi)
3448     return;
3449 
3450   if(nowp->tv_sec || nowp->tv_usec) {
3451     /* Since this is an cleared time, we must remove the previous entry from
3452        the splay tree */
3453     struct Curl_llist *list = &data->state.timeoutlist;
3454     int rc;
3455 
3456     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3457                           &multi->timetree);
3458     if(rc)
3459       infof(data, "Internal error clearing splay node = %d", rc);
3460 
3461     /* flush the timeout list too */
3462     while(list->size > 0) {
3463       Curl_llist_remove(list, list->tail, NULL);
3464     }
3465 
3466 #ifdef DEBUGBUILD
3467     infof(data, "Expire cleared (transfer %p)", data);
3468 #endif
3469     nowp->tv_sec = 0;
3470     nowp->tv_usec = 0;
3471   }
3472 }
3473 
3474 
3475 
3476 
3477 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3478                             void *hashp)
3479 {
3480   struct Curl_sh_entry *there = NULL;
3481 
3482   if(multi->in_callback)
3483     return CURLM_RECURSIVE_API_CALL;
3484 
3485   there = sh_getentry(&multi->sockhash, s);
3486 
3487   if(!there)
3488     return CURLM_BAD_SOCKET;
3489 
3490   there->socketp = hashp;
3491 
3492   return CURLM_OK;
3493 }
3494 
3495 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3496 {
3497   return multi ? multi->max_host_connections : 0;
3498 }
3499 
3500 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3501 {
3502   return multi ? multi->max_total_connections : 0;
3503 }
3504 
3505 /*
3506  * When information about a connection has appeared, call this!
3507  */
3508 
3509 void Curl_multiuse_state(struct Curl_easy *data,
3510                          int bundlestate) /* use BUNDLE_* defines */
3511 {
3512   struct connectdata *conn;
3513   DEBUGASSERT(data);
3514   DEBUGASSERT(data->multi);
3515   conn = data->conn;
3516   DEBUGASSERT(conn);
3517   DEBUGASSERT(conn->bundle);
3518 
3519   conn->bundle->multiuse = bundlestate;
3520   process_pending_handles(data->multi);
3521 }
3522 
3523 static void process_pending_handles(struct Curl_multi *multi)
3524 {
3525   struct Curl_llist_element *e = multi->pending.head;
3526   if(e) {
3527     struct Curl_easy *data = e->ptr;
3528 
3529     DEBUGASSERT(data->mstate == MSTATE_PENDING);
3530 
3531     multistate(data, MSTATE_CONNECT);
3532 
3533     /* Remove this node from the list */
3534     Curl_llist_remove(&multi->pending, e, NULL);
3535 
3536     /* Make sure that the handle will be processed soonish. */
3537     Curl_expire(data, 0, EXPIRE_RUN_NOW);
3538 
3539     /* mark this as having been in the pending queue */
3540     data->state.previouslypending = TRUE;
3541   }
3542 }
3543 
3544 void Curl_set_in_callback(struct Curl_easy *data, bool value)
3545 {
3546   /* might get called when there is no data pointer! */
3547   if(data) {
3548     if(data->multi_easy)
3549       data->multi_easy->in_callback = value;
3550     else if(data->multi)
3551       data->multi->in_callback = value;
3552   }
3553 }
3554 
3555 bool Curl_is_in_callback(struct Curl_easy *easy)
3556 {
3557   return ((easy->multi && easy->multi->in_callback) ||
3558           (easy->multi_easy && easy->multi_easy->in_callback));
3559 }
3560 
3561 #ifdef DEBUGBUILD
3562 void Curl_multi_dump(struct Curl_multi *multi)
3563 {
3564   struct Curl_easy *data;
3565   int i;
3566   fprintf(stderr, "* Multi status: %d handles, %d alive\n",
3567           multi->num_easy, multi->num_alive);
3568   for(data = multi->easyp; data; data = data->next) {
3569     if(data->mstate < MSTATE_COMPLETED) {
3570       /* only display handles that are not completed */
3571       fprintf(stderr, "handle %p, state %s, %d sockets\n",
3572               (void *)data,
3573               statename[data->mstate], data->numsocks);
3574       for(i = 0; i < data->numsocks; i++) {
3575         curl_socket_t s = data->sockets[i];
3576         struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3577 
3578         fprintf(stderr, "%d ", (int)s);
3579         if(!entry) {
3580           fprintf(stderr, "INTERNAL CONFUSION\n");
3581           continue;
3582         }
3583         fprintf(stderr, "[%s %s] ",
3584                 (entry->action&CURL_POLL_IN)?"RECVING":"",
3585                 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3586       }
3587       if(data->numsocks)
3588         fprintf(stderr, "\n");
3589     }
3590   }
3591 }
3592 #endif
3593 
3594 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3595 {
3596   DEBUGASSERT(multi);
3597   return multi->max_concurrent_streams;
3598 }
3599