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