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