quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

multi.c (122154B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 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  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #include <curl/curl.h>
     28 
     29 #include "urldata.h"
     30 #include "transfer.h"
     31 #include "url.h"
     32 #include "cfilters.h"
     33 #include "connect.h"
     34 #include "progress.h"
     35 #include "easyif.h"
     36 #include "share.h"
     37 #include "psl.h"
     38 #include "multiif.h"
     39 #include "multi_ev.h"
     40 #include "sendf.h"
     41 #include "curlx/timeval.h"
     42 #include "http.h"
     43 #include "select.h"
     44 #include "curlx/warnless.h"
     45 #include "curlx/wait.h"
     46 #include "speedcheck.h"
     47 #include "conncache.h"
     48 #include "multihandle.h"
     49 #include "sigpipe.h"
     50 #include "vtls/vtls.h"
     51 #include "vtls/vtls_scache.h"
     52 #include "http_proxy.h"
     53 #include "http2.h"
     54 #include "socketpair.h"
     55 #include "socks.h"
     56 #include "urlapi-int.h"
     57 /* The last 3 #include files should be in this order */
     58 #include "curl_printf.h"
     59 #include "curl_memory.h"
     60 #include "memdebug.h"
     61 
     62 /* initial multi->xfers table size for a full multi */
     63 #define CURL_XFER_TABLE_SIZE    512
     64 
     65 /*
     66   CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
     67   to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
     68   curl handle takes 6K memory, therefore this 3K are not significant.
     69 */
     70 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
     71 #define CURL_SOCKET_HASH_TABLE_SIZE 911
     72 #endif
     73 
     74 #ifndef CURL_CONNECTION_HASH_SIZE
     75 #define CURL_CONNECTION_HASH_SIZE 97
     76 #endif
     77 
     78 #ifndef CURL_DNS_HASH_SIZE
     79 #define CURL_DNS_HASH_SIZE 71
     80 #endif
     81 
     82 #ifndef CURL_TLS_SESSION_SIZE
     83 #define CURL_TLS_SESSION_SIZE 25
     84 #endif
     85 
     86 #define CURL_MULTI_HANDLE 0x000bab1e
     87 
     88 #ifdef DEBUGBUILD
     89 /* On a debug build, we want to fail hard on multi handles that
     90  * are not NULL, but no longer have the MAGIC touch. This gives
     91  * us early warning on things only discovered by valgrind otherwise. */
     92 #define GOOD_MULTI_HANDLE(x) \
     93   (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE:      \
     94   (DEBUGASSERT(!(x)), FALSE))
     95 #else
     96 #define GOOD_MULTI_HANDLE(x) \
     97   ((x) && (x)->magic == CURL_MULTI_HANDLE)
     98 #endif
     99 
    100 static void move_pending_to_connect(struct Curl_multi *multi,
    101                                     struct Curl_easy *data);
    102 static CURLMcode add_next_timeout(struct curltime now,
    103                                   struct Curl_multi *multi,
    104                                   struct Curl_easy *d);
    105 static CURLMcode multi_timeout(struct Curl_multi *multi,
    106                                struct curltime *expire_time,
    107                                long *timeout_ms);
    108 static void process_pending_handles(struct Curl_multi *multi);
    109 static void multi_xfer_bufs_free(struct Curl_multi *multi);
    110 #ifdef DEBUGBUILD
    111 static void multi_xfer_tbl_dump(struct Curl_multi *multi);
    112 #endif
    113 
    114 /* function pointer called once when switching TO a state */
    115 typedef void (*init_multistate_func)(struct Curl_easy *data);
    116 
    117 /* called in DID state, before PERFORMING state */
    118 static void before_perform(struct Curl_easy *data)
    119 {
    120   data->req.chunk = FALSE;
    121   Curl_pgrsTime(data, TIMER_PRETRANSFER);
    122 }
    123 
    124 static void init_completed(struct Curl_easy *data)
    125 {
    126   /* this is a completed transfer */
    127 
    128   /* Important: reset the conn pointer so that we do not point to memory
    129      that could be freed anytime */
    130   Curl_detach_connection(data);
    131   Curl_expire_clear(data); /* stop all timers */
    132 }
    133 
    134 /* always use this function to change state, to make debugging easier */
    135 static void mstate(struct Curl_easy *data, CURLMstate state
    136 #ifdef DEBUGBUILD
    137                    , int lineno
    138 #endif
    139 )
    140 {
    141   CURLMstate oldstate = data->mstate;
    142   static const init_multistate_func finit[MSTATE_LAST] = {
    143     NULL,              /* INIT */
    144     NULL,              /* PENDING */
    145     NULL,              /* SETUP */
    146     Curl_init_CONNECT, /* CONNECT */
    147     NULL,              /* RESOLVING */
    148     NULL,              /* CONNECTING */
    149     NULL,              /* TUNNELING */
    150     NULL,              /* PROTOCONNECT */
    151     NULL,              /* PROTOCONNECTING */
    152     NULL,              /* DO */
    153     NULL,              /* DOING */
    154     NULL,              /* DOING_MORE */
    155     before_perform,    /* DID */
    156     NULL,              /* PERFORMING */
    157     NULL,              /* RATELIMITING */
    158     NULL,              /* DONE */
    159     init_completed,    /* COMPLETED */
    160     NULL               /* MSGSENT */
    161   };
    162 
    163   if(oldstate == state)
    164     /* do not bother when the new state is the same as the old state */
    165     return;
    166 
    167 #ifdef DEBUGBUILD
    168   CURL_TRC_M(data, "-> [%s] (line %d)", CURL_MSTATE_NAME(state), lineno);
    169 #else
    170   CURL_TRC_M(data, "-> [%s]", CURL_MSTATE_NAME(state));
    171 #endif
    172 
    173   data->mstate = state;
    174 
    175   if(state == MSTATE_COMPLETED) {
    176     /* changing to COMPLETED means it is in process and needs to go */
    177     DEBUGASSERT(Curl_uint_bset_contains(&data->multi->process, data->mid));
    178     Curl_uint_bset_remove(&data->multi->process, data->mid);
    179     Curl_uint_bset_remove(&data->multi->pending, data->mid); /* to be sure */
    180 
    181     if(Curl_uint_bset_empty(&data->multi->process)) {
    182       /* free the transfer buffer when we have no more active transfers */
    183       multi_xfer_bufs_free(data->multi);
    184     }
    185   }
    186 
    187   /* if this state has an init-function, run it */
    188   if(finit[state])
    189     finit[state](data);
    190 }
    191 
    192 #ifndef DEBUGBUILD
    193 #define multistate(x,y) mstate(x,y)
    194 #else
    195 #define multistate(x,y) mstate(x,y, __LINE__)
    196 #endif
    197 
    198 
    199 /* multi->proto_hash destructor. Should never be called as elements
    200  * MUST be added with their own destructor */
    201 static void ph_freeentry(void *p)
    202 {
    203   (void)p;
    204   /* Will always be FALSE. Cannot use a 0 assert here since compilers
    205    * are not in agreement if they then want a NORETURN attribute or
    206    * not. *sigh* */
    207   DEBUGASSERT(p == NULL);
    208 }
    209 
    210 /*
    211  * multi_addmsg()
    212  *
    213  * Called when a transfer is completed. Adds the given msg pointer to
    214  * the list kept in the multi handle.
    215  */
    216 static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
    217 {
    218   Curl_llist_append(&multi->msglist, msg, &msg->list);
    219 }
    220 
    221 struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size,
    222                                      size_t ev_hashsize,  /* event hash */
    223                                      size_t chashsize, /* connection hash */
    224                                      size_t dnssize,   /* dns hash */
    225                                      size_t sesssize)  /* TLS session cache */
    226 {
    227   struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
    228 
    229   if(!multi)
    230     return NULL;
    231 
    232   multi->magic = CURL_MULTI_HANDLE;
    233 
    234   Curl_dnscache_init(&multi->dnscache, dnssize);
    235   Curl_multi_ev_init(multi, ev_hashsize);
    236   Curl_uint_tbl_init(&multi->xfers, NULL);
    237   Curl_uint_bset_init(&multi->process);
    238   Curl_uint_bset_init(&multi->dirty);
    239   Curl_uint_bset_init(&multi->pending);
    240   Curl_uint_bset_init(&multi->msgsent);
    241   Curl_hash_init(&multi->proto_hash, 23,
    242                  Curl_hash_str, curlx_str_key_compare, ph_freeentry);
    243   Curl_llist_init(&multi->msglist, NULL);
    244 
    245   multi->multiplexing = TRUE;
    246   multi->max_concurrent_streams = 100;
    247   multi->last_timeout_ms = -1;
    248 
    249   if(Curl_uint_bset_resize(&multi->process, xfer_table_size) ||
    250      Curl_uint_bset_resize(&multi->pending, xfer_table_size) ||
    251      Curl_uint_bset_resize(&multi->dirty, xfer_table_size) ||
    252      Curl_uint_bset_resize(&multi->msgsent, xfer_table_size) ||
    253      Curl_uint_tbl_resize(&multi->xfers, xfer_table_size))
    254     goto error;
    255 
    256   multi->admin = curl_easy_init();
    257   if(!multi->admin)
    258     goto error;
    259   /* Initialize admin handle to operate inside this multi */
    260   multi->admin->multi = multi;
    261   multi->admin->state.internal = TRUE;
    262   Curl_llist_init(&multi->admin->state.timeoutlist, NULL);
    263 #ifdef DEBUGBUILD
    264   if(getenv("CURL_DEBUG"))
    265     multi->admin->set.verbose = TRUE;
    266 #endif
    267   Curl_uint_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid);
    268 
    269   if(Curl_cshutdn_init(&multi->cshutdn, multi))
    270     goto error;
    271 
    272   Curl_cpool_init(&multi->cpool, multi->admin, NULL, chashsize);
    273 
    274 #ifdef USE_SSL
    275   if(Curl_ssl_scache_create(sesssize, 2, &multi->ssl_scache))
    276     goto error;
    277 #else
    278   (void)sesssize;
    279 #endif
    280 
    281 #ifdef USE_WINSOCK
    282   multi->wsa_event = WSACreateEvent();
    283   if(multi->wsa_event == WSA_INVALID_EVENT)
    284     goto error;
    285 #elif defined(ENABLE_WAKEUP)
    286   if(wakeup_create(multi->wakeup_pair, TRUE) < 0) {
    287     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
    288     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
    289   }
    290 #endif
    291 
    292   return multi;
    293 
    294 error:
    295 
    296   Curl_multi_ev_cleanup(multi);
    297   Curl_hash_destroy(&multi->proto_hash);
    298   Curl_dnscache_destroy(&multi->dnscache);
    299   Curl_cpool_destroy(&multi->cpool);
    300   Curl_cshutdn_destroy(&multi->cshutdn, multi->admin);
    301 #ifdef USE_SSL
    302   Curl_ssl_scache_destroy(multi->ssl_scache);
    303 #endif
    304   if(multi->admin) {
    305     multi->admin->multi = NULL;
    306     Curl_close(&multi->admin);
    307   }
    308 
    309   Curl_uint_bset_destroy(&multi->process);
    310   Curl_uint_bset_destroy(&multi->dirty);
    311   Curl_uint_bset_destroy(&multi->pending);
    312   Curl_uint_bset_destroy(&multi->msgsent);
    313   Curl_uint_tbl_destroy(&multi->xfers);
    314 
    315   free(multi);
    316   return NULL;
    317 }
    318 
    319 CURLM *curl_multi_init(void)
    320 {
    321   return Curl_multi_handle(CURL_XFER_TABLE_SIZE,
    322                            CURL_SOCKET_HASH_TABLE_SIZE,
    323                            CURL_CONNECTION_HASH_SIZE,
    324                            CURL_DNS_HASH_SIZE,
    325                            CURL_TLS_SESSION_SIZE);
    326 }
    327 
    328 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
    329 static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
    330 {
    331   if(!multi->warned) {
    332     infof(data, "!!! WARNING !!!");
    333     infof(data, "This is a debug build of libcurl, "
    334           "do not use in production.");
    335     multi->warned = TRUE;
    336   }
    337 }
    338 #else
    339 #define multi_warn_debug(x,y) Curl_nop_stmt
    340 #endif
    341 
    342 
    343 static CURLMcode multi_xfers_add(struct Curl_multi *multi,
    344                                  struct Curl_easy *data)
    345 {
    346   unsigned int capacity = Curl_uint_tbl_capacity(&multi->xfers);
    347   unsigned int new_size = 0;
    348   /* Prepare to make this into a CURLMOPT_MAX_TRANSFERS, because some
    349    * applications may want to prevent a run-away of their memory use. */
    350   /* UINT_MAX is our "invalid" id, do not let the table grow up to that. */
    351   const unsigned int max_capacity = UINT_MAX - 1;
    352 
    353   if(capacity < max_capacity) {
    354     /* We want `multi->xfers` to have "sufficient" free rows, so that we do
    355      * have to reuse the `mid` from a just removed easy right away.
    356      * Since uint_tbl and uint_bset are quite memory efficient,
    357      * regard less than 25% free as insufficient.
    358      * (for low capacities, e.g. multi_easy, 4 or less). */
    359     unsigned int used = Curl_uint_tbl_count(&multi->xfers);
    360     unsigned int unused = capacity - used;
    361     unsigned int min_unused = CURLMAX(capacity >> 2, 4);
    362     if(unused <= min_unused) {
    363       /* Make sure the uint arithmetic here works on the corner
    364        * cases where we are close to max_capacity or UINT_MAX */
    365       if((min_unused >= max_capacity) ||
    366          ((max_capacity - min_unused) <= capacity) ||
    367          ((UINT_MAX - min_unused - 63) <= capacity)) {
    368         new_size = max_capacity; /* can not be larger than this */
    369       }
    370       else {
    371          /* make it a 64 multiple, since our bitsets frow by that and
    372           * small (easy_multi) grows to at least 64 on first resize. */
    373         new_size = (((used + min_unused) + 63) / 64) * 64;
    374       }
    375     }
    376   }
    377 
    378   if(new_size > capacity) {
    379     /* Grow the bitsets first. Should one fail, we do not need
    380      * to downsize the already resized ones. The sets continue
    381      * to work properly when larger than the table, but not
    382      * the other way around. */
    383     CURL_TRC_M(data, "increasing xfer table size to %u", new_size);
    384     if(Curl_uint_bset_resize(&multi->process, new_size) ||
    385        Curl_uint_bset_resize(&multi->dirty, new_size) ||
    386        Curl_uint_bset_resize(&multi->pending, new_size) ||
    387        Curl_uint_bset_resize(&multi->msgsent, new_size) ||
    388        Curl_uint_tbl_resize(&multi->xfers, new_size))
    389       return CURLM_OUT_OF_MEMORY;
    390   }
    391 
    392   /* Insert the easy into the table now */
    393   if(!Curl_uint_tbl_add(&multi->xfers, data, &data->mid)) {
    394     /* MUST only happen when table is full */
    395     DEBUGASSERT(Curl_uint_tbl_capacity(&multi->xfers) <=
    396                 Curl_uint_tbl_count(&multi->xfers));
    397     return CURLM_OUT_OF_MEMORY;
    398   }
    399   return CURLM_OK;
    400 }
    401 
    402 
    403 CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
    404 {
    405   CURLMcode rc;
    406   struct Curl_multi *multi = m;
    407   struct Curl_easy *data = d;
    408   /* First, make some basic checks that the CURLM handle is a good handle */
    409   if(!GOOD_MULTI_HANDLE(multi))
    410     return CURLM_BAD_HANDLE;
    411 
    412   /* Verify that we got a somewhat good easy handle too */
    413   if(!GOOD_EASY_HANDLE(data))
    414     return CURLM_BAD_EASY_HANDLE;
    415 
    416   /* Prevent users from adding same easy handle more than once and prevent
    417      adding to more than one multi stack */
    418   if(data->multi)
    419     return CURLM_ADDED_ALREADY;
    420 
    421   if(multi->in_callback)
    422     return CURLM_RECURSIVE_API_CALL;
    423 
    424   if(multi->dead) {
    425     /* a "dead" handle cannot get added transfers while any existing easy
    426        handles are still alive - but if there are none alive anymore, it is
    427        fine to start over and unmark the "deadness" of this handle.
    428        This means only the admin handle MUST be present. */
    429     if((Curl_uint_tbl_count(&multi->xfers) != 1) ||
    430        !Curl_uint_tbl_contains(&multi->xfers, 0))
    431       return CURLM_ABORTED_BY_CALLBACK;
    432     multi->dead = FALSE;
    433     Curl_uint_bset_clear(&multi->process);
    434     Curl_uint_bset_clear(&multi->dirty);
    435     Curl_uint_bset_clear(&multi->pending);
    436     Curl_uint_bset_clear(&multi->msgsent);
    437   }
    438 
    439   if(data->multi_easy) {
    440     /* if this easy handle was previously used for curl_easy_perform(), there
    441        is a private multi handle here that we can kill */
    442     curl_multi_cleanup(data->multi_easy);
    443     data->multi_easy = NULL;
    444   }
    445 
    446   /* Insert the easy into the multi->xfers table, assigning it a `mid`. */
    447   if(multi_xfers_add(multi, data))
    448     return CURLM_OUT_OF_MEMORY;
    449 
    450   /* Initialize timeout list for this handle */
    451   Curl_llist_init(&data->state.timeoutlist, NULL);
    452 
    453   /*
    454    * No failure allowed in this function beyond this point. No modification of
    455    * easy nor multi handle allowed before this except for potential multi's
    456    * connection pool growing which will not be undone in this function no
    457    * matter what.
    458    */
    459   if(data->set.errorbuffer)
    460     data->set.errorbuffer[0] = 0;
    461 
    462   data->state.os_errno = 0;
    463 
    464   /* make the Curl_easy refer back to this multi handle - before Curl_expire()
    465      is called. */
    466   data->multi = multi;
    467 
    468   /* Set the timeout for this handle to expire really soon so that it will
    469      be taken care of even when this handle is added in the midst of operation
    470      when only the curl_multi_socket() API is used. During that flow, only
    471      sockets that time-out or have actions will be dealt with. Since this
    472      handle has no action yet, we make sure it times out to get things to
    473      happen. */
    474   Curl_expire(data, 0, EXPIRE_RUN_NOW);
    475 
    476   rc = Curl_update_timer(multi);
    477   if(rc) {
    478     data->multi = NULL; /* not anymore */
    479     Curl_uint_tbl_remove(&multi->xfers, data->mid);
    480     data->mid = UINT_MAX;
    481     return rc;
    482   }
    483 
    484   /* set the easy handle */
    485   multistate(data, MSTATE_INIT);
    486 
    487 #ifdef USE_LIBPSL
    488   /* Do the same for PSL. */
    489   if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
    490     data->psl = &data->share->psl;
    491   else
    492     data->psl = &multi->psl;
    493 #endif
    494 
    495   /* add the easy handle to the process set */
    496   Curl_uint_bset_add(&multi->process, data->mid);
    497   ++multi->xfers_alive;
    498 
    499   Curl_cpool_xfer_init(data);
    500   multi_warn_debug(multi, data);
    501 
    502   /* The admin handle only ever has default timeouts set. To improve the
    503      state somewhat we clone the timeouts from each added handle so that the
    504      admin handle always has the same timeouts as the most recently added
    505      easy handle. */
    506   multi->admin->set.timeout = data->set.timeout;
    507   multi->admin->set.server_response_timeout =
    508     data->set.server_response_timeout;
    509   multi->admin->set.no_signal = data->set.no_signal;
    510 
    511   CURL_TRC_M(data, "added to multi, mid=%u, running=%u, total=%u",
    512              data->mid, Curl_multi_xfers_running(multi),
    513              Curl_uint_tbl_count(&multi->xfers));
    514   return CURLM_OK;
    515 }
    516 
    517 #if 0
    518 /* Debug-function, used like this:
    519  *
    520  * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
    521  *
    522  * Enable the hash print function first by editing hash.c
    523  */
    524 static void debug_print_sock_hash(void *p)
    525 {
    526   struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
    527 
    528   fprintf(stderr, " [readers %u][writers %u]",
    529           sh->readers, sh->writers);
    530 }
    531 #endif
    532 
    533 struct multi_done_ctx {
    534   BIT(premature);
    535 };
    536 
    537 static void multi_done_locked(struct connectdata *conn,
    538                               struct Curl_easy *data,
    539                               void *userdata)
    540 {
    541   struct multi_done_ctx *mdctx = userdata;
    542 
    543   Curl_detach_connection(data);
    544 
    545   CURL_TRC_M(data, "multi_done_locked, in use=%u",
    546              Curl_uint_spbset_count(&conn->xfers_attached));
    547   if(CONN_INUSE(conn)) {
    548     /* Stop if still used. */
    549     CURL_TRC_M(data, "Connection still in use %u, no more multi_done now!",
    550                Curl_uint_spbset_count(&conn->xfers_attached));
    551     return;
    552   }
    553 
    554   data->state.done = TRUE; /* called just now! */
    555   data->state.recent_conn_id = conn->connection_id;
    556 
    557   Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */
    558   Curl_resolv_unlink(data, &data->state.dns[1]);
    559   Curl_dnscache_prune(data);
    560 
    561   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
    562      forced us to close this connection. This is ignored for requests taking
    563      place in a NTLM/NEGOTIATE authentication handshake
    564 
    565      if conn->bits.close is TRUE, it means that the connection should be
    566      closed in spite of all our efforts to be nice, due to protocol
    567      restrictions in our or the server's end
    568 
    569      if premature is TRUE, it means this connection was said to be DONE before
    570      the entire request operation is complete and thus we cannot know in what
    571      state it is for reusing, so we are forced to close it. In a perfect world
    572      we can add code that keep track of if we really must close it here or not,
    573      but currently we have no such detail knowledge.
    574   */
    575 
    576   if((data->set.reuse_forbid
    577 #if defined(USE_NTLM)
    578       && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
    579            conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
    580 #endif
    581 #if defined(USE_SPNEGO)
    582       && !(conn->http_negotiate_state == GSS_AUTHRECV ||
    583            conn->proxy_negotiate_state == GSS_AUTHRECV)
    584 #endif
    585      ) || conn->bits.close
    586        || (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
    587     CURL_TRC_M(data, "multi_done, not reusing connection=%"
    588                      FMT_OFF_T ", forbid=%d"
    589                      ", close=%d, premature=%d, conn_multiplex=%d",
    590                      conn->connection_id, data->set.reuse_forbid,
    591                      conn->bits.close, mdctx->premature,
    592                      Curl_conn_is_multiplex(conn, FIRSTSOCKET));
    593     connclose(conn, "disconnecting");
    594     Curl_conn_terminate(data, conn, mdctx->premature);
    595   }
    596   else {
    597     /* the connection is no longer in use by any transfer */
    598     if(Curl_cpool_conn_now_idle(data, conn)) {
    599       /* connection kept in the cpool */
    600       const char *host =
    601 #ifndef CURL_DISABLE_PROXY
    602         conn->bits.socksproxy ?
    603         conn->socks_proxy.host.dispname :
    604         conn->bits.httpproxy ? conn->http_proxy.host.dispname :
    605 #endif
    606         conn->bits.conn_to_host ? conn->conn_to_host.dispname :
    607         conn->host.dispname;
    608       data->state.lastconnect_id = conn->connection_id;
    609       infof(data, "Connection #%" FMT_OFF_T " to host %s left intact",
    610             conn->connection_id, host);
    611     }
    612     else {
    613       /* connection was removed from the cpool and destroyed. */
    614       data->state.lastconnect_id = -1;
    615     }
    616   }
    617 }
    618 
    619 static CURLcode multi_done(struct Curl_easy *data,
    620                            CURLcode status,  /* an error if this is called
    621                                                 after an error was detected */
    622                            bool premature)
    623 {
    624   CURLcode result;
    625   struct connectdata *conn = data->conn;
    626   struct multi_done_ctx mdctx;
    627 
    628   memset(&mdctx, 0, sizeof(mdctx));
    629 
    630   CURL_TRC_M(data, "multi_done: status: %d prem: %d done: %d",
    631              (int)status, (int)premature, data->state.done);
    632 
    633   if(data->state.done)
    634     /* Stop if multi_done() has already been called */
    635     return CURLE_OK;
    636 
    637   /* Shut down any ongoing async resolver operation. */
    638   Curl_async_shutdown(data);
    639 
    640   /* Cleanup possible redirect junk */
    641   Curl_safefree(data->req.newurl);
    642   Curl_safefree(data->req.location);
    643 
    644   switch(status) {
    645   case CURLE_ABORTED_BY_CALLBACK:
    646   case CURLE_READ_ERROR:
    647   case CURLE_WRITE_ERROR:
    648     /* When we are aborted due to a callback return code it basically have to
    649        be counted as premature as there is trouble ahead if we do not. We have
    650        many callbacks and protocols work differently, we could potentially do
    651        this more fine-grained in the future. */
    652     premature = TRUE;
    653     FALLTHROUGH();
    654   default:
    655     break;
    656   }
    657 
    658   /* this calls the protocol-specific function pointer previously set */
    659   if(conn->handler->done && (data->mstate >= MSTATE_PROTOCONNECT))
    660     result = conn->handler->done(data, status, premature);
    661   else
    662     result = status;
    663 
    664   if(CURLE_ABORTED_BY_CALLBACK != result) {
    665     /* avoid this if we already aborted by callback to avoid this calling
    666        another callback */
    667     int rc = Curl_pgrsDone(data);
    668     if(!result && rc)
    669       result = CURLE_ABORTED_BY_CALLBACK;
    670   }
    671 
    672   /* Make sure that transfer client writes are really done now. */
    673   result = Curl_1st_err(result, Curl_xfer_write_done(data, premature));
    674 
    675   /* Inform connection filters that this transfer is done */
    676   Curl_conn_ev_data_done(data, premature);
    677 
    678   process_pending_handles(data->multi); /* connection / multiplex */
    679 
    680   if(!result)
    681     result = Curl_req_done(&data->req, data, premature);
    682 
    683   /* Under the potential connection pool's share lock, decide what to
    684    * do with the transfer's connection. */
    685   mdctx.premature = premature;
    686   Curl_cpool_do_locked(data, data->conn, multi_done_locked, &mdctx);
    687 
    688   /* flush the netrc cache */
    689   Curl_netrc_cleanup(&data->state.netrc);
    690   return result;
    691 }
    692 
    693 static void close_connect_only(struct connectdata *conn,
    694                                struct Curl_easy *data,
    695                                void *userdata)
    696 {
    697   (void)userdata;
    698   (void)data;
    699   if(conn->connect_only)
    700     connclose(conn, "Removing connect-only easy handle");
    701 }
    702 
    703 CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
    704 {
    705   struct Curl_multi *multi = m;
    706   struct Curl_easy *data = d;
    707   bool premature;
    708   struct Curl_llist_node *e;
    709   CURLMcode rc;
    710   bool removed_timer = FALSE;
    711   unsigned int mid;
    712 
    713   /* First, make some basic checks that the CURLM handle is a good handle */
    714   if(!GOOD_MULTI_HANDLE(multi))
    715     return CURLM_BAD_HANDLE;
    716 
    717   /* Verify that we got a somewhat good easy handle too */
    718   if(!GOOD_EASY_HANDLE(data))
    719     return CURLM_BAD_EASY_HANDLE;
    720 
    721   /* Prevent users from trying to remove same easy handle more than once */
    722   if(!data->multi)
    723     return CURLM_OK; /* it is already removed so let's say it is fine! */
    724 
    725   /* Prevent users from trying to remove an easy handle from the wrong multi */
    726   if(data->multi != multi)
    727     return CURLM_BAD_EASY_HANDLE;
    728 
    729   if(data->mid == UINT_MAX) {
    730     DEBUGASSERT(0);
    731     return CURLM_INTERNAL_ERROR;
    732   }
    733   if(Curl_uint_tbl_get(&multi->xfers, data->mid) != data) {
    734     DEBUGASSERT(0);
    735     return CURLM_INTERNAL_ERROR;
    736   }
    737 
    738   if(multi->in_callback)
    739     return CURLM_RECURSIVE_API_CALL;
    740 
    741   premature = (data->mstate < MSTATE_COMPLETED);
    742 
    743   /* If the 'state' is not INIT or COMPLETED, we might need to do something
    744      nice to put the easy_handle in a good known state when this returns. */
    745   if(data->conn &&
    746      data->mstate > MSTATE_DO &&
    747      data->mstate < MSTATE_COMPLETED) {
    748     /* Set connection owner so that the DONE function closes it. We can
    749        safely do this here since connection is killed. */
    750     streamclose(data->conn, "Removed with partial response");
    751   }
    752 
    753   if(data->conn) {
    754     /* multi_done() clears the association between the easy handle and the
    755        connection.
    756 
    757        Note that this ignores the return code simply because there is
    758        nothing really useful to do with it anyway! */
    759     (void)multi_done(data, data->result, premature);
    760   }
    761 
    762   /* The timer must be shut down before data->multi is set to NULL, else the
    763      timenode will remain in the splay tree after curl_easy_cleanup is
    764      called. Do it after multi_done() in case that sets another time! */
    765   removed_timer = Curl_expire_clear(data);
    766 
    767   /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */
    768   if(!Curl_uint_bset_contains(&multi->msgsent, data->mid))
    769     --multi->xfers_alive;
    770 
    771   Curl_wildcard_dtor(&data->wildcard);
    772 
    773   data->mstate = MSTATE_COMPLETED;
    774 
    775   /* Remove the association between the connection and the handle */
    776   Curl_detach_connection(data);
    777 
    778   /* Tell event handling that this transfer is definitely going away */
    779   Curl_multi_ev_xfer_done(multi, data);
    780 
    781   if(data->set.connect_only && !data->multi_easy) {
    782     /* This removes a handle that was part the multi interface that used
    783        CONNECT_ONLY, that connection is now left alive but since this handle
    784        has bits.close set nothing can use that transfer anymore and it is
    785        forbidden from reuse. This easy handle cannot find the connection
    786        anymore once removed from the multi handle
    787 
    788        Better close the connection here, at once.
    789     */
    790     struct connectdata *c;
    791     curl_socket_t s;
    792     s = Curl_getconnectinfo(data, &c);
    793     if((s != CURL_SOCKET_BAD) && c) {
    794       Curl_conn_terminate(data, c, TRUE);
    795     }
    796   }
    797 
    798   if(data->state.lastconnect_id != -1) {
    799     /* Mark any connect-only connection for closure */
    800     Curl_cpool_do_by_id(data, data->state.lastconnect_id,
    801                             close_connect_only, NULL);
    802   }
    803 
    804 #ifdef USE_LIBPSL
    805   /* Remove the PSL association. */
    806   if(data->psl == &multi->psl)
    807     data->psl = NULL;
    808 #endif
    809 
    810   /* make sure there is no pending message in the queue sent from this easy
    811      handle */
    812   for(e = Curl_llist_head(&multi->msglist); e; e = Curl_node_next(e)) {
    813     struct Curl_message *msg = Curl_node_elem(e);
    814 
    815     if(msg->extmsg.easy_handle == data) {
    816       Curl_node_remove(e);
    817       /* there can only be one from this specific handle */
    818       break;
    819     }
    820   }
    821 
    822   /* clear the association to this multi handle */
    823   mid = data->mid;
    824   DEBUGASSERT(Curl_uint_tbl_contains(&multi->xfers, mid));
    825   Curl_uint_tbl_remove(&multi->xfers, mid);
    826   Curl_uint_bset_remove(&multi->process, mid);
    827   Curl_uint_bset_remove(&multi->dirty, mid);
    828   Curl_uint_bset_remove(&multi->pending, mid);
    829   Curl_uint_bset_remove(&multi->msgsent, mid);
    830   data->multi = NULL;
    831   data->mid = UINT_MAX;
    832   data->master_mid = UINT_MAX;
    833 
    834   /* NOTE NOTE NOTE
    835      We do not touch the easy handle here! */
    836   process_pending_handles(multi);
    837 
    838   if(removed_timer) {
    839     rc = Curl_update_timer(multi);
    840     if(rc)
    841       return rc;
    842   }
    843 
    844   CURL_TRC_M(data, "removed from multi, mid=%u, running=%u, total=%u",
    845              mid, Curl_multi_xfers_running(multi),
    846              Curl_uint_tbl_count(&multi->xfers));
    847   return CURLM_OK;
    848 }
    849 
    850 /* Return TRUE if the application asked for multiplexing */
    851 bool Curl_multiplex_wanted(const struct Curl_multi *multi)
    852 {
    853   return multi && multi->multiplexing;
    854 }
    855 
    856 /*
    857  * Curl_detach_connection() removes the given transfer from the connection.
    858  *
    859  * This is the only function that should clear data->conn. This will
    860  * occasionally be called with the data->conn pointer already cleared.
    861  */
    862 void Curl_detach_connection(struct Curl_easy *data)
    863 {
    864   struct connectdata *conn = data->conn;
    865   if(conn) {
    866     Curl_uint_spbset_remove(&conn->xfers_attached, data->mid);
    867     if(Curl_uint_spbset_empty(&conn->xfers_attached))
    868       conn->attached_multi = NULL;
    869   }
    870   data->conn = NULL;
    871 }
    872 
    873 /*
    874  * Curl_attach_connection() attaches this transfer to this connection.
    875  *
    876  * This is the only function that should assign data->conn
    877  */
    878 void Curl_attach_connection(struct Curl_easy *data,
    879                             struct connectdata *conn)
    880 {
    881   DEBUGASSERT(data);
    882   DEBUGASSERT(!data->conn);
    883   DEBUGASSERT(conn);
    884   data->conn = conn;
    885   Curl_uint_spbset_add(&conn->xfers_attached, data->mid);
    886   /* all attached transfers must be from the same multi */
    887   if(!conn->attached_multi)
    888     conn->attached_multi = data->multi;
    889   DEBUGASSERT(conn->attached_multi == data->multi);
    890 
    891   if(conn->handler && conn->handler->attach)
    892     conn->handler->attach(data, conn);
    893 }
    894 
    895 static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
    896 {
    897   struct connectdata *conn = data->conn;
    898   curl_socket_t sockfd;
    899 
    900   if(!conn)
    901     return GETSOCK_BLANK;
    902   sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
    903   if(sockfd != CURL_SOCKET_BAD) {
    904     /* Default is to wait to something from the server */
    905     socks[0] = sockfd;
    906     return GETSOCK_READSOCK(0);
    907   }
    908   return GETSOCK_BLANK;
    909 }
    910 
    911 static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
    912 {
    913   struct connectdata *conn = data->conn;
    914   curl_socket_t sockfd;
    915 
    916   if(!conn)
    917     return GETSOCK_BLANK;
    918   if(conn->handler->proto_getsock)
    919     return conn->handler->proto_getsock(data, conn, socks);
    920   sockfd = Curl_conn_get_socket(data, FIRSTSOCKET);
    921   if(sockfd != CURL_SOCKET_BAD) {
    922     /* Default is to wait to something from the server */
    923     socks[0] = sockfd;
    924     return GETSOCK_READSOCK(0);
    925   }
    926   return GETSOCK_BLANK;
    927 }
    928 
    929 static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
    930 {
    931   struct connectdata *conn = data->conn;
    932   if(!conn)
    933     return GETSOCK_BLANK;
    934   if(conn->handler->domore_getsock)
    935     return conn->handler->domore_getsock(data, conn, socks);
    936   else if(conn->sockfd != CURL_SOCKET_BAD) {
    937     /* Default is that we want to send something to the server */
    938     socks[0] = conn->sockfd;
    939     return GETSOCK_WRITESOCK(0);
    940   }
    941   return GETSOCK_BLANK;
    942 }
    943 
    944 static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
    945 {
    946   struct connectdata *conn = data->conn;
    947   if(!conn)
    948     return GETSOCK_BLANK;
    949   if(conn->handler->doing_getsock)
    950     return conn->handler->doing_getsock(data, conn, socks);
    951   else if(conn->sockfd != CURL_SOCKET_BAD) {
    952     /* Default is that we want to send something to the server */
    953     socks[0] = conn->sockfd;
    954     return GETSOCK_WRITESOCK(0);
    955   }
    956   return GETSOCK_BLANK;
    957 }
    958 
    959 static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
    960 {
    961   struct connectdata *conn = data->conn;
    962   if(!conn)
    963     return GETSOCK_BLANK;
    964   else if(conn->handler->perform_getsock)
    965     return conn->handler->perform_getsock(data, conn, sock);
    966   else {
    967     /* Default is to obey the data->req.keepon flags for send/recv */
    968     int bitmap = GETSOCK_BLANK;
    969     unsigned sockindex = 0;
    970     if(CURL_WANT_RECV(data)) {
    971       DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
    972       bitmap |= GETSOCK_READSOCK(sockindex);
    973       sock[sockindex] = conn->sockfd;
    974     }
    975 
    976     if(Curl_req_want_send(data)) {
    977       if((conn->sockfd != conn->writesockfd) ||
    978          bitmap == GETSOCK_BLANK) {
    979         /* only if they are not the same socket and we have a readable
    980            one, we increase index */
    981         if(bitmap != GETSOCK_BLANK)
    982           sockindex++; /* increase index if we need two entries */
    983 
    984         DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
    985         sock[sockindex] = conn->writesockfd;
    986       }
    987       bitmap |= GETSOCK_WRITESOCK(sockindex);
    988     }
    989     return bitmap;
    990   }
    991 }
    992 
    993 /* Initializes `poll_set` with the current socket poll actions needed
    994  * for transfer `data`. */
    995 void Curl_multi_getsock(struct Curl_easy *data,
    996                         struct easy_pollset *ps,
    997                         const char *caller)
    998 {
    999   bool expect_sockets = TRUE;
   1000 
   1001   /* If the transfer has no connection, this is fine. Happens when
   1002      called via curl_multi_remove_handle() => Curl_multi_ev_assess() =>
   1003      Curl_multi_getsock(). */
   1004   Curl_pollset_reset(data, ps);
   1005   if(!data->conn)
   1006     return;
   1007 
   1008   switch(data->mstate) {
   1009   case MSTATE_INIT:
   1010   case MSTATE_PENDING:
   1011   case MSTATE_SETUP:
   1012   case MSTATE_CONNECT:
   1013     /* nothing to poll for yet */
   1014     expect_sockets = FALSE;
   1015     break;
   1016 
   1017   case MSTATE_RESOLVING:
   1018     Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
   1019     /* connection filters are not involved in this phase. It's ok if we get no
   1020      * sockets to wait for. Resolving can wake up from other sources. */
   1021     expect_sockets = FALSE;
   1022     break;
   1023 
   1024   case MSTATE_CONNECTING:
   1025   case MSTATE_TUNNELING:
   1026     Curl_pollset_add_socks(data, ps, connecting_getsock);
   1027     Curl_conn_adjust_pollset(data, data->conn, ps);
   1028     break;
   1029 
   1030   case MSTATE_PROTOCONNECT:
   1031   case MSTATE_PROTOCONNECTING:
   1032     Curl_pollset_add_socks(data, ps, protocol_getsock);
   1033     Curl_conn_adjust_pollset(data, data->conn, ps);
   1034     break;
   1035 
   1036   case MSTATE_DO:
   1037   case MSTATE_DOING:
   1038     Curl_pollset_add_socks(data, ps, doing_getsock);
   1039     Curl_conn_adjust_pollset(data, data->conn, ps);
   1040     break;
   1041 
   1042   case MSTATE_DOING_MORE:
   1043     Curl_pollset_add_socks(data, ps, domore_getsock);
   1044     Curl_conn_adjust_pollset(data, data->conn, ps);
   1045     break;
   1046 
   1047   case MSTATE_DID: /* same as PERFORMING in regard to polling */
   1048   case MSTATE_PERFORMING:
   1049     Curl_pollset_add_socks(data, ps, perform_getsock);
   1050     Curl_conn_adjust_pollset(data, data->conn, ps);
   1051     break;
   1052 
   1053   case MSTATE_RATELIMITING:
   1054     /* we need to let time pass, ignore socket(s) */
   1055     expect_sockets = FALSE;
   1056     break;
   1057 
   1058   case MSTATE_DONE:
   1059   case MSTATE_COMPLETED:
   1060   case MSTATE_MSGSENT:
   1061     /* nothing more to poll for */
   1062     expect_sockets = FALSE;
   1063     break;
   1064 
   1065   default:
   1066     failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
   1067     DEBUGASSERT(0);
   1068     expect_sockets = FALSE;
   1069     break;
   1070   }
   1071 
   1072 
   1073   /* Unblocked and waiting to receive with buffered input.
   1074    * Make transfer run again at next opportunity. */
   1075   if(!Curl_xfer_is_blocked(data) &&
   1076      ((Curl_pollset_want_read(data, ps, data->conn->sock[FIRSTSOCKET]) &&
   1077        Curl_conn_data_pending(data, FIRSTSOCKET)) ||
   1078       (Curl_pollset_want_read(data, ps, data->conn->sock[SECONDARYSOCKET]) &&
   1079        Curl_conn_data_pending(data, SECONDARYSOCKET)))) {
   1080     CURL_TRC_M(data, "%s pollset[] has POLLIN, but there is still "
   1081                "buffered input to consume -> mark as dirty", caller);
   1082     Curl_multi_mark_dirty(data);
   1083   }
   1084 
   1085   switch(ps->num) {
   1086     case 0:
   1087       CURL_TRC_M(data, "%s pollset[], timeouts=%zu, paused %d/%d (r/w)",
   1088                  caller, Curl_llist_count(&data->state.timeoutlist),
   1089                  Curl_xfer_send_is_paused(data),
   1090                  Curl_xfer_recv_is_paused(data));
   1091       break;
   1092     case 1:
   1093       CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu",
   1094                  caller, ps->sockets[0],
   1095                  (ps->actions[0] & CURL_POLL_IN) ? "IN" : "",
   1096                  (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "",
   1097                  Curl_llist_count(&data->state.timeoutlist));
   1098       break;
   1099     case 2:
   1100       CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s, "
   1101                  "fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu",
   1102                  caller, ps->sockets[0],
   1103                  (ps->actions[0] & CURL_POLL_IN) ? "IN" : "",
   1104                  (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "",
   1105                  ps->sockets[1],
   1106                  (ps->actions[1] & CURL_POLL_IN) ? "IN" : "",
   1107                  (ps->actions[1] & CURL_POLL_OUT) ? "OUT" : "",
   1108                  Curl_llist_count(&data->state.timeoutlist));
   1109       break;
   1110     default:
   1111       CURL_TRC_M(data, "%s pollset[fds=%u], timeouts=%zu",
   1112                  caller, ps->num, Curl_llist_count(&data->state.timeoutlist));
   1113       break;
   1114   }
   1115   if(expect_sockets && !ps->num &&
   1116      !Curl_llist_count(&data->state.timeoutlist) &&
   1117      !Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) &&
   1118      Curl_conn_is_ip_connected(data, FIRSTSOCKET)) {
   1119     /* We expected sockets for POLL monitoring, but none are set.
   1120      * We are not waiting on any timer.
   1121      * None of the READ/WRITE directions are paused.
   1122      * We are connected to the server on IP level, at least. */
   1123     infof(data, "WARNING: no socket in pollset or timer, transfer may stall!");
   1124     DEBUGASSERT(0);
   1125   }
   1126 }
   1127 
   1128 CURLMcode curl_multi_fdset(CURLM *m,
   1129                            fd_set *read_fd_set, fd_set *write_fd_set,
   1130                            fd_set *exc_fd_set, int *max_fd)
   1131 {
   1132   /* Scan through all the easy handles to get the file descriptors set.
   1133      Some easy handles may not have connected to the remote host yet,
   1134      and then we must make sure that is done. */
   1135   int this_max_fd = -1;
   1136   struct Curl_multi *multi = m;
   1137   unsigned int i, mid;
   1138   (void)exc_fd_set; /* not used */
   1139 
   1140   if(!GOOD_MULTI_HANDLE(multi))
   1141     return CURLM_BAD_HANDLE;
   1142 
   1143   if(multi->in_callback)
   1144     return CURLM_RECURSIVE_API_CALL;
   1145 
   1146   if(Curl_uint_bset_first(&multi->process, &mid)) {
   1147     do {
   1148       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   1149       struct easy_pollset ps;
   1150 
   1151       if(!data) {
   1152         DEBUGASSERT(0);
   1153         continue;
   1154       }
   1155 
   1156       Curl_multi_getsock(data, &ps, "curl_multi_fdset");
   1157       for(i = 0; i < ps.num; i++) {
   1158         if(!FDSET_SOCK(ps.sockets[i]))
   1159           /* pretend it does not exist */
   1160           continue;
   1161 #if defined(__DJGPP__)
   1162 #pragma GCC diagnostic push
   1163 #pragma GCC diagnostic ignored "-Warith-conversion"
   1164 #endif
   1165         if(ps.actions[i] & CURL_POLL_IN)
   1166           FD_SET(ps.sockets[i], read_fd_set);
   1167         if(ps.actions[i] & CURL_POLL_OUT)
   1168           FD_SET(ps.sockets[i], write_fd_set);
   1169 #if defined(__DJGPP__)
   1170 #pragma GCC diagnostic pop
   1171 #endif
   1172         if((int)ps.sockets[i] > this_max_fd)
   1173           this_max_fd = (int)ps.sockets[i];
   1174       }
   1175     }
   1176     while(Curl_uint_bset_next(&multi->process, mid, &mid));
   1177   }
   1178 
   1179   Curl_cshutdn_setfds(&multi->cshutdn, multi->admin,
   1180                       read_fd_set, write_fd_set, &this_max_fd);
   1181 
   1182   *max_fd = this_max_fd;
   1183 
   1184   return CURLM_OK;
   1185 }
   1186 
   1187 CURLMcode curl_multi_waitfds(CURLM *m,
   1188                              struct curl_waitfd *ufds,
   1189                              unsigned int size,
   1190                              unsigned int *fd_count)
   1191 {
   1192   struct Curl_waitfds cwfds;
   1193   CURLMcode result = CURLM_OK;
   1194   struct Curl_multi *multi = m;
   1195   unsigned int need = 0, mid;
   1196 
   1197   if(!ufds && (size || !fd_count))
   1198     return CURLM_BAD_FUNCTION_ARGUMENT;
   1199 
   1200   if(!GOOD_MULTI_HANDLE(multi))
   1201     return CURLM_BAD_HANDLE;
   1202 
   1203   if(multi->in_callback)
   1204     return CURLM_RECURSIVE_API_CALL;
   1205 
   1206   Curl_waitfds_init(&cwfds, ufds, size);
   1207   if(Curl_uint_bset_first(&multi->process, &mid)) {
   1208     do {
   1209       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   1210       struct easy_pollset ps;
   1211       if(!data) {
   1212         DEBUGASSERT(0);
   1213         Curl_uint_bset_remove(&multi->process, mid);
   1214         Curl_uint_bset_remove(&multi->dirty, mid);
   1215         continue;
   1216       }
   1217       Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
   1218       need += Curl_waitfds_add_ps(&cwfds, &ps);
   1219     }
   1220     while(Curl_uint_bset_next(&multi->process, mid, &mid));
   1221   }
   1222 
   1223   need += Curl_cshutdn_add_waitfds(&multi->cshutdn, multi->admin, &cwfds);
   1224 
   1225   if(need != cwfds.n && ufds) {
   1226     result = CURLM_OUT_OF_MEMORY;
   1227   }
   1228 
   1229   if(fd_count)
   1230     *fd_count = need;
   1231   return result;
   1232 }
   1233 
   1234 #ifdef USE_WINSOCK
   1235 /* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets cannot
   1236  * be reset this way because an empty datagram would be sent. #9203
   1237  *
   1238  * "On Windows the internal state of FD_WRITE as returned from
   1239  * WSAEnumNetworkEvents is only reset after successful send()."
   1240  */
   1241 static void reset_socket_fdwrite(curl_socket_t s)
   1242 {
   1243   int t;
   1244   int l = (int)sizeof(t);
   1245   if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
   1246     send(s, NULL, 0, 0);
   1247 }
   1248 #endif
   1249 
   1250 #define NUM_POLLS_ON_STACK 10
   1251 
   1252 static CURLMcode multi_wait(struct Curl_multi *multi,
   1253                             struct curl_waitfd extra_fds[],
   1254                             unsigned int extra_nfds,
   1255                             int timeout_ms,
   1256                             int *ret,
   1257                             bool extrawait, /* when no socket, wait */
   1258                             bool use_wakeup)
   1259 {
   1260   size_t i;
   1261   struct curltime expire_time;
   1262   long timeout_internal;
   1263   int retcode = 0;
   1264   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   1265   struct curl_pollfds cpfds;
   1266   unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
   1267   struct Curl_easy *data = NULL;
   1268   CURLMcode result = CURLM_OK;
   1269   unsigned int mid;
   1270 
   1271 #ifdef USE_WINSOCK
   1272   WSANETWORKEVENTS wsa_events;
   1273   DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
   1274 #endif
   1275 #ifndef ENABLE_WAKEUP
   1276   (void)use_wakeup;
   1277 #endif
   1278 
   1279   if(!GOOD_MULTI_HANDLE(multi))
   1280     return CURLM_BAD_HANDLE;
   1281 
   1282   if(multi->in_callback)
   1283     return CURLM_RECURSIVE_API_CALL;
   1284 
   1285   if(timeout_ms < 0)
   1286     return CURLM_BAD_FUNCTION_ARGUMENT;
   1287 
   1288   Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
   1289 
   1290   /* Add the curl handles to our pollfds first */
   1291   if(Curl_uint_bset_first(&multi->process, &mid)) {
   1292     do {
   1293       struct easy_pollset ps;
   1294       data = Curl_multi_get_easy(multi, mid);
   1295       if(!data) {
   1296         DEBUGASSERT(0);
   1297         Curl_uint_bset_remove(&multi->process, mid);
   1298         Curl_uint_bset_remove(&multi->dirty, mid);
   1299         continue;
   1300       }
   1301       Curl_multi_getsock(data, &ps, "multi_wait");
   1302       if(Curl_pollfds_add_ps(&cpfds, &ps)) {
   1303         result = CURLM_OUT_OF_MEMORY;
   1304         goto out;
   1305       }
   1306     }
   1307     while(Curl_uint_bset_next(&multi->process, mid, &mid));
   1308   }
   1309 
   1310   if(Curl_cshutdn_add_pollfds(&multi->cshutdn, multi->admin, &cpfds)) {
   1311     result = CURLM_OUT_OF_MEMORY;
   1312     goto out;
   1313   }
   1314 
   1315   curl_nfds = cpfds.n; /* what curl internally uses in cpfds */
   1316   /* Add external file descriptions from poll-like struct curl_waitfd */
   1317   for(i = 0; i < extra_nfds; i++) {
   1318     unsigned short events = 0;
   1319     if(extra_fds[i].events & CURL_WAIT_POLLIN)
   1320       events |= POLLIN;
   1321     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
   1322       events |= POLLPRI;
   1323     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
   1324       events |= POLLOUT;
   1325     if(Curl_pollfds_add_sock(&cpfds, extra_fds[i].fd, events)) {
   1326       result = CURLM_OUT_OF_MEMORY;
   1327       goto out;
   1328     }
   1329   }
   1330 
   1331 #ifdef USE_WINSOCK
   1332   /* Set the WSA events based on the collected pollds */
   1333   for(i = 0; i < cpfds.n; i++) {
   1334     long mask = 0;
   1335     if(cpfds.pfds[i].events & POLLIN)
   1336       mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
   1337     if(cpfds.pfds[i].events & POLLPRI)
   1338       mask |= FD_OOB;
   1339     if(cpfds.pfds[i].events & POLLOUT) {
   1340       mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
   1341       reset_socket_fdwrite(cpfds.pfds[i].fd);
   1342     }
   1343     if(mask) {
   1344       if(WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, mask) != 0) {
   1345         result = CURLM_OUT_OF_MEMORY;
   1346         goto out;
   1347       }
   1348     }
   1349   }
   1350 #endif
   1351 
   1352 #ifdef ENABLE_WAKEUP
   1353 #ifndef USE_WINSOCK
   1354   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
   1355     if(Curl_pollfds_add_sock(&cpfds, multi->wakeup_pair[0], POLLIN)) {
   1356       result = CURLM_OUT_OF_MEMORY;
   1357       goto out;
   1358     }
   1359   }
   1360 #endif
   1361 #endif
   1362 
   1363   /* We check the internal timeout *AFTER* we collected all sockets to
   1364    * poll. Collecting the sockets may install new timers by protocols
   1365    * and connection filters.
   1366    * Use the shorter one of the internal and the caller requested timeout. */
   1367   (void)multi_timeout(multi, &expire_time, &timeout_internal);
   1368   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
   1369     timeout_ms = (int)timeout_internal;
   1370 
   1371   if(data)
   1372     CURL_TRC_M(data, "multi_wait(fds=%d, timeout=%d) tinternal=%ld",
   1373                cpfds.n, timeout_ms, timeout_internal);
   1374 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
   1375   if(cpfds.n || use_wakeup) {
   1376 #else
   1377   if(cpfds.n) {
   1378 #endif
   1379     int pollrc;
   1380 #ifdef USE_WINSOCK
   1381     if(cpfds.n)         /* just pre-check with Winsock */
   1382       pollrc = Curl_poll(cpfds.pfds, cpfds.n, 0);
   1383     else
   1384       pollrc = 0;
   1385 #else
   1386     pollrc = Curl_poll(cpfds.pfds, cpfds.n, timeout_ms); /* wait... */
   1387 #endif
   1388     if(pollrc < 0) {
   1389       result = CURLM_UNRECOVERABLE_POLL;
   1390       goto out;
   1391     }
   1392 
   1393     if(pollrc > 0) {
   1394       retcode = pollrc;
   1395 #ifdef USE_WINSOCK
   1396     }
   1397     else { /* now wait... if not ready during the pre-check (pollrc == 0) */
   1398       WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, (DWORD)timeout_ms,
   1399                                FALSE);
   1400     }
   1401     /* With Winsock, we have to run the following section unconditionally
   1402        to call WSAEventSelect(fd, event, 0) on all the sockets */
   1403     {
   1404 #endif
   1405       /* copy revents results from the poll to the curl_multi_wait poll
   1406          struct, the bit values of the actual underlying poll() implementation
   1407          may not be the same as the ones in the public libcurl API! */
   1408       for(i = 0; i < extra_nfds; i++) {
   1409         unsigned r = (unsigned)cpfds.pfds[curl_nfds + i].revents;
   1410         unsigned short mask = 0;
   1411 #ifdef USE_WINSOCK
   1412         curl_socket_t s = extra_fds[i].fd;
   1413         wsa_events.lNetworkEvents = 0;
   1414         if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
   1415           if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
   1416             mask |= CURL_WAIT_POLLIN;
   1417           if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
   1418             mask |= CURL_WAIT_POLLOUT;
   1419           if(wsa_events.lNetworkEvents & FD_OOB)
   1420             mask |= CURL_WAIT_POLLPRI;
   1421           if(ret && !pollrc && wsa_events.lNetworkEvents)
   1422             retcode++;
   1423         }
   1424         WSAEventSelect(s, multi->wsa_event, 0);
   1425         if(!pollrc) {
   1426           extra_fds[i].revents = (short)mask;
   1427           continue;
   1428         }
   1429 #endif
   1430         if(r & POLLIN)
   1431           mask |= CURL_WAIT_POLLIN;
   1432         if(r & POLLOUT)
   1433           mask |= CURL_WAIT_POLLOUT;
   1434         if(r & POLLPRI)
   1435           mask |= CURL_WAIT_POLLPRI;
   1436         extra_fds[i].revents = (short)mask;
   1437       }
   1438 
   1439 #ifdef USE_WINSOCK
   1440       /* Count up all our own sockets that had activity,
   1441          and remove them from the event. */
   1442       for(i = 0; i < curl_nfds; ++i) {
   1443         wsa_events.lNetworkEvents = 0;
   1444         if(WSAEnumNetworkEvents(cpfds.pfds[i].fd, NULL, &wsa_events) == 0) {
   1445           if(ret && !pollrc && wsa_events.lNetworkEvents)
   1446             retcode++;
   1447         }
   1448         WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, 0);
   1449       }
   1450       WSAResetEvent(multi->wsa_event);
   1451 #else
   1452 #ifdef ENABLE_WAKEUP
   1453       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
   1454         if(cpfds.pfds[curl_nfds + extra_nfds].revents & POLLIN) {
   1455           char buf[64];
   1456           ssize_t nread;
   1457           while(1) {
   1458             /* the reading socket is non-blocking, try to read
   1459                data from it until it receives an error (except EINTR).
   1460                In normal cases it will get EAGAIN or EWOULDBLOCK
   1461                when there is no more data, breaking the loop. */
   1462             nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
   1463             if(nread <= 0) {
   1464               if(nread < 0 && SOCKEINTR == SOCKERRNO)
   1465                 continue;
   1466               break;
   1467             }
   1468           }
   1469           /* do not count the wakeup socket into the returned value */
   1470           retcode--;
   1471         }
   1472       }
   1473 #endif
   1474 #endif
   1475     }
   1476   }
   1477 
   1478   if(ret)
   1479     *ret = retcode;
   1480 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
   1481   if(extrawait && !cpfds.n && !use_wakeup) {
   1482 #else
   1483   if(extrawait && !cpfds.n) {
   1484 #endif
   1485     long sleep_ms = 0;
   1486 
   1487     /* Avoid busy-looping when there is nothing particular to wait for */
   1488     if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
   1489       if(sleep_ms > timeout_ms)
   1490         sleep_ms = timeout_ms;
   1491       /* when there are no easy handles in the multi, this holds a -1
   1492          timeout */
   1493       else if(sleep_ms < 0)
   1494         sleep_ms = timeout_ms;
   1495       curlx_wait_ms(sleep_ms);
   1496     }
   1497   }
   1498 
   1499 out:
   1500   Curl_pollfds_cleanup(&cpfds);
   1501   return result;
   1502 }
   1503 
   1504 CURLMcode curl_multi_wait(CURLM *multi,
   1505                           struct curl_waitfd extra_fds[],
   1506                           unsigned int extra_nfds,
   1507                           int timeout_ms,
   1508                           int *ret)
   1509 {
   1510   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
   1511                     FALSE);
   1512 }
   1513 
   1514 CURLMcode curl_multi_poll(CURLM *multi,
   1515                           struct curl_waitfd extra_fds[],
   1516                           unsigned int extra_nfds,
   1517                           int timeout_ms,
   1518                           int *ret)
   1519 {
   1520   return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
   1521                     TRUE);
   1522 }
   1523 
   1524 CURLMcode curl_multi_wakeup(CURLM *m)
   1525 {
   1526   /* this function is usually called from another thread,
   1527      it has to be careful only to access parts of the
   1528      Curl_multi struct that are constant */
   1529   struct Curl_multi *multi = m;
   1530 
   1531   /* GOOD_MULTI_HANDLE can be safely called */
   1532   if(!GOOD_MULTI_HANDLE(multi))
   1533     return CURLM_BAD_HANDLE;
   1534 
   1535 #ifdef ENABLE_WAKEUP
   1536 #ifdef USE_WINSOCK
   1537   if(WSASetEvent(multi->wsa_event))
   1538     return CURLM_OK;
   1539 #else
   1540   /* the wakeup_pair variable is only written during init and cleanup,
   1541      making it safe to access from another thread after the init part
   1542      and before cleanup */
   1543   if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
   1544     while(1) {
   1545 #ifdef USE_EVENTFD
   1546       /* eventfd has a stringent rule of requiring the 8-byte buffer when
   1547          calling write(2) on it */
   1548       const uint64_t buf[1] = { 1 };
   1549 #else
   1550       const char buf[1] = { 1 };
   1551 #endif
   1552       /* swrite() is not thread-safe in general, because concurrent calls
   1553          can have their messages interleaved, but in this case the content
   1554          of the messages does not matter, which makes it ok to call.
   1555 
   1556          The write socket is set to non-blocking, this way this function
   1557          cannot block, making it safe to call even from the same thread
   1558          that will call curl_multi_wait(). If swrite() returns that it
   1559          would block, it is considered successful because it means that
   1560          previous calls to this function will wake up the poll(). */
   1561       if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
   1562         int err = SOCKERRNO;
   1563         int return_success;
   1564 #ifdef USE_WINSOCK
   1565         return_success = SOCKEWOULDBLOCK == err;
   1566 #else
   1567         if(SOCKEINTR == err)
   1568           continue;
   1569         return_success = SOCKEWOULDBLOCK == err || EAGAIN == err;
   1570 #endif
   1571         if(!return_success)
   1572           return CURLM_WAKEUP_FAILURE;
   1573       }
   1574       return CURLM_OK;
   1575     }
   1576   }
   1577 #endif
   1578 #endif
   1579   return CURLM_WAKEUP_FAILURE;
   1580 }
   1581 
   1582 /*
   1583  * multi_ischanged() is called
   1584  *
   1585  * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
   1586  * => CONNECT action.
   1587  *
   1588  * Set 'clear' to TRUE to have it also clear the state variable.
   1589  */
   1590 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
   1591 {
   1592   bool retval = multi->recheckstate;
   1593   if(clear)
   1594     multi->recheckstate = FALSE;
   1595   return retval;
   1596 }
   1597 
   1598 /*
   1599  * Curl_multi_connchanged() is called to tell that there is a connection in
   1600  * this multi handle that has changed state (multiplexing become possible, the
   1601  * number of allowed streams changed or similar), and a subsequent use of this
   1602  * multi handle should move CONNECT_PEND handles back to CONNECT to have them
   1603  * retry.
   1604  */
   1605 void Curl_multi_connchanged(struct Curl_multi *multi)
   1606 {
   1607   multi->recheckstate = TRUE;
   1608 }
   1609 
   1610 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
   1611                                  struct Curl_easy *data,
   1612                                  struct connectdata *conn)
   1613 {
   1614   CURLMcode rc;
   1615 
   1616   if(multi->in_callback)
   1617     return CURLM_RECURSIVE_API_CALL;
   1618 
   1619   rc = curl_multi_add_handle(multi, data);
   1620   if(!rc) {
   1621     struct SingleRequest *k = &data->req;
   1622     CURLcode result;
   1623 
   1624     /* pass in NULL for 'conn' here since we do not want to init the
   1625        connection, only this transfer */
   1626     result = Curl_init_do(data, NULL);
   1627     if(result) {
   1628       curl_multi_remove_handle(multi, data);
   1629       return CURLM_INTERNAL_ERROR;
   1630     }
   1631 
   1632     /* take this handle to the perform state right away */
   1633     multistate(data, MSTATE_PERFORMING);
   1634     Curl_attach_connection(data, conn);
   1635     k->keepon |= KEEP_RECV; /* setup to receive! */
   1636   }
   1637   return rc;
   1638 }
   1639 
   1640 static CURLcode multi_do(struct Curl_easy *data, bool *done)
   1641 {
   1642   CURLcode result = CURLE_OK;
   1643   struct connectdata *conn = data->conn;
   1644 
   1645   DEBUGASSERT(conn);
   1646   DEBUGASSERT(conn->handler);
   1647 
   1648   if(conn->handler->do_it)
   1649     result = conn->handler->do_it(data, done);
   1650 
   1651   return result;
   1652 }
   1653 
   1654 /*
   1655  * multi_do_more() is called during the DO_MORE multi state. It is basically a
   1656  * second stage DO state which (wrongly) was introduced to support FTP's
   1657  * second connection.
   1658  *
   1659  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
   1660  * DOING state there is more work to do!
   1661  */
   1662 
   1663 static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
   1664 {
   1665   CURLcode result = CURLE_OK;
   1666   struct connectdata *conn = data->conn;
   1667 
   1668   *complete = 0;
   1669 
   1670   if(conn->handler->do_more)
   1671     result = conn->handler->do_more(data, complete);
   1672 
   1673   return result;
   1674 }
   1675 
   1676 /*
   1677  * Check whether a timeout occurred, and handle it if it did
   1678  */
   1679 static bool multi_handle_timeout(struct Curl_easy *data,
   1680                                  struct curltime *now,
   1681                                  bool *stream_error,
   1682                                  CURLcode *result)
   1683 {
   1684   bool connect_timeout = data->mstate < MSTATE_DO;
   1685   timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout);
   1686   if(timeout_ms < 0) {
   1687     /* Handle timed out */
   1688     struct curltime since;
   1689     if(connect_timeout)
   1690       since = data->progress.t_startsingle;
   1691     else
   1692       since = data->progress.t_startop;
   1693     if(data->mstate == MSTATE_RESOLVING)
   1694       failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T
   1695             " milliseconds", curlx_timediff(*now, since));
   1696     else if(data->mstate == MSTATE_CONNECTING)
   1697       failf(data, "Connection timed out after %" FMT_TIMEDIFF_T
   1698             " milliseconds", curlx_timediff(*now, since));
   1699     else {
   1700       struct SingleRequest *k = &data->req;
   1701       if(k->size != -1) {
   1702         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
   1703               " milliseconds with %" FMT_OFF_T " out of %"
   1704               FMT_OFF_T " bytes received",
   1705               curlx_timediff(*now, since), k->bytecount, k->size);
   1706       }
   1707       else {
   1708         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
   1709               " milliseconds with %" FMT_OFF_T " bytes received",
   1710               curlx_timediff(*now, since), k->bytecount);
   1711       }
   1712     }
   1713     *result = CURLE_OPERATION_TIMEDOUT;
   1714     if(data->conn) {
   1715       /* Force connection closed if the connection has indeed been used */
   1716       if(data->mstate > MSTATE_DO) {
   1717         streamclose(data->conn, "Disconnect due to timeout");
   1718         *stream_error = TRUE;
   1719       }
   1720       (void)multi_done(data, *result, TRUE);
   1721     }
   1722     return TRUE;
   1723   }
   1724 
   1725   return FALSE;
   1726 }
   1727 
   1728 /*
   1729  * We are doing protocol-specific connecting and this is being called over and
   1730  * over from the multi interface until the connection phase is done on
   1731  * protocol layer.
   1732  */
   1733 
   1734 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
   1735 {
   1736   CURLcode result = CURLE_OK;
   1737   struct connectdata *conn = data->conn;
   1738 
   1739   if(conn && conn->handler->connecting) {
   1740     *done = FALSE;
   1741     result = conn->handler->connecting(data, done);
   1742   }
   1743   else
   1744     *done = TRUE;
   1745 
   1746   return result;
   1747 }
   1748 
   1749 /*
   1750  * We are DOING this is being called over and over from the multi interface
   1751  * until the DOING phase is done on protocol layer.
   1752  */
   1753 
   1754 static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
   1755 {
   1756   CURLcode result = CURLE_OK;
   1757   struct connectdata *conn = data->conn;
   1758 
   1759   if(conn && conn->handler->doing) {
   1760     *done = FALSE;
   1761     result = conn->handler->doing(data, done);
   1762   }
   1763   else
   1764     *done = TRUE;
   1765 
   1766   return result;
   1767 }
   1768 
   1769 /*
   1770  * We have discovered that the TCP connection has been successful, we can now
   1771  * proceed with some action.
   1772  *
   1773  */
   1774 static CURLcode protocol_connect(struct Curl_easy *data,
   1775                                  bool *protocol_done)
   1776 {
   1777   CURLcode result = CURLE_OK;
   1778   struct connectdata *conn = data->conn;
   1779   DEBUGASSERT(conn);
   1780   DEBUGASSERT(protocol_done);
   1781 
   1782   *protocol_done = FALSE;
   1783 
   1784   if(Curl_conn_is_connected(conn, FIRSTSOCKET)
   1785      && conn->bits.protoconnstart) {
   1786     /* We already are connected, get back. This may happen when the connect
   1787        worked fine in the first call, like when we connect to a local server
   1788        or proxy. Note that we do not know if the protocol is actually done.
   1789 
   1790        Unless this protocol does not have any protocol-connect callback, as
   1791        then we know we are done. */
   1792     if(!conn->handler->connecting)
   1793       *protocol_done = TRUE;
   1794 
   1795     return CURLE_OK;
   1796   }
   1797 
   1798   if(!conn->bits.protoconnstart) {
   1799     if(conn->handler->connect_it) {
   1800       /* is there a protocol-specific connect() procedure? */
   1801 
   1802       /* Call the protocol-specific connect function */
   1803       result = conn->handler->connect_it(data, protocol_done);
   1804     }
   1805     else
   1806       *protocol_done = TRUE;
   1807 
   1808     /* it has started, possibly even completed but that knowledge is not stored
   1809        in this bit! */
   1810     if(!result)
   1811       conn->bits.protoconnstart = TRUE;
   1812   }
   1813 
   1814   return result; /* pass back status */
   1815 }
   1816 
   1817 static void set_in_callback(struct Curl_multi *multi, bool value)
   1818 {
   1819   multi->in_callback = value;
   1820 }
   1821 
   1822 /*
   1823  * posttransfer() is called immediately after a transfer ends
   1824  */
   1825 static void multi_posttransfer(struct Curl_easy *data)
   1826 {
   1827 #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
   1828   /* restore the signal handler for SIGPIPE before we get back */
   1829   if(!data->set.no_signal)
   1830     signal(SIGPIPE, data->state.prev_signal);
   1831 #else
   1832   (void)data; /* unused parameter */
   1833 #endif
   1834 }
   1835 
   1836 /*
   1837  * multi_follow() handles the URL redirect magic. Pass in the 'newurl' string
   1838  * as given by the remote server and set up the new URL to request.
   1839  *
   1840  * This function DOES NOT FREE the given url.
   1841  */
   1842 static CURLcode multi_follow(struct Curl_easy *data,
   1843                              const struct Curl_handler *handler,
   1844                              const char *newurl, /* the Location: string */
   1845                              followtype type) /* see transfer.h */
   1846 {
   1847   if(handler && handler->follow)
   1848     return handler->follow(data, newurl, type);
   1849   return CURLE_TOO_MANY_REDIRECTS;
   1850 }
   1851 
   1852 static CURLMcode state_performing(struct Curl_easy *data,
   1853                                   struct curltime *nowp,
   1854                                   bool *stream_errorp,
   1855                                   CURLcode *resultp)
   1856 {
   1857   char *newurl = NULL;
   1858   bool retry = FALSE;
   1859   timediff_t recv_timeout_ms = 0;
   1860   timediff_t send_timeout_ms = 0;
   1861   CURLMcode rc = CURLM_OK;
   1862   CURLcode result = *resultp = CURLE_OK;
   1863   *stream_errorp = FALSE;
   1864 
   1865   /* check if over send speed */
   1866   if(data->set.max_send_speed)
   1867     send_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.ul,
   1868                                              data->set.max_send_speed,
   1869                                              *nowp);
   1870 
   1871   /* check if over recv speed */
   1872   if(data->set.max_recv_speed)
   1873     recv_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.dl,
   1874                                              data->set.max_recv_speed,
   1875                                              *nowp);
   1876 
   1877   if(send_timeout_ms || recv_timeout_ms) {
   1878     Curl_ratelimit(data, *nowp);
   1879     multistate(data, MSTATE_RATELIMITING);
   1880     if(send_timeout_ms >= recv_timeout_ms)
   1881       Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
   1882     else
   1883       Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
   1884     return CURLM_OK;
   1885   }
   1886 
   1887   /* read/write data if it is ready to do so */
   1888   result = Curl_sendrecv(data, nowp);
   1889 
   1890   if(data->req.done || (result == CURLE_RECV_ERROR)) {
   1891     /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
   1892      * condition and the server closed the reused connection exactly when we
   1893      * wanted to use it, so figure out if that is indeed the case.
   1894      */
   1895     CURLcode ret = Curl_retry_request(data, &newurl);
   1896     if(!ret)
   1897       retry = !!newurl;
   1898     else if(!result)
   1899       result = ret;
   1900 
   1901     if(retry) {
   1902       /* if we are to retry, set the result to OK and consider the
   1903          request as done */
   1904       result = CURLE_OK;
   1905       data->req.done = TRUE;
   1906     }
   1907   }
   1908 #ifndef CURL_DISABLE_HTTP
   1909   else if((CURLE_HTTP2_STREAM == result) &&
   1910           Curl_h2_http_1_1_error(data)) {
   1911     CURLcode ret = Curl_retry_request(data, &newurl);
   1912 
   1913     if(!ret) {
   1914       infof(data, "Downgrades to HTTP/1.1");
   1915       streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
   1916       data->state.http_neg.wanted = CURL_HTTP_V1x;
   1917       data->state.http_neg.allowed = CURL_HTTP_V1x;
   1918       /* clear the error message bit too as we ignore the one we got */
   1919       data->state.errorbuf = FALSE;
   1920       if(!newurl)
   1921         /* typically for HTTP_1_1_REQUIRED error on first flight */
   1922         newurl = strdup(data->state.url);
   1923       /* if we are to retry, set the result to OK and consider the request
   1924          as done */
   1925       retry = TRUE;
   1926       result = CURLE_OK;
   1927       data->req.done = TRUE;
   1928     }
   1929     else
   1930       result = ret;
   1931   }
   1932 #endif
   1933 
   1934   if(result) {
   1935     /*
   1936      * The transfer phase returned error, we mark the connection to get closed
   1937      * to prevent being reused. This is because we cannot possibly know if the
   1938      * connection is in a good shape or not now. Unless it is a protocol which
   1939      * uses two "channels" like FTP, as then the error happened in the data
   1940      * connection.
   1941      */
   1942 
   1943     if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
   1944        result != CURLE_HTTP2_STREAM)
   1945       streamclose(data->conn, "Transfer returned error");
   1946 
   1947     multi_posttransfer(data);
   1948     multi_done(data, result, TRUE);
   1949   }
   1950   else if(data->req.done && !Curl_cwriter_is_paused(data)) {
   1951     const struct Curl_handler *handler = data->conn->handler;
   1952 
   1953     /* call this even if the readwrite function returned error */
   1954     multi_posttransfer(data);
   1955 
   1956     /* When we follow redirects or is set to retry the connection, we must to
   1957        go back to the CONNECT state */
   1958     if(data->req.newurl || retry) {
   1959       followtype follow = FOLLOW_NONE;
   1960       if(!retry) {
   1961         /* if the URL is a follow-location and not just a retried request then
   1962            figure out the URL here */
   1963         free(newurl);
   1964         newurl = data->req.newurl;
   1965         data->req.newurl = NULL;
   1966         follow = FOLLOW_REDIR;
   1967       }
   1968       else
   1969         follow = FOLLOW_RETRY;
   1970       (void)multi_done(data, CURLE_OK, FALSE);
   1971       /* multi_done() might return CURLE_GOT_NOTHING */
   1972       result = multi_follow(data, handler, newurl, follow);
   1973       if(!result) {
   1974         multistate(data, MSTATE_SETUP);
   1975         rc = CURLM_CALL_MULTI_PERFORM;
   1976       }
   1977     }
   1978     else {
   1979       /* after the transfer is done, go DONE */
   1980 
   1981       /* but first check to see if we got a location info even though we are
   1982          not following redirects */
   1983       if(data->req.location) {
   1984         free(newurl);
   1985         newurl = data->req.location;
   1986         data->req.location = NULL;
   1987         result = multi_follow(data, handler, newurl, FOLLOW_FAKE);
   1988         if(result) {
   1989           *stream_errorp = TRUE;
   1990           result = multi_done(data, result, TRUE);
   1991         }
   1992       }
   1993 
   1994       if(!result) {
   1995         multistate(data, MSTATE_DONE);
   1996         rc = CURLM_CALL_MULTI_PERFORM;
   1997       }
   1998     }
   1999   }
   2000   free(newurl);
   2001   *resultp = result;
   2002   return rc;
   2003 }
   2004 
   2005 static CURLMcode state_do(struct Curl_easy *data,
   2006                           bool *stream_errorp,
   2007                           CURLcode *resultp)
   2008 {
   2009   CURLMcode rc = CURLM_OK;
   2010   CURLcode result = CURLE_OK;
   2011   if(data->set.fprereq) {
   2012     int prereq_rc;
   2013 
   2014     /* call the prerequest callback function */
   2015     Curl_set_in_callback(data, TRUE);
   2016     prereq_rc = data->set.fprereq(data->set.prereq_userp,
   2017                                   data->info.primary.remote_ip,
   2018                                   data->info.primary.local_ip,
   2019                                   data->info.primary.remote_port,
   2020                                   data->info.primary.local_port);
   2021     Curl_set_in_callback(data, FALSE);
   2022     if(prereq_rc != CURL_PREREQFUNC_OK) {
   2023       failf(data, "operation aborted by pre-request callback");
   2024       /* failure in pre-request callback - do not do any other processing */
   2025       result = CURLE_ABORTED_BY_CALLBACK;
   2026       multi_posttransfer(data);
   2027       multi_done(data, result, FALSE);
   2028       *stream_errorp = TRUE;
   2029       goto end;
   2030     }
   2031   }
   2032 
   2033   if(data->set.connect_only && !data->set.connect_only_ws) {
   2034     /* keep connection open for application to use the socket */
   2035     connkeep(data->conn, "CONNECT_ONLY");
   2036     multistate(data, MSTATE_DONE);
   2037     rc = CURLM_CALL_MULTI_PERFORM;
   2038   }
   2039   else {
   2040     bool dophase_done = FALSE;
   2041     /* Perform the protocol's DO action */
   2042     result = multi_do(data, &dophase_done);
   2043 
   2044     /* When multi_do() returns failure, data->conn might be NULL! */
   2045 
   2046     if(!result) {
   2047       if(!dophase_done) {
   2048 #ifndef CURL_DISABLE_FTP
   2049         /* some steps needed for wildcard matching */
   2050         if(data->state.wildcardmatch) {
   2051           struct WildcardData *wc = data->wildcard;
   2052           if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
   2053             /* skip some states if it is important */
   2054             multi_done(data, CURLE_OK, FALSE);
   2055 
   2056             /* if there is no connection left, skip the DONE state */
   2057             multistate(data, data->conn ?
   2058                        MSTATE_DONE : MSTATE_COMPLETED);
   2059             rc = CURLM_CALL_MULTI_PERFORM;
   2060             goto end;
   2061           }
   2062         }
   2063 #endif
   2064         /* DO was not completed in one function call, we must continue
   2065            DOING... */
   2066         multistate(data, MSTATE_DOING);
   2067         rc = CURLM_CALL_MULTI_PERFORM;
   2068       }
   2069 
   2070       /* after DO, go DO_DONE... or DO_MORE */
   2071       else if(data->conn->bits.do_more) {
   2072         /* we are supposed to do more, but we need to sit down, relax and wait
   2073            a little while first */
   2074         multistate(data, MSTATE_DOING_MORE);
   2075         rc = CURLM_CALL_MULTI_PERFORM;
   2076       }
   2077       else {
   2078         /* we are done with the DO, now DID */
   2079         multistate(data, MSTATE_DID);
   2080         rc = CURLM_CALL_MULTI_PERFORM;
   2081       }
   2082     }
   2083     else if((CURLE_SEND_ERROR == result) &&
   2084             data->conn->bits.reuse) {
   2085       /*
   2086        * In this situation, a connection that we were trying to use may have
   2087        * unexpectedly died. If possible, send the connection back to the
   2088        * CONNECT phase so we can try again.
   2089        */
   2090       const struct Curl_handler *handler = data->conn->handler;
   2091       char *newurl = NULL;
   2092       followtype follow = FOLLOW_NONE;
   2093       CURLcode drc;
   2094 
   2095       drc = Curl_retry_request(data, &newurl);
   2096       if(drc) {
   2097         /* a failure here pretty much implies an out of memory */
   2098         result = drc;
   2099         *stream_errorp = TRUE;
   2100       }
   2101 
   2102       multi_posttransfer(data);
   2103       drc = multi_done(data, result, FALSE);
   2104 
   2105       /* When set to retry the connection, we must go back to the CONNECT
   2106        * state */
   2107       if(newurl) {
   2108         if(!drc || (drc == CURLE_SEND_ERROR)) {
   2109           follow = FOLLOW_RETRY;
   2110           drc = multi_follow(data, handler, newurl, follow);
   2111           if(!drc) {
   2112             multistate(data, MSTATE_SETUP);
   2113             rc = CURLM_CALL_MULTI_PERFORM;
   2114             result = CURLE_OK;
   2115           }
   2116           else {
   2117             /* Follow failed */
   2118             result = drc;
   2119           }
   2120         }
   2121         else {
   2122           /* done did not return OK or SEND_ERROR */
   2123           result = drc;
   2124         }
   2125       }
   2126       else {
   2127         /* Have error handler disconnect conn if we cannot retry */
   2128         *stream_errorp = TRUE;
   2129       }
   2130       free(newurl);
   2131     }
   2132     else {
   2133       /* failure detected */
   2134       multi_posttransfer(data);
   2135       if(data->conn)
   2136         multi_done(data, result, FALSE);
   2137       *stream_errorp = TRUE;
   2138     }
   2139   }
   2140 end:
   2141   *resultp = result;
   2142   return rc;
   2143 }
   2144 
   2145 static CURLMcode state_ratelimiting(struct Curl_easy *data,
   2146                                     struct curltime *nowp,
   2147                                     CURLcode *resultp)
   2148 {
   2149   CURLcode result = CURLE_OK;
   2150   CURLMcode rc = CURLM_OK;
   2151   DEBUGASSERT(data->conn);
   2152   /* if both rates are within spec, resume transfer */
   2153   if(Curl_pgrsUpdate(data))
   2154     result = CURLE_ABORTED_BY_CALLBACK;
   2155   else
   2156     result = Curl_speedcheck(data, *nowp);
   2157 
   2158   if(result) {
   2159     if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
   2160        result != CURLE_HTTP2_STREAM)
   2161       streamclose(data->conn, "Transfer returned error");
   2162 
   2163     multi_posttransfer(data);
   2164     multi_done(data, result, TRUE);
   2165   }
   2166   else {
   2167     timediff_t recv_timeout_ms = 0;
   2168     timediff_t send_timeout_ms = 0;
   2169     if(data->set.max_send_speed)
   2170       send_timeout_ms =
   2171         Curl_pgrsLimitWaitTime(&data->progress.ul,
   2172                                data->set.max_send_speed,
   2173                                *nowp);
   2174 
   2175     if(data->set.max_recv_speed)
   2176       recv_timeout_ms =
   2177         Curl_pgrsLimitWaitTime(&data->progress.dl,
   2178                                data->set.max_recv_speed,
   2179                                *nowp);
   2180 
   2181     if(!send_timeout_ms && !recv_timeout_ms) {
   2182       multistate(data, MSTATE_PERFORMING);
   2183       Curl_ratelimit(data, *nowp);
   2184       /* start performing again right away */
   2185       rc = CURLM_CALL_MULTI_PERFORM;
   2186     }
   2187     else if(send_timeout_ms >= recv_timeout_ms)
   2188       Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
   2189     else
   2190       Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
   2191   }
   2192   *resultp = result;
   2193   return rc;
   2194 }
   2195 
   2196 static CURLMcode state_resolving(struct Curl_multi *multi,
   2197                                  struct Curl_easy *data,
   2198                                  bool *stream_errorp,
   2199                                  CURLcode *resultp)
   2200 {
   2201   struct Curl_dns_entry *dns = NULL;
   2202   CURLcode result;
   2203   CURLMcode rc = CURLM_OK;
   2204 
   2205   result = Curl_resolv_check(data, &dns);
   2206   CURL_TRC_DNS(data, "Curl_resolv_check() -> %d, %s",
   2207                result, dns ? "found" : "missing");
   2208   /* Update sockets here, because the socket(s) may have been closed and the
   2209      application thus needs to be told, even if it is likely that the same
   2210      socket(s) will again be used further down. If the name has not yet been
   2211      resolved, it is likely that new sockets have been opened in an attempt to
   2212      contact another resolver. */
   2213   rc = Curl_multi_ev_assess_xfer(multi, data);
   2214   if(rc)
   2215     return rc;
   2216 
   2217   if(dns) {
   2218     bool connected;
   2219     /* Perform the next step in the connection phase, and then move on to the
   2220        WAITCONNECT state */
   2221     result = Curl_once_resolved(data, dns, &connected);
   2222 
   2223     if(result)
   2224       /* if Curl_once_resolved() returns failure, the connection struct is
   2225          already freed and gone */
   2226       data->conn = NULL; /* no more connection */
   2227     else {
   2228       /* call again please so that we get the next socket setup */
   2229       rc = CURLM_CALL_MULTI_PERFORM;
   2230       if(connected)
   2231         multistate(data, MSTATE_PROTOCONNECT);
   2232       else {
   2233         multistate(data, MSTATE_CONNECTING);
   2234       }
   2235     }
   2236   }
   2237 
   2238   if(result)
   2239     /* failure detected */
   2240     *stream_errorp = TRUE;
   2241 
   2242   *resultp = result;
   2243   return rc;
   2244 }
   2245 
   2246 static CURLMcode state_connect(struct Curl_multi *multi,
   2247                                struct Curl_easy *data,
   2248                                struct curltime *nowp,
   2249                                CURLcode *resultp)
   2250 {
   2251   /* Connect. We want to get a connection identifier filled in. This state can
   2252      be entered from SETUP and from PENDING. */
   2253   bool connected;
   2254   bool async;
   2255   CURLMcode rc = CURLM_OK;
   2256   CURLcode result = Curl_connect(data, &async, &connected);
   2257   if(CURLE_NO_CONNECTION_AVAILABLE == result) {
   2258     /* There was no connection available. We will go to the pending state and
   2259        wait for an available connection. */
   2260     multistate(data, MSTATE_PENDING);
   2261     /* move from process to pending set */
   2262     Curl_uint_bset_remove(&multi->process, data->mid);
   2263     Curl_uint_bset_remove(&multi->dirty, data->mid);
   2264     Curl_uint_bset_add(&multi->pending, data->mid);
   2265     *resultp = CURLE_OK;
   2266     return rc;
   2267   }
   2268   else
   2269     process_pending_handles(data->multi);
   2270 
   2271   if(!result) {
   2272     *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
   2273     if(async)
   2274       /* We are now waiting for an asynchronous name lookup */
   2275       multistate(data, MSTATE_RESOLVING);
   2276     else {
   2277       /* after the connect has been sent off, go WAITCONNECT unless the
   2278          protocol connect is already done and we can go directly to WAITDO or
   2279          DO! */
   2280       rc = CURLM_CALL_MULTI_PERFORM;
   2281 
   2282       if(connected) {
   2283         if(!data->conn->bits.reuse &&
   2284            Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
   2285           /* new connection, can multiplex, wake pending handles */
   2286           process_pending_handles(data->multi);
   2287         }
   2288         multistate(data, MSTATE_PROTOCONNECT);
   2289       }
   2290       else {
   2291         multistate(data, MSTATE_CONNECTING);
   2292       }
   2293     }
   2294   }
   2295   *resultp = result;
   2296   return rc;
   2297 }
   2298 
   2299 static CURLMcode multi_runsingle(struct Curl_multi *multi,
   2300                                  struct curltime *nowp,
   2301                                  struct Curl_easy *data)
   2302 {
   2303   struct Curl_message *msg = NULL;
   2304   bool connected;
   2305   bool protocol_connected = FALSE;
   2306   bool dophase_done = FALSE;
   2307   CURLMcode rc;
   2308   CURLcode result = CURLE_OK;
   2309   int control;
   2310 
   2311   if(!GOOD_EASY_HANDLE(data))
   2312     return CURLM_BAD_EASY_HANDLE;
   2313 
   2314   if(multi->dead) {
   2315     /* a multi-level callback returned error before, meaning every individual
   2316      transfer now has failed */
   2317     result = CURLE_ABORTED_BY_CALLBACK;
   2318     multi_posttransfer(data);
   2319     multi_done(data, result, FALSE);
   2320     multistate(data, MSTATE_COMPLETED);
   2321   }
   2322 
   2323   multi_warn_debug(multi, data);
   2324 
   2325   /* transfer runs now, clear the dirty bit. This may be set
   2326    * again during processing, triggering a re-run later. */
   2327   Curl_uint_bset_remove(&multi->dirty, data->mid);
   2328 
   2329   do {
   2330     /* A "stream" here is a logical stream if the protocol can handle that
   2331        (HTTP/2), or the full connection for older protocols */
   2332     bool stream_error = FALSE;
   2333     rc = CURLM_OK;
   2334 
   2335     if(multi_ischanged(multi, TRUE)) {
   2336       CURL_TRC_M(data, "multi changed, check CONNECT_PEND queue");
   2337       process_pending_handles(multi); /* multiplexed */
   2338     }
   2339 
   2340     if(data->mstate > MSTATE_CONNECT &&
   2341        data->mstate < MSTATE_COMPLETED) {
   2342       /* Make sure we set the connection's current owner */
   2343       DEBUGASSERT(data->conn);
   2344       if(!data->conn)
   2345         return CURLM_INTERNAL_ERROR;
   2346     }
   2347 
   2348     /* Wait for the connect state as only then is the start time stored, but
   2349        we must not check already completed handles */
   2350     if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) &&
   2351        multi_handle_timeout(data, nowp, &stream_error, &result))
   2352       /* Skip the statemachine and go directly to error handling section. */
   2353       goto statemachine_end;
   2354 
   2355     switch(data->mstate) {
   2356     case MSTATE_INIT:
   2357       /* Transitional state. init this transfer. A handle never comes back to
   2358          this state. */
   2359       result = Curl_pretransfer(data);
   2360       if(result)
   2361         break;
   2362 
   2363       /* after init, go SETUP */
   2364       multistate(data, MSTATE_SETUP);
   2365       (void)Curl_pgrsTime(data, TIMER_STARTOP);
   2366       FALLTHROUGH();
   2367 
   2368     case MSTATE_SETUP:
   2369       /* Transitional state. Setup things for a new transfer. The handle
   2370          can come back to this state on a redirect. */
   2371       *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
   2372       if(data->set.timeout)
   2373         Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
   2374       if(data->set.connecttimeout)
   2375         /* Since a connection might go to pending and back to CONNECT several
   2376            times before it actually takes off, we need to set the timeout once
   2377            in SETUP before we enter CONNECT the first time. */
   2378         Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
   2379 
   2380       multistate(data, MSTATE_CONNECT);
   2381       FALLTHROUGH();
   2382 
   2383     case MSTATE_CONNECT:
   2384       rc = state_connect(multi, data, nowp, &result);
   2385       break;
   2386 
   2387     case MSTATE_RESOLVING:
   2388       /* awaiting an asynch name resolve to complete */
   2389       rc = state_resolving(multi, data, &stream_error, &result);
   2390       break;
   2391 
   2392 #ifndef CURL_DISABLE_HTTP
   2393     case MSTATE_TUNNELING:
   2394       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
   2395       DEBUGASSERT(data->conn);
   2396       result = Curl_http_connect(data, &protocol_connected);
   2397       if(!result) {
   2398         rc = CURLM_CALL_MULTI_PERFORM;
   2399         /* initiate protocol connect phase */
   2400         multistate(data, MSTATE_PROTOCONNECT);
   2401       }
   2402       else
   2403         stream_error = TRUE;
   2404       break;
   2405 #endif
   2406 
   2407     case MSTATE_CONNECTING:
   2408       /* awaiting a completion of an asynch TCP connect */
   2409       DEBUGASSERT(data->conn);
   2410       result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
   2411       if(connected && !result) {
   2412         if(!data->conn->bits.reuse &&
   2413            Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) {
   2414           /* new connection, can multiplex, wake pending handles */
   2415           process_pending_handles(data->multi);
   2416         }
   2417         rc = CURLM_CALL_MULTI_PERFORM;
   2418         multistate(data, MSTATE_PROTOCONNECT);
   2419       }
   2420       else if(result) {
   2421         /* failure detected */
   2422         multi_posttransfer(data);
   2423         multi_done(data, result, TRUE);
   2424         stream_error = TRUE;
   2425         break;
   2426       }
   2427       break;
   2428 
   2429     case MSTATE_PROTOCONNECT:
   2430       if(!result && data->conn->bits.reuse) {
   2431         /* ftp seems to hang when protoconnect on reused connection since we
   2432          * handle PROTOCONNECT in general inside the filers, it seems wrong to
   2433          * restart this on a reused connection.
   2434          */
   2435         multistate(data, MSTATE_DO);
   2436         rc = CURLM_CALL_MULTI_PERFORM;
   2437         break;
   2438       }
   2439       if(!result)
   2440         result = protocol_connect(data, &protocol_connected);
   2441       if(!result && !protocol_connected) {
   2442         /* switch to waiting state */
   2443         multistate(data, MSTATE_PROTOCONNECTING);
   2444         rc = CURLM_CALL_MULTI_PERFORM;
   2445       }
   2446       else if(!result) {
   2447         /* protocol connect has completed, go WAITDO or DO */
   2448         multistate(data, MSTATE_DO);
   2449         rc = CURLM_CALL_MULTI_PERFORM;
   2450       }
   2451       else {
   2452         /* failure detected */
   2453         multi_posttransfer(data);
   2454         multi_done(data, result, TRUE);
   2455         stream_error = TRUE;
   2456       }
   2457       break;
   2458 
   2459     case MSTATE_PROTOCONNECTING:
   2460       /* protocol-specific connect phase */
   2461       result = protocol_connecting(data, &protocol_connected);
   2462       if(!result && protocol_connected) {
   2463         /* after the connect has completed, go WAITDO or DO */
   2464         multistate(data, MSTATE_DO);
   2465         rc = CURLM_CALL_MULTI_PERFORM;
   2466       }
   2467       else if(result) {
   2468         /* failure detected */
   2469         multi_posttransfer(data);
   2470         multi_done(data, result, TRUE);
   2471         stream_error = TRUE;
   2472       }
   2473       break;
   2474 
   2475     case MSTATE_DO:
   2476       rc = state_do(data, &stream_error, &result);
   2477       break;
   2478 
   2479     case MSTATE_DOING:
   2480       /* we continue DOING until the DO phase is complete */
   2481       DEBUGASSERT(data->conn);
   2482       result = protocol_doing(data, &dophase_done);
   2483       if(!result) {
   2484         if(dophase_done) {
   2485           /* after DO, go DO_DONE or DO_MORE */
   2486           multistate(data, data->conn->bits.do_more ?
   2487                      MSTATE_DOING_MORE : MSTATE_DID);
   2488           rc = CURLM_CALL_MULTI_PERFORM;
   2489         } /* dophase_done */
   2490       }
   2491       else {
   2492         /* failure detected */
   2493         multi_posttransfer(data);
   2494         multi_done(data, result, FALSE);
   2495         stream_error = TRUE;
   2496       }
   2497       break;
   2498 
   2499     case MSTATE_DOING_MORE:
   2500       /*
   2501        * When we are connected, DOING MORE and then go DID
   2502        */
   2503       DEBUGASSERT(data->conn);
   2504       result = multi_do_more(data, &control);
   2505 
   2506       if(!result) {
   2507         if(control) {
   2508           /* if positive, advance to DO_DONE
   2509              if negative, go back to DOING */
   2510           multistate(data, control == 1 ?
   2511                      MSTATE_DID : MSTATE_DOING);
   2512           rc = CURLM_CALL_MULTI_PERFORM;
   2513         }
   2514         /* else
   2515            stay in DO_MORE */
   2516       }
   2517       else {
   2518         /* failure detected */
   2519         multi_posttransfer(data);
   2520         multi_done(data, result, FALSE);
   2521         stream_error = TRUE;
   2522       }
   2523       break;
   2524 
   2525     case MSTATE_DID:
   2526       DEBUGASSERT(data->conn);
   2527       if(data->conn->bits.multiplex)
   2528         /* Check if we can move pending requests to send pipe */
   2529         process_pending_handles(multi); /*  multiplexed */
   2530 
   2531       /* Only perform the transfer if there is a good socket to work with.
   2532          Having both BAD is a signal to skip immediately to DONE */
   2533       if((data->conn->sockfd != CURL_SOCKET_BAD) ||
   2534          (data->conn->writesockfd != CURL_SOCKET_BAD))
   2535         multistate(data, MSTATE_PERFORMING);
   2536       else {
   2537 #ifndef CURL_DISABLE_FTP
   2538         if(data->state.wildcardmatch &&
   2539            ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
   2540           data->wildcard->state = CURLWC_DONE;
   2541         }
   2542 #endif
   2543         multistate(data, MSTATE_DONE);
   2544       }
   2545       rc = CURLM_CALL_MULTI_PERFORM;
   2546       break;
   2547 
   2548     case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
   2549       rc = state_ratelimiting(data, nowp, &result);
   2550       break;
   2551 
   2552     case MSTATE_PERFORMING:
   2553       rc = state_performing(data, nowp, &stream_error, &result);
   2554       break;
   2555 
   2556     case MSTATE_DONE:
   2557       /* this state is highly transient, so run another loop after this */
   2558       rc = CURLM_CALL_MULTI_PERFORM;
   2559 
   2560       if(data->conn) {
   2561         CURLcode res;
   2562 
   2563         /* post-transfer command */
   2564         res = multi_done(data, result, FALSE);
   2565 
   2566         /* allow a previously set error code take precedence */
   2567         if(!result)
   2568           result = res;
   2569       }
   2570 
   2571 #ifndef CURL_DISABLE_FTP
   2572       if(data->state.wildcardmatch) {
   2573         if(data->wildcard->state != CURLWC_DONE) {
   2574           /* if a wildcard is set and we are not ending -> lets start again
   2575              with MSTATE_INIT */
   2576           multistate(data, MSTATE_INIT);
   2577           break;
   2578         }
   2579       }
   2580 #endif
   2581       /* after we have DONE what we are supposed to do, go COMPLETED, and
   2582          it does not matter what the multi_done() returned! */
   2583       multistate(data, MSTATE_COMPLETED);
   2584       break;
   2585 
   2586     case MSTATE_COMPLETED:
   2587       break;
   2588 
   2589     case MSTATE_PENDING:
   2590     case MSTATE_MSGSENT:
   2591       /* handles in these states should NOT be in this list */
   2592       break;
   2593 
   2594     default:
   2595       return CURLM_INTERNAL_ERROR;
   2596     }
   2597 
   2598     if(data->mstate >= MSTATE_CONNECT &&
   2599        data->mstate < MSTATE_DO &&
   2600        rc != CURLM_CALL_MULTI_PERFORM &&
   2601        !multi_ischanged(multi, FALSE)) {
   2602       /* We now handle stream timeouts if and only if this will be the last
   2603        * loop iteration. We only check this on the last iteration to ensure
   2604        * that if we know we have additional work to do immediately
   2605        * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
   2606        * declaring the connection timed out as we may almost have a completed
   2607        * connection. */
   2608       multi_handle_timeout(data, nowp, &stream_error, &result);
   2609     }
   2610 
   2611 statemachine_end:
   2612 
   2613     if(data->mstate < MSTATE_COMPLETED) {
   2614       if(result) {
   2615         /*
   2616          * If an error was returned, and we are not in completed state now,
   2617          * then we go to completed and consider this transfer aborted.
   2618          */
   2619 
   2620         /* NOTE: no attempt to disconnect connections must be made
   2621            in the case blocks above - cleanup happens only here */
   2622 
   2623         /* Check if we can move pending requests to send pipe */
   2624         process_pending_handles(multi); /* connection */
   2625 
   2626         if(data->conn) {
   2627           if(stream_error) {
   2628             /* Do not attempt to send data over a connection that timed out */
   2629             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
   2630             struct connectdata *conn = data->conn;
   2631 
   2632             /* This is where we make sure that the conn pointer is reset.
   2633                We do not have to do this in every case block above where a
   2634                failure is detected */
   2635             Curl_detach_connection(data);
   2636             Curl_conn_terminate(data, conn, dead_connection);
   2637           }
   2638         }
   2639         else if(data->mstate == MSTATE_CONNECT) {
   2640           /* Curl_connect() failed */
   2641           multi_posttransfer(data);
   2642           Curl_pgrsUpdate_nometer(data);
   2643         }
   2644 
   2645         multistate(data, MSTATE_COMPLETED);
   2646         rc = CURLM_CALL_MULTI_PERFORM;
   2647       }
   2648       /* if there is still a connection to use, call the progress function */
   2649       else if(data->conn && Curl_pgrsUpdate(data)) {
   2650         /* aborted due to progress callback return code must close the
   2651            connection */
   2652         result = CURLE_ABORTED_BY_CALLBACK;
   2653         streamclose(data->conn, "Aborted by callback");
   2654 
   2655         /* if not yet in DONE state, go there, otherwise COMPLETED */
   2656         multistate(data, (data->mstate < MSTATE_DONE) ?
   2657                    MSTATE_DONE : MSTATE_COMPLETED);
   2658         rc = CURLM_CALL_MULTI_PERFORM;
   2659       }
   2660     }
   2661 
   2662     if(MSTATE_COMPLETED == data->mstate) {
   2663       if(data->master_mid != UINT_MAX) {
   2664         /* A sub transfer, not for msgsent to application */
   2665         struct Curl_easy *mdata;
   2666 
   2667         CURL_TRC_M(data, "sub xfer done for master %u", data->master_mid);
   2668         mdata = Curl_multi_get_easy(multi, data->master_mid);
   2669         if(mdata) {
   2670           if(mdata->sub_xfer_done)
   2671             mdata->sub_xfer_done(mdata, data, result);
   2672           else
   2673             CURL_TRC_M(data, "master easy %u without sub_xfer_done callback.",
   2674                        data->master_mid);
   2675         }
   2676         else {
   2677           CURL_TRC_M(data, "master easy %u already gone.", data->master_mid);
   2678         }
   2679       }
   2680       else {
   2681         /* now fill in the Curl_message with this info */
   2682         msg = &data->msg;
   2683 
   2684         msg->extmsg.msg = CURLMSG_DONE;
   2685         msg->extmsg.easy_handle = data;
   2686         msg->extmsg.data.result = result;
   2687 
   2688         multi_addmsg(multi, msg);
   2689         DEBUGASSERT(!data->conn);
   2690       }
   2691       multistate(data, MSTATE_MSGSENT);
   2692 
   2693       /* remove from the other sets, add to msgsent */
   2694       Curl_uint_bset_remove(&multi->process, data->mid);
   2695       Curl_uint_bset_remove(&multi->dirty, data->mid);
   2696       Curl_uint_bset_remove(&multi->pending, data->mid);
   2697       Curl_uint_bset_add(&multi->msgsent, data->mid);
   2698       --multi->xfers_alive;
   2699       return CURLM_OK;
   2700     }
   2701   } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
   2702 
   2703   data->result = result;
   2704   return rc;
   2705 }
   2706 
   2707 
   2708 CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
   2709 {
   2710   CURLMcode returncode = CURLM_OK;
   2711   struct Curl_tree *t = NULL;
   2712   struct curltime now = curlx_now();
   2713   struct Curl_multi *multi = m;
   2714   unsigned int mid;
   2715   SIGPIPE_VARIABLE(pipe_st);
   2716 
   2717   if(!GOOD_MULTI_HANDLE(multi))
   2718     return CURLM_BAD_HANDLE;
   2719 
   2720   if(multi->in_callback)
   2721     return CURLM_RECURSIVE_API_CALL;
   2722 
   2723   sigpipe_init(&pipe_st);
   2724   if(Curl_uint_bset_first(&multi->process, &mid)) {
   2725     CURL_TRC_M(multi->admin, "multi_perform(running=%u)",
   2726                Curl_multi_xfers_running(multi));
   2727     do {
   2728       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   2729       CURLMcode result;
   2730       if(!data) {
   2731         DEBUGASSERT(0);
   2732         Curl_uint_bset_remove(&multi->process, mid);
   2733         Curl_uint_bset_remove(&multi->dirty, mid);
   2734         continue;
   2735       }
   2736       if(data != multi->admin) {
   2737         /* admin handle is processed below */
   2738         sigpipe_apply(data, &pipe_st);
   2739         result = multi_runsingle(multi, &now, data);
   2740         if(result)
   2741           returncode = result;
   2742       }
   2743     }
   2744     while(Curl_uint_bset_next(&multi->process, mid, &mid));
   2745   }
   2746 
   2747   sigpipe_apply(multi->admin, &pipe_st);
   2748   Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT);
   2749   sigpipe_restore(&pipe_st);
   2750 
   2751   if(multi_ischanged(m, TRUE))
   2752     process_pending_handles(m);
   2753 
   2754   /*
   2755    * Simply remove all expired timers from the splay since handles are dealt
   2756    * with unconditionally by this function and curl_multi_timeout() requires
   2757    * that already passed/handled expire times are removed from the splay.
   2758    *
   2759    * It is important that the 'now' value is set at the entry of this function
   2760    * and not for the current time as it may have ticked a little while since
   2761    * then and then we risk this loop to remove timers that actually have not
   2762    * been handled!
   2763    */
   2764   do {
   2765     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
   2766     if(t) {
   2767       /* the removed may have another timeout in queue */
   2768       struct Curl_easy *data = Curl_splayget(t);
   2769       if(data->mstate == MSTATE_PENDING) {
   2770         bool stream_unused;
   2771         CURLcode result_unused;
   2772         if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) {
   2773           infof(data, "PENDING handle timeout");
   2774           move_pending_to_connect(multi, data);
   2775         }
   2776       }
   2777       (void)add_next_timeout(now, multi, Curl_splayget(t));
   2778     }
   2779   } while(t);
   2780 
   2781   if(running_handles) {
   2782     unsigned int running = Curl_multi_xfers_running(multi);
   2783     *running_handles = (running < INT_MAX) ? (int)running : INT_MAX;
   2784   }
   2785 
   2786   if(CURLM_OK >= returncode)
   2787     returncode = Curl_update_timer(multi);
   2788 
   2789   return returncode;
   2790 }
   2791 
   2792 CURLMcode curl_multi_cleanup(CURLM *m)
   2793 {
   2794   struct Curl_multi *multi = m;
   2795   if(GOOD_MULTI_HANDLE(multi)) {
   2796     void *entry;
   2797     unsigned int mid;
   2798     if(multi->in_callback)
   2799       return CURLM_RECURSIVE_API_CALL;
   2800 
   2801     /* First remove all remaining easy handles,
   2802      * close internal ones. admin handle is special */
   2803     if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
   2804       do {
   2805         struct Curl_easy *data = entry;
   2806         if(!GOOD_EASY_HANDLE(data))
   2807           return CURLM_BAD_HANDLE;
   2808 
   2809 #ifdef DEBUGBUILD
   2810         if(mid != data->mid) {
   2811           CURL_TRC_M(data, "multi_cleanup: still present with mid=%u, "
   2812                      "but unexpected data->mid=%u\n", mid, data->mid);
   2813           DEBUGASSERT(0);
   2814         }
   2815 #endif
   2816 
   2817         if(data == multi->admin)
   2818           continue;
   2819 
   2820         if(!data->state.done && data->conn)
   2821           /* if DONE was never called for this handle */
   2822           (void)multi_done(data, CURLE_OK, TRUE);
   2823 
   2824         data->multi = NULL; /* clear the association */
   2825         Curl_uint_tbl_remove(&multi->xfers, mid);
   2826         data->mid = UINT_MAX;
   2827 
   2828 #ifdef USE_LIBPSL
   2829         if(data->psl == &multi->psl)
   2830           data->psl = NULL;
   2831 #endif
   2832         if(data->state.internal)
   2833           Curl_close(&data);
   2834       }
   2835       while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry));
   2836     }
   2837 
   2838     Curl_cpool_destroy(&multi->cpool);
   2839     Curl_cshutdn_destroy(&multi->cshutdn, multi->admin);
   2840     if(multi->admin) {
   2841       CURL_TRC_M(multi->admin, "multi_cleanup, closing admin handle, done");
   2842       multi->admin->multi = NULL;
   2843       Curl_uint_tbl_remove(&multi->xfers, multi->admin->mid);
   2844       Curl_close(&multi->admin);
   2845     }
   2846 
   2847     multi->magic = 0; /* not good anymore */
   2848 
   2849     Curl_multi_ev_cleanup(multi);
   2850     Curl_hash_destroy(&multi->proto_hash);
   2851     Curl_dnscache_destroy(&multi->dnscache);
   2852     Curl_psl_destroy(&multi->psl);
   2853 #ifdef USE_SSL
   2854     Curl_ssl_scache_destroy(multi->ssl_scache);
   2855 #endif
   2856 
   2857 #ifdef USE_WINSOCK
   2858     WSACloseEvent(multi->wsa_event);
   2859 #else
   2860 #ifdef ENABLE_WAKEUP
   2861     wakeup_close(multi->wakeup_pair[0]);
   2862 #ifndef USE_EVENTFD
   2863     wakeup_close(multi->wakeup_pair[1]);
   2864 #endif
   2865 #endif
   2866 #endif
   2867 
   2868     multi_xfer_bufs_free(multi);
   2869 #ifdef DEBUGBUILD
   2870     if(Curl_uint_tbl_count(&multi->xfers)) {
   2871       multi_xfer_tbl_dump(multi);
   2872       DEBUGASSERT(0);
   2873     }
   2874 #endif
   2875     Curl_uint_bset_destroy(&multi->process);
   2876     Curl_uint_bset_destroy(&multi->dirty);
   2877     Curl_uint_bset_destroy(&multi->pending);
   2878     Curl_uint_bset_destroy(&multi->msgsent);
   2879     Curl_uint_tbl_destroy(&multi->xfers);
   2880     free(multi);
   2881 
   2882     return CURLM_OK;
   2883   }
   2884   return CURLM_BAD_HANDLE;
   2885 }
   2886 
   2887 /*
   2888  * curl_multi_info_read()
   2889  *
   2890  * This function is the primary way for a multi/multi_socket application to
   2891  * figure out if a transfer has ended. We MUST make this function as fast as
   2892  * possible as it will be polled frequently and we MUST NOT scan any lists in
   2893  * here to figure out things. We must scale fine to thousands of handles and
   2894  * beyond. The current design is fully O(1).
   2895  */
   2896 
   2897 CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue)
   2898 {
   2899   struct Curl_message *msg;
   2900   struct Curl_multi *multi = m;
   2901 
   2902   *msgs_in_queue = 0; /* default to none */
   2903 
   2904   if(GOOD_MULTI_HANDLE(multi) &&
   2905      !multi->in_callback &&
   2906      Curl_llist_count(&multi->msglist)) {
   2907     /* there is one or more messages in the list */
   2908     struct Curl_llist_node *e;
   2909 
   2910     /* extract the head of the list to return */
   2911     e = Curl_llist_head(&multi->msglist);
   2912 
   2913     msg = Curl_node_elem(e);
   2914 
   2915     /* remove the extracted entry */
   2916     Curl_node_remove(e);
   2917 
   2918     *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
   2919 
   2920     return &msg->extmsg;
   2921   }
   2922   return NULL;
   2923 }
   2924 
   2925 
   2926 void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s)
   2927 {
   2928   if(data) {
   2929     struct Curl_multi *multi = data->multi;
   2930     if(multi) {
   2931       CURL_TRC_M(data, "Curl_multi_will_close fd=%" FMT_SOCKET_T, s);
   2932       Curl_multi_ev_socket_done(multi, data, s);
   2933     }
   2934   }
   2935 }
   2936 
   2937 /*
   2938  * add_next_timeout()
   2939  *
   2940  * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
   2941  * when it has just been removed from the splay tree because the timeout has
   2942  * expired. This function is then to advance in the list to pick the next
   2943  * timeout to use (skip the already expired ones) and add this node back to
   2944  * the splay tree again.
   2945  *
   2946  * The splay tree only has each sessionhandle as a single node and the nearest
   2947  * timeout is used to sort it on.
   2948  */
   2949 static CURLMcode add_next_timeout(struct curltime now,
   2950                                   struct Curl_multi *multi,
   2951                                   struct Curl_easy *d)
   2952 {
   2953   struct curltime *tv = &d->state.expiretime;
   2954   struct Curl_llist *list = &d->state.timeoutlist;
   2955   struct Curl_llist_node *e;
   2956 
   2957   /* move over the timeout list for this specific handle and remove all
   2958      timeouts that are now passed tense and store the next pending
   2959      timeout in *tv */
   2960   for(e = Curl_llist_head(list); e;) {
   2961     struct Curl_llist_node *n = Curl_node_next(e);
   2962     struct time_node *node = Curl_node_elem(e);
   2963     timediff_t diff = curlx_timediff_us(node->time, now);
   2964     if(diff <= 0)
   2965       /* remove outdated entry */
   2966       Curl_node_remove(e);
   2967     else
   2968       /* the list is sorted so get out on the first mismatch */
   2969       break;
   2970     e = n;
   2971   }
   2972   e = Curl_llist_head(list);
   2973   if(!e) {
   2974     /* clear the expire times within the handles that we remove from the
   2975        splay tree */
   2976     tv->tv_sec = 0;
   2977     tv->tv_usec = 0;
   2978   }
   2979   else {
   2980     struct time_node *node = Curl_node_elem(e);
   2981     /* copy the first entry to 'tv' */
   2982     memcpy(tv, &node->time, sizeof(*tv));
   2983 
   2984     /* Insert this node again into the splay. Keep the timer in the list in
   2985        case we need to recompute future timers. */
   2986     multi->timetree = Curl_splayinsert(*tv, multi->timetree,
   2987                                        &d->state.timenode);
   2988   }
   2989   return CURLM_OK;
   2990 }
   2991 
   2992 struct multi_run_ctx {
   2993   struct Curl_multi *multi;
   2994   struct curltime now;
   2995   size_t run_xfers;
   2996   SIGPIPE_MEMBER(pipe_st);
   2997   bool run_cpool;
   2998 };
   2999 
   3000 static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc)
   3001 {
   3002   struct Curl_multi *multi = mrc->multi;
   3003   struct Curl_easy *data = NULL;
   3004   struct Curl_tree *t = NULL;
   3005 
   3006   /*
   3007    * The loop following here will go on as long as there are expire-times left
   3008    * to process (compared to mrc->now) in the splay and 'data' will be
   3009    * re-assigned for every expired handle we deal with.
   3010    */
   3011   while(1) {
   3012     /* Check if there is one (more) expired timer to deal with! This function
   3013        extracts a matching node if there is one */
   3014     multi->timetree = Curl_splaygetbest(mrc->now, multi->timetree, &t);
   3015     if(!t)
   3016       return;
   3017 
   3018     data = Curl_splayget(t); /* assign this for next loop */
   3019     if(!data)
   3020       continue;
   3021 
   3022     (void)add_next_timeout(mrc->now, multi, data);
   3023     Curl_multi_mark_dirty(data);
   3024   }
   3025 }
   3026 
   3027 static CURLMcode multi_run_dirty(struct multi_run_ctx *mrc)
   3028 {
   3029   struct Curl_multi *multi = mrc->multi;
   3030   CURLMcode result = CURLM_OK;
   3031   unsigned int mid;
   3032 
   3033   if(Curl_uint_bset_first(&multi->dirty, &mid)) {
   3034     do {
   3035       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   3036       if(data) {
   3037         CURL_TRC_M(data, "multi_run_dirty");
   3038 
   3039         if(data == multi->admin) {
   3040           Curl_uint_bset_remove(&multi->dirty, mid);
   3041           mrc->run_cpool = TRUE;
   3042           continue;
   3043         }
   3044         else if(!Curl_uint_bset_contains(&multi->process, mid)) {
   3045           /* We are no longer processing this transfer */
   3046           Curl_uint_bset_remove(&multi->dirty, mid);
   3047           continue;
   3048         }
   3049 
   3050         mrc->run_xfers++;
   3051         sigpipe_apply(data, &mrc->pipe_st);
   3052         /* runsingle() clears the dirty mid */
   3053         result = multi_runsingle(multi, &mrc->now, data);
   3054 
   3055         if(CURLM_OK >= result) {
   3056           /* reassess event handling of data */
   3057           result = Curl_multi_ev_assess_xfer(multi, data);
   3058           if(result)
   3059             goto out;
   3060         }
   3061       }
   3062       else {
   3063         CURL_TRC_M(multi->admin, "multi_run_dirty, %u no longer found", mid);
   3064         Curl_uint_bset_remove(&multi->dirty, mid);
   3065       }
   3066     }
   3067     while(Curl_uint_bset_next(&multi->dirty, mid, &mid));
   3068   }
   3069 
   3070 out:
   3071   return result;
   3072 }
   3073 
   3074 static CURLMcode multi_socket(struct Curl_multi *multi,
   3075                               bool checkall,
   3076                               curl_socket_t s,
   3077                               int ev_bitmask,
   3078                               int *running_handles)
   3079 {
   3080   CURLMcode result = CURLM_OK;
   3081   struct multi_run_ctx mrc;
   3082 
   3083   (void)ev_bitmask;
   3084   memset(&mrc, 0, sizeof(mrc));
   3085   mrc.multi = multi;
   3086   mrc.now = curlx_now();
   3087   sigpipe_init(&mrc.pipe_st);
   3088 
   3089   if(checkall) {
   3090     /* *perform() deals with running_handles on its own */
   3091     result = curl_multi_perform(multi, running_handles);
   3092 
   3093     if(result != CURLM_BAD_HANDLE) {
   3094       /* Reassess event status of all active transfers */
   3095       result = Curl_multi_ev_assess_xfer_bset(multi, &multi->process);
   3096     }
   3097     mrc.run_cpool = TRUE;
   3098     goto out;
   3099   }
   3100 
   3101   if(s != CURL_SOCKET_TIMEOUT) {
   3102     /* Mark all transfers of that socket as dirty */
   3103     Curl_multi_ev_dirty_xfers(multi, s, &mrc.run_cpool);
   3104   }
   3105   else {
   3106     /* Asked to run due to time-out. Clear the 'last_expire_ts' variable to
   3107        force Curl_update_timer() to trigger a callback to the app again even
   3108        if the same timeout is still the one to run after this call. That
   3109        handles the case when the application asks libcurl to run the timeout
   3110        prematurely. */
   3111     memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts));
   3112     mrc.run_cpool = TRUE;
   3113   }
   3114 
   3115   multi_mark_expired_as_dirty(&mrc);
   3116   result = multi_run_dirty(&mrc);
   3117   if(result)
   3118     goto out;
   3119 
   3120   if(mrc.run_xfers) {
   3121     /* Running transfers takes time. With a new timestamp, we might catch
   3122      * other expires which are due now. Instead of telling the application
   3123      * to set a 0 timeout and call us again, we run them here.
   3124      * Do that only once or it might be unfair to transfers on other
   3125      * sockets. */
   3126     mrc.now = curlx_now();
   3127     multi_mark_expired_as_dirty(&mrc);
   3128     result = multi_run_dirty(&mrc);
   3129   }
   3130 
   3131 out:
   3132   if(mrc.run_cpool) {
   3133     sigpipe_apply(multi->admin, &mrc.pipe_st);
   3134     Curl_cshutdn_perform(&multi->cshutdn, multi->admin, s);
   3135   }
   3136   sigpipe_restore(&mrc.pipe_st);
   3137 
   3138   if(multi_ischanged(multi, TRUE))
   3139     process_pending_handles(multi);
   3140 
   3141   if(running_handles) {
   3142     unsigned int running = Curl_multi_xfers_running(multi);
   3143     *running_handles = (running < INT_MAX) ? (int)running : INT_MAX;
   3144   }
   3145 
   3146   if(CURLM_OK >= result)
   3147     result = Curl_update_timer(multi);
   3148   return result;
   3149 }
   3150 
   3151 #undef curl_multi_setopt
   3152 CURLMcode curl_multi_setopt(CURLM *m,
   3153                             CURLMoption option, ...)
   3154 {
   3155   CURLMcode res = CURLM_OK;
   3156   va_list param;
   3157   unsigned long uarg;
   3158   struct Curl_multi *multi = m;
   3159 
   3160   if(!GOOD_MULTI_HANDLE(multi))
   3161     return CURLM_BAD_HANDLE;
   3162 
   3163   if(multi->in_callback)
   3164     return CURLM_RECURSIVE_API_CALL;
   3165 
   3166   va_start(param, option);
   3167 
   3168   switch(option) {
   3169   case CURLMOPT_SOCKETFUNCTION:
   3170     multi->socket_cb = va_arg(param, curl_socket_callback);
   3171     break;
   3172   case CURLMOPT_SOCKETDATA:
   3173     multi->socket_userp = va_arg(param, void *);
   3174     break;
   3175   case CURLMOPT_PUSHFUNCTION:
   3176     multi->push_cb = va_arg(param, curl_push_callback);
   3177     break;
   3178   case CURLMOPT_PUSHDATA:
   3179     multi->push_userp = va_arg(param, void *);
   3180     break;
   3181   case CURLMOPT_PIPELINING:
   3182     multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
   3183     break;
   3184   case CURLMOPT_TIMERFUNCTION:
   3185     multi->timer_cb = va_arg(param, curl_multi_timer_callback);
   3186     break;
   3187   case CURLMOPT_TIMERDATA:
   3188     multi->timer_userp = va_arg(param, void *);
   3189     break;
   3190   case CURLMOPT_MAXCONNECTS:
   3191     uarg = va_arg(param, unsigned long);
   3192     if(uarg <= UINT_MAX)
   3193       multi->maxconnects = (unsigned int)uarg;
   3194     break;
   3195   case CURLMOPT_MAX_HOST_CONNECTIONS:
   3196     multi->max_host_connections = va_arg(param, long);
   3197     break;
   3198   case CURLMOPT_MAX_TOTAL_CONNECTIONS:
   3199     multi->max_total_connections = va_arg(param, long);
   3200     break;
   3201     /* options formerly used for pipelining */
   3202   case CURLMOPT_MAX_PIPELINE_LENGTH:
   3203     break;
   3204   case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
   3205     break;
   3206   case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
   3207     break;
   3208   case CURLMOPT_PIPELINING_SITE_BL:
   3209     break;
   3210   case CURLMOPT_PIPELINING_SERVER_BL:
   3211     break;
   3212   case CURLMOPT_MAX_CONCURRENT_STREAMS:
   3213     {
   3214       long streams = va_arg(param, long);
   3215       if((streams < 1) || (streams > INT_MAX))
   3216         streams = 100;
   3217       multi->max_concurrent_streams = (unsigned int)streams;
   3218     }
   3219     break;
   3220   default:
   3221     res = CURLM_UNKNOWN_OPTION;
   3222     break;
   3223   }
   3224   va_end(param);
   3225   return res;
   3226 }
   3227 
   3228 /* we define curl_multi_socket() in the public multi.h header */
   3229 #undef curl_multi_socket
   3230 
   3231 CURLMcode curl_multi_socket(CURLM *m, curl_socket_t s, int *running_handles)
   3232 {
   3233   struct Curl_multi *multi = m;
   3234   if(multi->in_callback)
   3235     return CURLM_RECURSIVE_API_CALL;
   3236   return multi_socket(multi, FALSE, s, 0, running_handles);
   3237 }
   3238 
   3239 CURLMcode curl_multi_socket_action(CURLM *m, curl_socket_t s,
   3240                                    int ev_bitmask, int *running_handles)
   3241 {
   3242   struct Curl_multi *multi = m;
   3243   if(multi->in_callback)
   3244     return CURLM_RECURSIVE_API_CALL;
   3245   return multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
   3246 }
   3247 
   3248 CURLMcode curl_multi_socket_all(CURLM *m, int *running_handles)
   3249 {
   3250   struct Curl_multi *multi = m;
   3251   if(multi->in_callback)
   3252     return CURLM_RECURSIVE_API_CALL;
   3253   return multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
   3254 }
   3255 
   3256 
   3257 static bool multi_has_dirties(struct Curl_multi *multi)
   3258 {
   3259   unsigned int mid;
   3260   if(Curl_uint_bset_first(&multi->dirty, &mid)) {
   3261     do {
   3262       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   3263       if(data) {
   3264         if(Curl_uint_bset_contains(&multi->process, mid))
   3265           return TRUE;
   3266         /* We are no longer processing this transfer */
   3267         Curl_uint_bset_remove(&multi->dirty, mid);
   3268       }
   3269       else {
   3270         CURL_TRC_M(multi->admin, "dirty transfer %u no longer found", mid);
   3271         Curl_uint_bset_remove(&multi->dirty, mid);
   3272       }
   3273     }
   3274     while(Curl_uint_bset_next(&multi->dirty, mid, &mid));
   3275   }
   3276   return FALSE;
   3277 }
   3278 
   3279 static CURLMcode multi_timeout(struct Curl_multi *multi,
   3280                                struct curltime *expire_time,
   3281                                long *timeout_ms)
   3282 {
   3283   static const struct curltime tv_zero = {0, 0};
   3284 
   3285   if(multi->dead) {
   3286     *timeout_ms = 0;
   3287     return CURLM_OK;
   3288   }
   3289 
   3290   if(multi_has_dirties(multi)) {
   3291     *expire_time = curlx_now();
   3292     *timeout_ms = 0;
   3293     return CURLM_OK;
   3294   }
   3295   else if(multi->timetree) {
   3296     /* we have a tree of expire times */
   3297     struct curltime now = curlx_now();
   3298 
   3299     /* splay the lowest to the bottom */
   3300     multi->timetree = Curl_splay(tv_zero, multi->timetree);
   3301     /* this will not return NULL from a non-empty tree, but some compilers
   3302      * are not convinced of that. Analyzers are hard. */
   3303     *expire_time = multi->timetree ? multi->timetree->key : tv_zero;
   3304 
   3305     /* 'multi->timetree' will be non-NULL here but the compilers sometimes
   3306        yell at us if we assume so */
   3307     if(multi->timetree &&
   3308        curlx_timediff_us(multi->timetree->key, now) > 0) {
   3309       /* some time left before expiration */
   3310       timediff_t diff = curlx_timediff_ceil(multi->timetree->key, now);
   3311       /* this should be safe even on 32-bit archs, as we do not use that
   3312          overly long timeouts */
   3313       *timeout_ms = (long)diff;
   3314     }
   3315     else {
   3316       if(multi->timetree) {
   3317         struct Curl_easy *data = Curl_splayget(multi->timetree);
   3318         CURL_TRC_M(data, "multi_timeout() says this has expired");
   3319       }
   3320       /* 0 means immediately */
   3321       *timeout_ms = 0;
   3322     }
   3323   }
   3324   else {
   3325     *expire_time = tv_zero;
   3326     *timeout_ms = -1;
   3327   }
   3328 
   3329   return CURLM_OK;
   3330 }
   3331 
   3332 CURLMcode curl_multi_timeout(CURLM *m,
   3333                              long *timeout_ms)
   3334 {
   3335   struct curltime expire_time;
   3336   struct Curl_multi *multi = m;
   3337 
   3338   /* First, make some basic checks that the CURLM handle is a good handle */
   3339   if(!GOOD_MULTI_HANDLE(multi))
   3340     return CURLM_BAD_HANDLE;
   3341 
   3342   if(multi->in_callback)
   3343     return CURLM_RECURSIVE_API_CALL;
   3344 
   3345   return multi_timeout(multi, &expire_time, timeout_ms);
   3346 }
   3347 
   3348 #define DEBUG_UPDATE_TIMER    0
   3349 
   3350 /*
   3351  * Tell the application it should update its timers, if it subscribes to the
   3352  * update timer callback.
   3353  */
   3354 CURLMcode Curl_update_timer(struct Curl_multi *multi)
   3355 {
   3356   struct curltime expire_ts;
   3357   long timeout_ms;
   3358   int rc;
   3359   bool set_value = FALSE;
   3360 
   3361   if(!multi->timer_cb || multi->dead)
   3362     return CURLM_OK;
   3363   if(multi_timeout(multi, &expire_ts, &timeout_ms)) {
   3364     return CURLM_OK;
   3365   }
   3366 
   3367   if(timeout_ms < 0 && multi->last_timeout_ms < 0) {
   3368 #if DEBUG_UPDATE_TIMER
   3369     fprintf(stderr, "Curl_update_timer(), still no timeout, no change\n");
   3370 #endif
   3371   }
   3372   else if(timeout_ms < 0) {
   3373     /* there is no timeout now but there was one previously */
   3374 #if DEBUG_UPDATE_TIMER
   3375     fprintf(stderr, "Curl_update_timer(), remove timeout, "
   3376         " last_timeout=%ldms\n", multi->last_timeout_ms);
   3377 #endif
   3378     timeout_ms = -1; /* normalize */
   3379     set_value = TRUE;
   3380   }
   3381   else if(multi->last_timeout_ms < 0) {
   3382 #if DEBUG_UPDATE_TIMER
   3383     fprintf(stderr, "Curl_update_timer(), had no timeout, set now\n");
   3384 #endif
   3385     set_value = TRUE;
   3386   }
   3387   else if(curlx_timediff_us(multi->last_expire_ts, expire_ts)) {
   3388     /* We had a timeout before and have one now, the absolute timestamp
   3389      * differs. The relative timeout_ms may be the same, but the starting
   3390      * point differs. Let the application restart its timer. */
   3391 #if DEBUG_UPDATE_TIMER
   3392     fprintf(stderr, "Curl_update_timer(), expire timestamp changed\n");
   3393 #endif
   3394     set_value = TRUE;
   3395   }
   3396   else {
   3397     /* We have same expire time as previously. Our relative 'timeout_ms'
   3398      * may be different now, but the application has the timer running
   3399      * and we do not to tell it to start this again. */
   3400 #if DEBUG_UPDATE_TIMER
   3401     fprintf(stderr, "Curl_update_timer(), same expire timestamp, no change\n");
   3402 #endif
   3403   }
   3404 
   3405   if(set_value) {
   3406 #if DEBUG_UPDATE_TIMER
   3407     fprintf(stderr, "Curl_update_timer(), set timeout %ldms\n", timeout_ms);
   3408 #endif
   3409     multi->last_expire_ts = expire_ts;
   3410     multi->last_timeout_ms = timeout_ms;
   3411     set_in_callback(multi, TRUE);
   3412     rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
   3413     set_in_callback(multi, FALSE);
   3414     if(rc == -1) {
   3415       multi->dead = TRUE;
   3416       return CURLM_ABORTED_BY_CALLBACK;
   3417     }
   3418   }
   3419   return CURLM_OK;
   3420 }
   3421 
   3422 /*
   3423  * multi_deltimeout()
   3424  *
   3425  * Remove a given timestamp from the list of timeouts.
   3426  */
   3427 static void
   3428 multi_deltimeout(struct Curl_easy *data, expire_id eid)
   3429 {
   3430   struct Curl_llist_node *e;
   3431   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
   3432   /* find and remove the specific node from the list */
   3433   for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
   3434     struct time_node *n = Curl_node_elem(e);
   3435     if(n->eid == eid) {
   3436       Curl_node_remove(e);
   3437       return;
   3438     }
   3439   }
   3440 }
   3441 
   3442 /*
   3443  * multi_addtimeout()
   3444  *
   3445  * Add a timestamp to the list of timeouts. Keep the list sorted so that head
   3446  * of list is always the timeout nearest in time.
   3447  *
   3448  */
   3449 static CURLMcode
   3450 multi_addtimeout(struct Curl_easy *data,
   3451                  struct curltime *stamp,
   3452                  expire_id eid)
   3453 {
   3454   struct Curl_llist_node *e;
   3455   struct time_node *node;
   3456   struct Curl_llist_node *prev = NULL;
   3457   size_t n;
   3458   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
   3459 
   3460   node = &data->state.expires[eid];
   3461 
   3462   /* copy the timestamp and id */
   3463   memcpy(&node->time, stamp, sizeof(*stamp));
   3464   node->eid = eid; /* also marks it as in use */
   3465 
   3466   n = Curl_llist_count(timeoutlist);
   3467   if(n) {
   3468     /* find the correct spot in the list */
   3469     for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
   3470       struct time_node *check = Curl_node_elem(e);
   3471       timediff_t diff = curlx_timediff(check->time, node->time);
   3472       if(diff > 0)
   3473         break;
   3474       prev = e;
   3475     }
   3476 
   3477   }
   3478   /* else
   3479      this is the first timeout on the list */
   3480 
   3481   Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
   3482   return CURLM_OK;
   3483 }
   3484 
   3485 void Curl_expire_ex(struct Curl_easy *data,
   3486                     const struct curltime *nowp,
   3487                     timediff_t milli, expire_id id)
   3488 {
   3489   struct Curl_multi *multi = data->multi;
   3490   struct curltime *curr_expire = &data->state.expiretime;
   3491   struct curltime set;
   3492 
   3493   /* this is only interesting while there is still an associated multi struct
   3494      remaining! */
   3495   if(!multi)
   3496     return;
   3497 
   3498   DEBUGASSERT(id < EXPIRE_LAST);
   3499 
   3500   set = *nowp;
   3501   set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bits conversion */
   3502   set.tv_usec += (int)(milli%1000)*1000;
   3503 
   3504   if(set.tv_usec >= 1000000) {
   3505     set.tv_sec++;
   3506     set.tv_usec -= 1000000;
   3507   }
   3508 
   3509   /* Remove any timer with the same id just in case. */
   3510   multi_deltimeout(data, id);
   3511 
   3512   /* Add it to the timer list. It must stay in the list until it has expired
   3513      in case we need to recompute the minimum timer later. */
   3514   multi_addtimeout(data, &set, id);
   3515 
   3516   if(curr_expire->tv_sec || curr_expire->tv_usec) {
   3517     /* This means that the struct is added as a node in the splay tree.
   3518        Compare if the new time is earlier, and only remove-old/add-new if it
   3519        is. */
   3520     timediff_t diff = curlx_timediff(set, *curr_expire);
   3521     int rc;
   3522 
   3523     if(diff > 0) {
   3524       /* The current splay tree entry is sooner than this new expiry time.
   3525          We do not need to update our splay tree entry. */
   3526       return;
   3527     }
   3528 
   3529     /* Since this is an updated time, we must remove the previous entry from
   3530        the splay tree first and then re-add the new value */
   3531     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
   3532                           &multi->timetree);
   3533     if(rc)
   3534       infof(data, "Internal error removing splay node = %d", rc);
   3535   }
   3536 
   3537   /* Indicate that we are in the splay tree and insert the new timer expiry
   3538      value since it is our local minimum. */
   3539   *curr_expire = set;
   3540   Curl_splayset(&data->state.timenode, data);
   3541   multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree,
   3542                                      &data->state.timenode);
   3543   if(data->id >= 0)
   3544     CURL_TRC_M(data, "set expire[%d] in %" FMT_TIMEDIFF_T "ns",
   3545                id, curlx_timediff_us(set, *nowp));
   3546 }
   3547 
   3548 /*
   3549  * Curl_expire()
   3550  *
   3551  * given a number of milliseconds from now to use to set the 'act before
   3552  * this'-time for the transfer, to be extracted by curl_multi_timeout()
   3553  *
   3554  * The timeout will be added to a queue of timeouts if it defines a moment in
   3555  * time that is later than the current head of queue.
   3556  *
   3557  * Expire replaces a former timeout using the same id if already set.
   3558  */
   3559 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
   3560 {
   3561   struct curltime now = curlx_now();
   3562   Curl_expire_ex(data, &now, milli, id);
   3563 }
   3564 
   3565 /*
   3566  * Curl_expire_done()
   3567  *
   3568  * Removes the expire timer. Marks it as done.
   3569  *
   3570  */
   3571 void Curl_expire_done(struct Curl_easy *data, expire_id id)
   3572 {
   3573   /* remove the timer, if there */
   3574   multi_deltimeout(data, id);
   3575 }
   3576 
   3577 /*
   3578  * Curl_expire_clear()
   3579  *
   3580  * Clear ALL timeout values for this handle.
   3581  */
   3582 bool Curl_expire_clear(struct Curl_easy *data)
   3583 {
   3584   struct Curl_multi *multi = data->multi;
   3585   struct curltime *nowp = &data->state.expiretime;
   3586 
   3587   /* this is only interesting while there is still an associated multi struct
   3588      remaining! */
   3589   if(!multi)
   3590     return FALSE;
   3591 
   3592   if(nowp->tv_sec || nowp->tv_usec) {
   3593     /* Since this is an cleared time, we must remove the previous entry from
   3594        the splay tree */
   3595     struct Curl_llist *list = &data->state.timeoutlist;
   3596     int rc;
   3597 
   3598     rc = Curl_splayremove(multi->timetree, &data->state.timenode,
   3599                           &multi->timetree);
   3600     if(rc)
   3601       infof(data, "Internal error clearing splay node = %d", rc);
   3602 
   3603     /* clear the timeout list too */
   3604     Curl_llist_destroy(list, NULL);
   3605 
   3606     CURL_TRC_M(data, "Expire cleared");
   3607     nowp->tv_sec = 0;
   3608     nowp->tv_usec = 0;
   3609     return TRUE;
   3610   }
   3611   return FALSE;
   3612 }
   3613 
   3614 CURLMcode curl_multi_assign(CURLM *m, curl_socket_t s,
   3615                             void *hashp)
   3616 {
   3617   struct Curl_multi *multi = m;
   3618   if(!GOOD_MULTI_HANDLE(multi))
   3619     return CURLM_BAD_HANDLE;
   3620 
   3621   return Curl_multi_ev_assign(multi, s, hashp);
   3622 }
   3623 
   3624 static void move_pending_to_connect(struct Curl_multi *multi,
   3625                                     struct Curl_easy *data)
   3626 {
   3627   DEBUGASSERT(data->mstate == MSTATE_PENDING);
   3628 
   3629   /* Remove this node from the pending set, add into process set */
   3630   Curl_uint_bset_remove(&multi->pending, data->mid);
   3631   Curl_uint_bset_add(&multi->process, data->mid);
   3632 
   3633   multistate(data, MSTATE_CONNECT);
   3634 
   3635   /* Make sure that the handle will be processed soonish. */
   3636   Curl_expire(data, 0, EXPIRE_RUN_NOW);
   3637 }
   3638 
   3639 /* process_pending_handles() moves a handle from PENDING back into the process
   3640    list and change state to CONNECT.
   3641 
   3642    We do not move all transfers because that can be a significant amount.
   3643    Since this is tried every now and then doing too many too often becomes a
   3644    performance problem.
   3645 
   3646    When there is a change for connection limits like max host connections etc,
   3647    this likely only allows one new transfer. When there is a pipewait change,
   3648    it can potentially allow hundreds of new transfers.
   3649 
   3650    We could consider an improvement where we store the queue reason and allow
   3651    more pipewait rechecks than others.
   3652 */
   3653 static void process_pending_handles(struct Curl_multi *multi)
   3654 {
   3655   unsigned int mid;
   3656   if(Curl_uint_bset_first(&multi->pending, &mid)) {
   3657     do {
   3658       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
   3659       DEBUGASSERT(data);
   3660       if(data)
   3661         move_pending_to_connect(multi, data);
   3662     }
   3663     while(Curl_uint_bset_next(&multi->pending, mid, &mid));
   3664   }
   3665 }
   3666 
   3667 void Curl_set_in_callback(struct Curl_easy *data, bool value)
   3668 {
   3669   if(data && data->multi)
   3670     data->multi->in_callback = value;
   3671 }
   3672 
   3673 bool Curl_is_in_callback(struct Curl_easy *data)
   3674 {
   3675   return data && data->multi && data->multi->in_callback;
   3676 }
   3677 
   3678 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
   3679 {
   3680   DEBUGASSERT(multi);
   3681   return multi->max_concurrent_streams;
   3682 }
   3683 
   3684 CURL **curl_multi_get_handles(CURLM *m)
   3685 {
   3686   struct Curl_multi *multi = m;
   3687   void *entry;
   3688   unsigned int count = Curl_uint_tbl_count(&multi->xfers);
   3689   CURL **a = malloc(sizeof(struct Curl_easy *) * (count + 1));
   3690   if(a) {
   3691     unsigned int i = 0, mid;
   3692 
   3693     if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
   3694       do {
   3695         struct Curl_easy *data = entry;
   3696         DEBUGASSERT(i < count);
   3697         if(!data->state.internal)
   3698           a[i++] = data;
   3699       }
   3700       while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry));
   3701     }
   3702     a[i] = NULL; /* last entry is a NULL */
   3703   }
   3704   return a;
   3705 }
   3706 
   3707 CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data,
   3708                                     char **pbuf, size_t *pbuflen)
   3709 {
   3710   DEBUGASSERT(data);
   3711   DEBUGASSERT(data->multi);
   3712   *pbuf = NULL;
   3713   *pbuflen = 0;
   3714   if(!data->multi) {
   3715     failf(data, "transfer has no multi handle");
   3716     return CURLE_FAILED_INIT;
   3717   }
   3718   if(!data->set.buffer_size) {
   3719     failf(data, "transfer buffer size is 0");
   3720     return CURLE_FAILED_INIT;
   3721   }
   3722   if(data->multi->xfer_buf_borrowed) {
   3723     failf(data, "attempt to borrow xfer_buf when already borrowed");
   3724     return CURLE_AGAIN;
   3725   }
   3726 
   3727   if(data->multi->xfer_buf &&
   3728      data->set.buffer_size > data->multi->xfer_buf_len) {
   3729     /* not large enough, get a new one */
   3730     free(data->multi->xfer_buf);
   3731     data->multi->xfer_buf = NULL;
   3732     data->multi->xfer_buf_len = 0;
   3733   }
   3734 
   3735   if(!data->multi->xfer_buf) {
   3736     data->multi->xfer_buf = malloc((size_t)data->set.buffer_size);
   3737     if(!data->multi->xfer_buf) {
   3738       failf(data, "could not allocate xfer_buf of %zu bytes",
   3739             (size_t)data->set.buffer_size);
   3740       return CURLE_OUT_OF_MEMORY;
   3741     }
   3742     data->multi->xfer_buf_len = data->set.buffer_size;
   3743   }
   3744 
   3745   data->multi->xfer_buf_borrowed = TRUE;
   3746   *pbuf = data->multi->xfer_buf;
   3747   *pbuflen = data->multi->xfer_buf_len;
   3748   return CURLE_OK;
   3749 }
   3750 
   3751 void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf)
   3752 {
   3753   (void)buf;
   3754   DEBUGASSERT(data);
   3755   DEBUGASSERT(data->multi);
   3756   DEBUGASSERT(!buf || data->multi->xfer_buf == buf);
   3757   data->multi->xfer_buf_borrowed = FALSE;
   3758 }
   3759 
   3760 CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data,
   3761                                       char **pbuf, size_t *pbuflen)
   3762 {
   3763   DEBUGASSERT(data);
   3764   DEBUGASSERT(data->multi);
   3765   *pbuf = NULL;
   3766   *pbuflen = 0;
   3767   if(!data->multi) {
   3768     failf(data, "transfer has no multi handle");
   3769     return CURLE_FAILED_INIT;
   3770   }
   3771   if(!data->set.upload_buffer_size) {
   3772     failf(data, "transfer upload buffer size is 0");
   3773     return CURLE_FAILED_INIT;
   3774   }
   3775   if(data->multi->xfer_ulbuf_borrowed) {
   3776     failf(data, "attempt to borrow xfer_ulbuf when already borrowed");
   3777     return CURLE_AGAIN;
   3778   }
   3779 
   3780   if(data->multi->xfer_ulbuf &&
   3781      data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) {
   3782     /* not large enough, get a new one */
   3783     free(data->multi->xfer_ulbuf);
   3784     data->multi->xfer_ulbuf = NULL;
   3785     data->multi->xfer_ulbuf_len = 0;
   3786   }
   3787 
   3788   if(!data->multi->xfer_ulbuf) {
   3789     data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size);
   3790     if(!data->multi->xfer_ulbuf) {
   3791       failf(data, "could not allocate xfer_ulbuf of %zu bytes",
   3792             (size_t)data->set.upload_buffer_size);
   3793       return CURLE_OUT_OF_MEMORY;
   3794     }
   3795     data->multi->xfer_ulbuf_len = data->set.upload_buffer_size;
   3796   }
   3797 
   3798   data->multi->xfer_ulbuf_borrowed = TRUE;
   3799   *pbuf = data->multi->xfer_ulbuf;
   3800   *pbuflen = data->multi->xfer_ulbuf_len;
   3801   return CURLE_OK;
   3802 }
   3803 
   3804 void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf)
   3805 {
   3806   (void)buf;
   3807   DEBUGASSERT(data);
   3808   DEBUGASSERT(data->multi);
   3809   DEBUGASSERT(!buf || data->multi->xfer_ulbuf == buf);
   3810   data->multi->xfer_ulbuf_borrowed = FALSE;
   3811 }
   3812 
   3813 CURLcode Curl_multi_xfer_sockbuf_borrow(struct Curl_easy *data,
   3814                                         size_t blen, char **pbuf)
   3815 {
   3816   DEBUGASSERT(data);
   3817   DEBUGASSERT(data->multi);
   3818   *pbuf = NULL;
   3819   if(!data->multi) {
   3820     failf(data, "transfer has no multi handle");
   3821     return CURLE_FAILED_INIT;
   3822   }
   3823   if(data->multi->xfer_sockbuf_borrowed) {
   3824     failf(data, "attempt to borrow xfer_sockbuf when already borrowed");
   3825     return CURLE_AGAIN;
   3826   }
   3827 
   3828   if(data->multi->xfer_sockbuf && blen > data->multi->xfer_sockbuf_len) {
   3829     /* not large enough, get a new one */
   3830     free(data->multi->xfer_sockbuf);
   3831     data->multi->xfer_sockbuf = NULL;
   3832     data->multi->xfer_sockbuf_len = 0;
   3833   }
   3834 
   3835   if(!data->multi->xfer_sockbuf) {
   3836     data->multi->xfer_sockbuf = malloc(blen);
   3837     if(!data->multi->xfer_sockbuf) {
   3838       failf(data, "could not allocate xfer_sockbuf of %zu bytes", blen);
   3839       return CURLE_OUT_OF_MEMORY;
   3840     }
   3841     data->multi->xfer_sockbuf_len = blen;
   3842   }
   3843 
   3844   data->multi->xfer_sockbuf_borrowed = TRUE;
   3845   *pbuf = data->multi->xfer_sockbuf;
   3846   return CURLE_OK;
   3847 }
   3848 
   3849 void Curl_multi_xfer_sockbuf_release(struct Curl_easy *data, char *buf)
   3850 {
   3851   (void)buf;
   3852   DEBUGASSERT(data);
   3853   DEBUGASSERT(data->multi);
   3854   DEBUGASSERT(!buf || data->multi->xfer_sockbuf == buf);
   3855   data->multi->xfer_sockbuf_borrowed = FALSE;
   3856 }
   3857 
   3858 static void multi_xfer_bufs_free(struct Curl_multi *multi)
   3859 {
   3860   DEBUGASSERT(multi);
   3861   Curl_safefree(multi->xfer_buf);
   3862   multi->xfer_buf_len = 0;
   3863   multi->xfer_buf_borrowed = FALSE;
   3864   Curl_safefree(multi->xfer_ulbuf);
   3865   multi->xfer_ulbuf_len = 0;
   3866   multi->xfer_ulbuf_borrowed = FALSE;
   3867   Curl_safefree(multi->xfer_sockbuf);
   3868   multi->xfer_sockbuf_len = 0;
   3869   multi->xfer_sockbuf_borrowed = FALSE;
   3870 }
   3871 
   3872 struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi,
   3873                                       unsigned int mid)
   3874 {
   3875   struct Curl_easy *data = mid ? Curl_uint_tbl_get(&multi->xfers, mid) : NULL;
   3876   if(data && GOOD_EASY_HANDLE(data))
   3877     return data;
   3878   CURL_TRC_M(multi->admin, "invalid easy handle in xfer table for mid=%u",
   3879              mid);
   3880   Curl_uint_tbl_remove(&multi->xfers, mid);
   3881   return NULL;
   3882 }
   3883 
   3884 unsigned int Curl_multi_xfers_running(struct Curl_multi *multi)
   3885 {
   3886   return multi->xfers_alive;
   3887 }
   3888 
   3889 void Curl_multi_mark_dirty(struct Curl_easy *data)
   3890 {
   3891   if(data->multi && data->mid != UINT_MAX)
   3892     Curl_uint_bset_add(&data->multi->dirty, data->mid);
   3893 }
   3894 
   3895 #ifdef DEBUGBUILD
   3896 static void multi_xfer_dump(struct Curl_multi *multi, unsigned int mid,
   3897                             void *entry)
   3898 {
   3899   struct Curl_easy *data = entry;
   3900 
   3901   (void)multi;
   3902   if(!data) {
   3903     fprintf(stderr, "mid=%u, entry=NULL, bug in xfer table?\n", mid);
   3904   }
   3905   else {
   3906     fprintf(stderr, "mid=%u, magic=%s, p=%p, id=%" FMT_OFF_T ", url=%s\n",
   3907             mid, (data->magic == CURLEASY_MAGIC_NUMBER) ? "GOOD" : "BAD!",
   3908             (void *)data, data->id, data->state.url);
   3909   }
   3910 }
   3911 
   3912 static void multi_xfer_tbl_dump(struct Curl_multi *multi)
   3913 {
   3914   unsigned int mid;
   3915   void *entry;
   3916   fprintf(stderr, "=== multi xfer table (count=%u, capacity=%u\n",
   3917           Curl_uint_tbl_count(&multi->xfers),
   3918           Curl_uint_tbl_capacity(&multi->xfers));
   3919   if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
   3920     multi_xfer_dump(multi, mid, entry);
   3921     while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry))
   3922       multi_xfer_dump(multi, mid, entry);
   3923   }
   3924   fprintf(stderr, "===\n");
   3925   fflush(stderr);
   3926 }
   3927 #endif /* DEBUGBUILD */