Annotation of embedaddon/curl/lib/multi.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>