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