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