multi.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #include <curl/curl.h>
00026 
00027 #include "urldata.h"
00028 #include "transfer.h"
00029 #include "url.h"
00030 #include "connect.h"
00031 #include "progress.h"
00032 #include "easyif.h"
00033 #include "share.h"
00034 #include "multiif.h"
00035 #include "sendf.h"
00036 #include "timeval.h"
00037 #include "http.h"
00038 #include "select.h"
00039 #include "warnless.h"
00040 #include "speedcheck.h"
00041 #include "conncache.h"
00042 #include "multihandle.h"
00043 #include "pipeline.h"
00044 #include "sigpipe.h"
00045 #include "vtls/vtls.h"
00046 #include "connect.h"
00047 /* The last 3 #include files should be in this order */
00048 #include "curl_printf.h"
00049 #include "curl_memory.h"
00050 #include "memdebug.h"
00051 
00052 /*
00053   CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
00054   to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes.  Still, every
00055   CURL handle takes 45-50 K memory, therefore this 3K are not significant.
00056 */
00057 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
00058 #define CURL_SOCKET_HASH_TABLE_SIZE 911
00059 #endif
00060 
00061 #define CURL_CONNECTION_HASH_SIZE 97
00062 
00063 #define CURL_MULTI_HANDLE 0x000bab1e
00064 
00065 #define GOOD_MULTI_HANDLE(x) \
00066   ((x) && (x)->type == CURL_MULTI_HANDLE)
00067 
00068 static void singlesocket(struct Curl_multi *multi,
00069                          struct Curl_easy *data);
00070 static int update_timer(struct Curl_multi *multi);
00071 
00072 static CURLMcode add_next_timeout(struct timeval now,
00073                                   struct Curl_multi *multi,
00074                                   struct Curl_easy *d);
00075 static CURLMcode multi_timeout(struct Curl_multi *multi,
00076                                long *timeout_ms);
00077 
00078 #ifdef DEBUGBUILD
00079 static const char * const statename[]={
00080   "INIT",
00081   "CONNECT_PEND",
00082   "CONNECT",
00083   "WAITRESOLVE",
00084   "WAITCONNECT",
00085   "WAITPROXYCONNECT",
00086   "SENDPROTOCONNECT",
00087   "PROTOCONNECT",
00088   "WAITDO",
00089   "DO",
00090   "DOING",
00091   "DO_MORE",
00092   "DO_DONE",
00093   "WAITPERFORM",
00094   "PERFORM",
00095   "TOOFAST",
00096   "DONE",
00097   "COMPLETED",
00098   "MSGSENT",
00099 };
00100 #endif
00101 
00102 static void multi_freetimeout(void *a, void *b);
00103 
00104 /* function pointer called once when switching TO a state */
00105 typedef void (*init_multistate_func)(struct Curl_easy *data);
00106 
00107 /* always use this function to change state, to make debugging easier */
00108 static void mstate(struct Curl_easy *data, CURLMstate state
00109 #ifdef DEBUGBUILD
00110                    , int lineno
00111 #endif
00112 )
00113 {
00114   CURLMstate oldstate = data->mstate;
00115   static const init_multistate_func finit[CURLM_STATE_LAST] = {
00116     NULL,
00117     NULL,
00118     Curl_init_CONNECT, /* CONNECT */
00119     /* the rest is NULL too */
00120   };
00121 
00122 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
00123   (void) lineno;
00124 #endif
00125 
00126   if(oldstate == state)
00127     /* don't bother when the new state is the same as the old state */
00128     return;
00129 
00130   data->mstate = state;
00131 
00132 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
00133   if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
00134      data->mstate < CURLM_STATE_COMPLETED) {
00135     long connection_id = -5000;
00136 
00137     if(data->easy_conn)
00138       connection_id = data->easy_conn->connection_id;
00139 
00140     infof(data,
00141           "STATE: %s => %s handle %p; line %d (connection #%ld)\n",
00142           statename[oldstate], statename[data->mstate],
00143           (void *)data, lineno, connection_id);
00144   }
00145 #endif
00146 
00147   if(state == CURLM_STATE_COMPLETED)
00148     /* changing to COMPLETED means there's one less easy handle 'alive' */
00149     data->multi->num_alive--;
00150 
00151   /* if this state has an init-function, run it */
00152   if(finit[state])
00153     finit[state](data);
00154 }
00155 
00156 #ifndef DEBUGBUILD
00157 #define multistate(x,y) mstate(x,y)
00158 #else
00159 #define multistate(x,y) mstate(x,y, __LINE__)
00160 #endif
00161 
00162 /*
00163  * We add one of these structs to the sockhash for a particular socket
00164  */
00165 
00166 struct Curl_sh_entry {
00167   struct Curl_easy *easy;
00168   int action;  /* what action READ/WRITE this socket waits for */
00169   curl_socket_t socket; /* mainly to ease debugging */
00170   void *socketp; /* settable by users with curl_multi_assign() */
00171 };
00172 /* bits for 'action' having no bits means this socket is not expecting any
00173    action */
00174 #define SH_READ  1
00175 #define SH_WRITE 2
00176 
00177 /* look up a given socket in the socket hash, skip invalid sockets */
00178 static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
00179                                          curl_socket_t s)
00180 {
00181   if(s != CURL_SOCKET_BAD)
00182     /* only look for proper sockets */
00183     return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
00184   return NULL;
00185 }
00186 
00187 /* make sure this socket is present in the hash for this handle */
00188 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
00189                                          curl_socket_t s,
00190                                          struct Curl_easy *data)
00191 {
00192   struct Curl_sh_entry *there = sh_getentry(sh, s);
00193   struct Curl_sh_entry *check;
00194 
00195   if(there)
00196     /* it is present, return fine */
00197     return there;
00198 
00199   /* not present, add it */
00200   check = calloc(1, sizeof(struct Curl_sh_entry));
00201   if(!check)
00202     return NULL; /* major failure */
00203 
00204   check->easy = data;
00205   check->socket = s;
00206 
00207   /* make/add new hash entry */
00208   if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
00209     free(check);
00210     return NULL; /* major failure */
00211   }
00212 
00213   return check; /* things are good in sockhash land */
00214 }
00215 
00216 
00217 /* delete the given socket + handle from the hash */
00218 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
00219 {
00220   /* We remove the hash entry. This will end up in a call to
00221      sh_freeentry(). */
00222   Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
00223 }
00224 
00225 /*
00226  * free a sockhash entry
00227  */
00228 static void sh_freeentry(void *freethis)
00229 {
00230   struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
00231 
00232   free(p);
00233 }
00234 
00235 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
00236 {
00237   (void) k1_len; (void) k2_len;
00238 
00239   return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
00240 }
00241 
00242 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
00243 {
00244   curl_socket_t fd = *((curl_socket_t *) key);
00245   (void) key_length;
00246 
00247   return (fd % slots_num);
00248 }
00249 
00250 /*
00251  * sh_init() creates a new socket hash and returns the handle for it.
00252  *
00253  * Quote from README.multi_socket:
00254  *
00255  * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
00256  * is somewhat of a bottle neck. Its current implementation may be a bit too
00257  * limiting. It simply has a fixed-size array, and on each entry in the array
00258  * it has a linked list with entries. So the hash only checks which list to
00259  * scan through. The code I had used so for used a list with merely 7 slots
00260  * (as that is what the DNS hash uses) but with 7000 connections that would
00261  * make an average of 1000 nodes in each list to run through. I upped that to
00262  * 97 slots (I believe a prime is suitable) and noticed a significant speed
00263  * increase.  I need to reconsider the hash implementation or use a rather
00264  * large default value like this. At 9000 connections I was still below 10us
00265  * per call."
00266  *
00267  */
00268 static int sh_init(struct curl_hash *hash, int hashsize)
00269 {
00270   return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
00271                         sh_freeentry);
00272 }
00273 
00274 /*
00275  * multi_addmsg()
00276  *
00277  * Called when a transfer is completed. Adds the given msg pointer to
00278  * the list kept in the multi handle.
00279  */
00280 static CURLMcode multi_addmsg(struct Curl_multi *multi,
00281                               struct Curl_message *msg)
00282 {
00283   if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
00284     return CURLM_OUT_OF_MEMORY;
00285 
00286   return CURLM_OK;
00287 }
00288 
00289 /*
00290  * multi_freeamsg()
00291  *
00292  * Callback used by the llist system when a single list entry is destroyed.
00293  */
00294 static void multi_freeamsg(void *a, void *b)
00295 {
00296   (void)a;
00297   (void)b;
00298 }
00299 
00300 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
00301                                      int chashsize) /* connection hash */
00302 {
00303   struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
00304 
00305   if(!multi)
00306     return NULL;
00307 
00308   multi->type = CURL_MULTI_HANDLE;
00309 
00310   if(Curl_mk_dnscache(&multi->hostcache))
00311     goto error;
00312 
00313   if(sh_init(&multi->sockhash, hashsize))
00314     goto error;
00315 
00316   if(Curl_conncache_init(&multi->conn_cache, chashsize))
00317     goto error;
00318 
00319   multi->msglist = Curl_llist_alloc(multi_freeamsg);
00320   if(!multi->msglist)
00321     goto error;
00322 
00323   multi->pending = Curl_llist_alloc(multi_freeamsg);
00324   if(!multi->pending)
00325     goto error;
00326 
00327   /* allocate a new easy handle to use when closing cached connections */
00328   multi->closure_handle = curl_easy_init();
00329   if(!multi->closure_handle)
00330     goto error;
00331 
00332   multi->closure_handle->multi = multi;
00333   multi->closure_handle->state.conn_cache = &multi->conn_cache;
00334 
00335   multi->max_pipeline_length = 5;
00336 
00337   /* -1 means it not set by user, use the default value */
00338   multi->maxconnects = -1;
00339   return multi;
00340 
00341   error:
00342 
00343   Curl_hash_destroy(&multi->sockhash);
00344   Curl_hash_destroy(&multi->hostcache);
00345   Curl_conncache_destroy(&multi->conn_cache);
00346   Curl_close(multi->closure_handle);
00347   multi->closure_handle = NULL;
00348   Curl_llist_destroy(multi->msglist, NULL);
00349   Curl_llist_destroy(multi->pending, NULL);
00350 
00351   free(multi);
00352   return NULL;
00353 }
00354 
00355 struct Curl_multi *curl_multi_init(void)
00356 {
00357   return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
00358                            CURL_CONNECTION_HASH_SIZE);
00359 }
00360 
00361 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
00362                                 struct Curl_easy *data)
00363 {
00364   struct curl_llist *timeoutlist;
00365 
00366   /* First, make some basic checks that the CURLM handle is a good handle */
00367   if(!GOOD_MULTI_HANDLE(multi))
00368     return CURLM_BAD_HANDLE;
00369 
00370   /* Verify that we got a somewhat good easy handle too */
00371   if(!GOOD_EASY_HANDLE(data))
00372     return CURLM_BAD_EASY_HANDLE;
00373 
00374   /* Prevent users from adding same easy handle more than once and prevent
00375      adding to more than one multi stack */
00376   if(data->multi)
00377     return CURLM_ADDED_ALREADY;
00378 
00379   /* Allocate and initialize timeout list for easy handle */
00380   timeoutlist = Curl_llist_alloc(multi_freetimeout);
00381   if(!timeoutlist)
00382     return CURLM_OUT_OF_MEMORY;
00383 
00384   /*
00385    * No failure allowed in this function beyond this point. And no
00386    * modification of easy nor multi handle allowed before this except for
00387    * potential multi's connection cache growing which won't be undone in this
00388    * function no matter what.
00389    */
00390 
00391   /* Make easy handle use timeout list initialized above */
00392   data->state.timeoutlist = timeoutlist;
00393   timeoutlist = NULL;
00394 
00395   /* set the easy handle */
00396   multistate(data, CURLM_STATE_INIT);
00397 
00398   if((data->set.global_dns_cache) &&
00399      (data->dns.hostcachetype != HCACHE_GLOBAL)) {
00400     /* global dns cache was requested but still isn't */
00401     struct curl_hash *global = Curl_global_host_cache_init();
00402     if(global) {
00403       /* only do this if the global cache init works */
00404       data->dns.hostcache = global;
00405       data->dns.hostcachetype = HCACHE_GLOBAL;
00406     }
00407   }
00408   /* for multi interface connections, we share DNS cache automatically if the
00409      easy handle's one is currently not set. */
00410   else if(!data->dns.hostcache ||
00411      (data->dns.hostcachetype == HCACHE_NONE)) {
00412     data->dns.hostcache = &multi->hostcache;
00413     data->dns.hostcachetype = HCACHE_MULTI;
00414   }
00415 
00416   /* Point to the multi's connection cache */
00417   data->state.conn_cache = &multi->conn_cache;
00418 
00419   /* This adds the new entry at the 'end' of the doubly-linked circular
00420      list of Curl_easy structs to try and maintain a FIFO queue so
00421      the pipelined requests are in order. */
00422 
00423   /* We add this new entry last in the list. */
00424 
00425   data->next = NULL; /* end of the line */
00426   if(multi->easyp) {
00427     struct Curl_easy *last = multi->easylp;
00428     last->next = data;
00429     data->prev = last;
00430     multi->easylp = data; /* the new last node */
00431   }
00432   else {
00433     /* first node, make prev NULL! */
00434     data->prev = NULL;
00435     multi->easylp = multi->easyp = data; /* both first and last */
00436   }
00437 
00438   /* make the Curl_easy refer back to this multi handle */
00439   data->multi = multi;
00440 
00441   /* Set the timeout for this handle to expire really soon so that it will
00442      be taken care of even when this handle is added in the midst of operation
00443      when only the curl_multi_socket() API is used. During that flow, only
00444      sockets that time-out or have actions will be dealt with. Since this
00445      handle has no action yet, we make sure it times out to get things to
00446      happen. */
00447   Curl_expire(data, 0);
00448 
00449   /* increase the node-counter */
00450   multi->num_easy++;
00451 
00452   /* increase the alive-counter */
00453   multi->num_alive++;
00454 
00455   /* A somewhat crude work-around for a little glitch in update_timer() that
00456      happens if the lastcall time is set to the same time when the handle is
00457      removed as when the next handle is added, as then the check in
00458      update_timer() that prevents calling the application multiple times with
00459      the same timer infor will not trigger and then the new handle's timeout
00460      will not be notified to the app.
00461 
00462      The work-around is thus simply to clear the 'lastcall' variable to force
00463      update_timer() to always trigger a callback to the app when a new easy
00464      handle is added */
00465   memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
00466 
00467   /* The closure handle only ever has default timeouts set. To improve the
00468      state somewhat we clone the timeouts from each added handle so that the
00469      closure handle always has the same timeouts as the most recently added
00470      easy handle. */
00471   multi->closure_handle->set.timeout = data->set.timeout;
00472   multi->closure_handle->set.server_response_timeout =
00473     data->set.server_response_timeout;
00474 
00475   update_timer(multi);
00476   return CURLM_OK;
00477 }
00478 
00479 #if 0
00480 /* Debug-function, used like this:
00481  *
00482  * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
00483  *
00484  * Enable the hash print function first by editing hash.c
00485  */
00486 static void debug_print_sock_hash(void *p)
00487 {
00488   struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
00489 
00490   fprintf(stderr, " [easy %p/magic %x/socket %d]",
00491           (void *)sh->data, sh->data->magic, (int)sh->socket);
00492 }
00493 #endif
00494 
00495 /* Mark the connection as 'idle', or close it if the cache is full.
00496    Returns TRUE if the connection is kept, or FALSE if it was closed. */
00497 static bool
00498 ConnectionDone(struct Curl_easy *data, struct connectdata *conn)
00499 {
00500   /* data->multi->maxconnects can be negative, deal with it. */
00501   size_t maxconnects =
00502     (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
00503     data->multi->maxconnects;
00504   struct connectdata *conn_candidate = NULL;
00505 
00506   /* Mark the current connection as 'unused' */
00507   conn->inuse = FALSE;
00508 
00509   if(maxconnects > 0 &&
00510      data->state.conn_cache->num_connections > maxconnects) {
00511     infof(data, "Connection cache is full, closing the oldest one.\n");
00512 
00513     conn_candidate = Curl_oldest_idle_connection(data);
00514 
00515     if(conn_candidate) {
00516       /* Set the connection's owner correctly */
00517       conn_candidate->data = data;
00518 
00519       /* the winner gets the honour of being disconnected */
00520       (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
00521     }
00522   }
00523 
00524   return (conn_candidate == conn) ? FALSE : TRUE;
00525 }
00526 
00527 static CURLcode multi_done(struct connectdata **connp,
00528                           CURLcode status,  /* an error if this is called
00529                                                after an error was detected */
00530                           bool premature)
00531 {
00532   CURLcode result;
00533   struct connectdata *conn;
00534   struct Curl_easy *data;
00535 
00536   DEBUGASSERT(*connp);
00537 
00538   conn = *connp;
00539   data = conn->data;
00540 
00541   DEBUGF(infof(data, "multi_done\n"));
00542 
00543   if(data->state.done)
00544     /* Stop if multi_done() has already been called */
00545     return CURLE_OK;
00546 
00547   Curl_getoff_all_pipelines(data, conn);
00548 
00549   /* Cleanup possible redirect junk */
00550   free(data->req.newurl);
00551   data->req.newurl = NULL;
00552   free(data->req.location);
00553   data->req.location = NULL;
00554 
00555   switch(status) {
00556   case CURLE_ABORTED_BY_CALLBACK:
00557   case CURLE_READ_ERROR:
00558   case CURLE_WRITE_ERROR:
00559     /* When we're aborted due to a callback return code it basically have to
00560        be counted as premature as there is trouble ahead if we don't. We have
00561        many callbacks and protocols work differently, we could potentially do
00562        this more fine-grained in the future. */
00563     premature = TRUE;
00564   default:
00565     break;
00566   }
00567 
00568   /* this calls the protocol-specific function pointer previously set */
00569   if(conn->handler->done)
00570     result = conn->handler->done(conn, status, premature);
00571   else
00572     result = status;
00573 
00574   if(CURLE_ABORTED_BY_CALLBACK != result) {
00575     /* avoid this if we already aborted by callback to avoid this calling
00576        another callback */
00577     CURLcode rc = Curl_pgrsDone(conn);
00578     if(!result && rc)
00579       result = CURLE_ABORTED_BY_CALLBACK;
00580   }
00581 
00582   if(conn->send_pipe->size + conn->recv_pipe->size != 0 &&
00583      !data->set.reuse_forbid &&
00584      !conn->bits.close) {
00585     /* Stop if pipeline is not empty and we do not have to close
00586        connection. */
00587     data->easy_conn = NULL;
00588     DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
00589     return CURLE_OK;
00590   }
00591 
00592   data->state.done = TRUE; /* called just now! */
00593   Curl_resolver_cancel(conn);
00594 
00595   if(conn->dns_entry) {
00596     Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
00597     conn->dns_entry = NULL;
00598   }
00599 
00600   /* if the transfer was completed in a paused state there can be buffered
00601      data left to write and then kill */
00602   free(data->state.tempwrite);
00603   data->state.tempwrite = NULL;
00604 
00605   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
00606      forced us to close this connection. This is ignored for requests taking
00607      place in a NTLM authentication handshake
00608 
00609      if conn->bits.close is TRUE, it means that the connection should be
00610      closed in spite of all our efforts to be nice, due to protocol
00611      restrictions in our or the server's end
00612 
00613      if premature is TRUE, it means this connection was said to be DONE before
00614      the entire request operation is complete and thus we can't know in what
00615      state it is for re-using, so we're forced to close it. In a perfect world
00616      we can add code that keep track of if we really must close it here or not,
00617      but currently we have no such detail knowledge.
00618   */
00619 
00620   if((data->set.reuse_forbid
00621 #if defined(USE_NTLM)
00622       && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
00623            conn->proxyntlm.state == NTLMSTATE_TYPE2)
00624 #endif
00625      ) || conn->bits.close || premature) {
00626     CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
00627 
00628     /* If we had an error already, make sure we return that one. But
00629        if we got a new error, return that. */
00630     if(!result && res2)
00631       result = res2;
00632   }
00633   else {
00634     /* the connection is no longer in use */
00635     if(ConnectionDone(data, conn)) {
00636       /* remember the most recently used connection */
00637       data->state.lastconnect = conn;
00638 
00639       infof(data, "Connection #%ld to host %s left intact\n",
00640             conn->connection_id,
00641             conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
00642     }
00643     else
00644       data->state.lastconnect = NULL;
00645   }
00646 
00647   *connp = NULL; /* to make the caller of this function better detect that
00648                     this was either closed or handed over to the connection
00649                     cache here, and therefore cannot be used from this point on
00650                  */
00651   Curl_free_request_state(data);
00652 
00653   return result;
00654 }
00655 
00656 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
00657                                    struct Curl_easy *data)
00658 {
00659   struct Curl_easy *easy = data;
00660   bool premature;
00661   bool easy_owns_conn;
00662   struct curl_llist_element *e;
00663 
00664   /* First, make some basic checks that the CURLM handle is a good handle */
00665   if(!GOOD_MULTI_HANDLE(multi))
00666     return CURLM_BAD_HANDLE;
00667 
00668   /* Verify that we got a somewhat good easy handle too */
00669   if(!GOOD_EASY_HANDLE(data))
00670     return CURLM_BAD_EASY_HANDLE;
00671 
00672   /* Prevent users from trying to remove same easy handle more than once */
00673   if(!data->multi)
00674     return CURLM_OK; /* it is already removed so let's say it is fine! */
00675 
00676   premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
00677   easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
00678     TRUE : FALSE;
00679 
00680   /* If the 'state' is not INIT or COMPLETED, we might need to do something
00681      nice to put the easy_handle in a good known state when this returns. */
00682   if(premature) {
00683     /* this handle is "alive" so we need to count down the total number of
00684        alive connections when this is removed */
00685     multi->num_alive--;
00686 
00687     /* When this handle gets removed, other handles may be able to get the
00688        connection */
00689     Curl_multi_process_pending_handles(multi);
00690   }
00691 
00692   if(data->easy_conn &&
00693      data->mstate > CURLM_STATE_DO &&
00694      data->mstate < CURLM_STATE_COMPLETED) {
00695     /* If the handle is in a pipeline and has started sending off its
00696        request but not received its response yet, we need to close
00697        connection. */
00698     streamclose(data->easy_conn, "Removed with partial response");
00699     /* Set connection owner so that the DONE function closes it.  We can
00700        safely do this here since connection is killed. */
00701     data->easy_conn->data = easy;
00702     easy_owns_conn = TRUE;
00703   }
00704 
00705   /* The timer must be shut down before data->multi is set to NULL,
00706      else the timenode will remain in the splay tree after
00707      curl_easy_cleanup is called. */
00708   Curl_expire_clear(data);
00709 
00710   if(data->dns.hostcachetype == HCACHE_MULTI) {
00711     /* stop using the multi handle's DNS cache */
00712     data->dns.hostcache = NULL;
00713     data->dns.hostcachetype = HCACHE_NONE;
00714   }
00715 
00716   if(data->easy_conn) {
00717 
00718     /* we must call multi_done() here (if we still own the connection) so that
00719        we don't leave a half-baked one around */
00720     if(easy_owns_conn) {
00721 
00722       /* multi_done() clears the conn->data field to lose the association
00723          between the easy handle and the connection
00724 
00725          Note that this ignores the return code simply because there's
00726          nothing really useful to do with it anyway! */
00727       (void)multi_done(&data->easy_conn, data->result, premature);
00728     }
00729     else
00730       /* Clear connection pipelines, if multi_done above was not called */
00731       Curl_getoff_all_pipelines(data, data->easy_conn);
00732   }
00733 
00734   Curl_wildcard_dtor(&data->wildcard);
00735 
00736   /* destroy the timeout list that is held in the easy handle, do this *after*
00737      multi_done() as that may actually call Curl_expire that uses this */
00738   if(data->state.timeoutlist) {
00739     Curl_llist_destroy(data->state.timeoutlist, NULL);
00740     data->state.timeoutlist = NULL;
00741   }
00742 
00743   /* as this was using a shared connection cache we clear the pointer to that
00744      since we're not part of that multi handle anymore */
00745   data->state.conn_cache = NULL;
00746 
00747   /* change state without using multistate(), only to make singlesocket() do
00748      what we want */
00749   data->mstate = CURLM_STATE_COMPLETED;
00750   singlesocket(multi, easy); /* to let the application know what sockets that
00751                                 vanish with this handle */
00752 
00753   /* Remove the association between the connection and the handle */
00754   if(data->easy_conn) {
00755     data->easy_conn->data = NULL;
00756     data->easy_conn = NULL;
00757   }
00758 
00759   data->multi = NULL; /* clear the association to this multi handle */
00760 
00761   /* make sure there's no pending message in the queue sent from this easy
00762      handle */
00763 
00764   for(e = multi->msglist->head; e; e = e->next) {
00765     struct Curl_message *msg = e->ptr;
00766 
00767     if(msg->extmsg.easy_handle == easy) {
00768       Curl_llist_remove(multi->msglist, e, NULL);
00769       /* there can only be one from this specific handle */
00770       break;
00771     }
00772   }
00773 
00774   /* make the previous node point to our next */
00775   if(data->prev)
00776     data->prev->next = data->next;
00777   else
00778     multi->easyp = data->next; /* point to first node */
00779 
00780   /* make our next point to our previous node */
00781   if(data->next)
00782     data->next->prev = data->prev;
00783   else
00784     multi->easylp = data->prev; /* point to last node */
00785 
00786   /* NOTE NOTE NOTE
00787      We do not touch the easy handle here! */
00788   multi->num_easy--; /* one less to care about now */
00789 
00790   update_timer(multi);
00791   return CURLM_OK;
00792 }
00793 
00794 /* Return TRUE if the application asked for a certain set of pipelining */
00795 bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
00796 {
00797   return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
00798 }
00799 
00800 void Curl_multi_handlePipeBreak(struct Curl_easy *data)
00801 {
00802   data->easy_conn = NULL;
00803 }
00804 
00805 static int waitconnect_getsock(struct connectdata *conn,
00806                                curl_socket_t *sock,
00807                                int numsocks)
00808 {
00809   int i;
00810   int s=0;
00811   int rc=0;
00812 
00813   if(!numsocks)
00814     return GETSOCK_BLANK;
00815 
00816 #ifdef USE_SSL
00817   if(CONNECT_FIRSTSOCKET_PROXY_SSL())
00818     return Curl_ssl_getsock(conn, sock, numsocks);
00819 #endif
00820 
00821   for(i=0; i<2; i++) {
00822     if(conn->tempsock[i] != CURL_SOCKET_BAD) {
00823       sock[s] = conn->tempsock[i];
00824       rc |= GETSOCK_WRITESOCK(s++);
00825     }
00826   }
00827 
00828   return rc;
00829 }
00830 
00831 static int waitproxyconnect_getsock(struct connectdata *conn,
00832                                     curl_socket_t *sock,
00833                                     int numsocks)
00834 {
00835   if(!numsocks)
00836     return GETSOCK_BLANK;
00837 
00838   sock[0] = conn->sock[FIRSTSOCKET];
00839 
00840   /* when we've sent a CONNECT to a proxy, we should rather wait for the
00841      socket to become readable to be able to get the response headers */
00842   if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
00843     return GETSOCK_READSOCK(0);
00844 
00845   return GETSOCK_WRITESOCK(0);
00846 }
00847 
00848 static int domore_getsock(struct connectdata *conn,
00849                           curl_socket_t *socks,
00850                           int numsocks)
00851 {
00852   if(conn && conn->handler->domore_getsock)
00853     return conn->handler->domore_getsock(conn, socks, numsocks);
00854   return GETSOCK_BLANK;
00855 }
00856 
00857 /* returns bitmapped flags for this handle and its sockets */
00858 static int multi_getsock(struct Curl_easy *data,
00859                          curl_socket_t *socks, /* points to numsocks number
00860                                                   of sockets */
00861                          int numsocks)
00862 {
00863   /* If the pipe broke, or if there's no connection left for this easy handle,
00864      then we MUST bail out now with no bitmask set. The no connection case can
00865      happen when this is called from curl_multi_remove_handle() =>
00866      singlesocket() => multi_getsock().
00867   */
00868   if(data->state.pipe_broke || !data->easy_conn)
00869     return 0;
00870 
00871   if(data->mstate > CURLM_STATE_CONNECT &&
00872      data->mstate < CURLM_STATE_COMPLETED) {
00873     /* Set up ownership correctly */
00874     data->easy_conn->data = data;
00875   }
00876 
00877   switch(data->mstate) {
00878   default:
00879 #if 0 /* switch back on these cases to get the compiler to check for all enums
00880          to be present */
00881   case CURLM_STATE_TOOFAST:  /* returns 0, so will not select. */
00882   case CURLM_STATE_COMPLETED:
00883   case CURLM_STATE_MSGSENT:
00884   case CURLM_STATE_INIT:
00885   case CURLM_STATE_CONNECT:
00886   case CURLM_STATE_WAITDO:
00887   case CURLM_STATE_DONE:
00888   case CURLM_STATE_LAST:
00889     /* this will get called with CURLM_STATE_COMPLETED when a handle is
00890        removed */
00891 #endif
00892     return 0;
00893 
00894   case CURLM_STATE_WAITRESOLVE:
00895     return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
00896 
00897   case CURLM_STATE_PROTOCONNECT:
00898   case CURLM_STATE_SENDPROTOCONNECT:
00899     return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
00900 
00901   case CURLM_STATE_DO:
00902   case CURLM_STATE_DOING:
00903     return Curl_doing_getsock(data->easy_conn, socks, numsocks);
00904 
00905   case CURLM_STATE_WAITPROXYCONNECT:
00906     return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
00907 
00908   case CURLM_STATE_WAITCONNECT:
00909     return waitconnect_getsock(data->easy_conn, socks, numsocks);
00910 
00911   case CURLM_STATE_DO_MORE:
00912     return domore_getsock(data->easy_conn, socks, numsocks);
00913 
00914   case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
00915                                to waiting for the same as the *PERFORM
00916                                states */
00917   case CURLM_STATE_PERFORM:
00918   case CURLM_STATE_WAITPERFORM:
00919     return Curl_single_getsock(data->easy_conn, socks, numsocks);
00920   }
00921 
00922 }
00923 
00924 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
00925                            fd_set *read_fd_set, fd_set *write_fd_set,
00926                            fd_set *exc_fd_set, int *max_fd)
00927 {
00928   /* Scan through all the easy handles to get the file descriptors set.
00929      Some easy handles may not have connected to the remote host yet,
00930      and then we must make sure that is done. */
00931   struct Curl_easy *data;
00932   int this_max_fd=-1;
00933   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
00934   int bitmap;
00935   int i;
00936   (void)exc_fd_set; /* not used */
00937 
00938   if(!GOOD_MULTI_HANDLE(multi))
00939     return CURLM_BAD_HANDLE;
00940 
00941   data=multi->easyp;
00942   while(data) {
00943     bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
00944 
00945     for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
00946       curl_socket_t s = CURL_SOCKET_BAD;
00947 
00948       if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
00949         FD_SET(sockbunch[i], read_fd_set);
00950         s = sockbunch[i];
00951       }
00952       if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
00953         FD_SET(sockbunch[i], write_fd_set);
00954         s = sockbunch[i];
00955       }
00956       if(s == CURL_SOCKET_BAD)
00957         /* this socket is unused, break out of loop */
00958         break;
00959       else {
00960         if((int)s > this_max_fd)
00961           this_max_fd = (int)s;
00962       }
00963     }
00964 
00965     data = data->next; /* check next handle */
00966   }
00967 
00968   *max_fd = this_max_fd;
00969 
00970   return CURLM_OK;
00971 }
00972 
00973 CURLMcode curl_multi_wait(struct Curl_multi *multi,
00974                           struct curl_waitfd extra_fds[],
00975                           unsigned int extra_nfds,
00976                           int timeout_ms,
00977                           int *ret)
00978 {
00979   struct Curl_easy *data;
00980   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
00981   int bitmap;
00982   unsigned int i;
00983   unsigned int nfds = 0;
00984   unsigned int curlfds;
00985   struct pollfd *ufds = NULL;
00986   long timeout_internal;
00987   int retcode = 0;
00988 
00989   if(!GOOD_MULTI_HANDLE(multi))
00990     return CURLM_BAD_HANDLE;
00991 
00992   /* If the internally desired timeout is actually shorter than requested from
00993      the outside, then use the shorter time! But only if the internal timer
00994      is actually larger than -1! */
00995   (void)multi_timeout(multi, &timeout_internal);
00996   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
00997     timeout_ms = (int)timeout_internal;
00998 
00999   /* Count up how many fds we have from the multi handle */
01000   data=multi->easyp;
01001   while(data) {
01002     bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
01003 
01004     for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
01005       curl_socket_t s = CURL_SOCKET_BAD;
01006 
01007       if(bitmap & GETSOCK_READSOCK(i)) {
01008         ++nfds;
01009         s = sockbunch[i];
01010       }
01011       if(bitmap & GETSOCK_WRITESOCK(i)) {
01012         ++nfds;
01013         s = sockbunch[i];
01014       }
01015       if(s == CURL_SOCKET_BAD) {
01016         break;
01017       }
01018     }
01019 
01020     data = data->next; /* check next handle */
01021   }
01022 
01023   curlfds = nfds; /* number of internal file descriptors */
01024   nfds += extra_nfds; /* add the externally provided ones */
01025 
01026   if(nfds || extra_nfds) {
01027     ufds = malloc(nfds * sizeof(struct pollfd));
01028     if(!ufds)
01029       return CURLM_OUT_OF_MEMORY;
01030   }
01031   nfds = 0;
01032 
01033   /* only do the second loop if we found descriptors in the first stage run
01034      above */
01035 
01036   if(curlfds) {
01037     /* Add the curl handles to our pollfds first */
01038     data=multi->easyp;
01039     while(data) {
01040       bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
01041 
01042       for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
01043         curl_socket_t s = CURL_SOCKET_BAD;
01044 
01045         if(bitmap & GETSOCK_READSOCK(i)) {
01046           ufds[nfds].fd = sockbunch[i];
01047           ufds[nfds].events = POLLIN;
01048           ++nfds;
01049           s = sockbunch[i];
01050         }
01051         if(bitmap & GETSOCK_WRITESOCK(i)) {
01052           ufds[nfds].fd = sockbunch[i];
01053           ufds[nfds].events = POLLOUT;
01054           ++nfds;
01055           s = sockbunch[i];
01056         }
01057         if(s == CURL_SOCKET_BAD) {
01058           break;
01059         }
01060       }
01061 
01062       data = data->next; /* check next handle */
01063     }
01064   }
01065 
01066   /* Add external file descriptions from poll-like struct curl_waitfd */
01067   for(i = 0; i < extra_nfds; i++) {
01068     ufds[nfds].fd = extra_fds[i].fd;
01069     ufds[nfds].events = 0;
01070     if(extra_fds[i].events & CURL_WAIT_POLLIN)
01071       ufds[nfds].events |= POLLIN;
01072     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
01073       ufds[nfds].events |= POLLPRI;
01074     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
01075       ufds[nfds].events |= POLLOUT;
01076     ++nfds;
01077   }
01078 
01079   if(nfds) {
01080     int pollrc;
01081     /* wait... */
01082     pollrc = Curl_poll(ufds, nfds, timeout_ms);
01083     DEBUGF(infof(data, "Curl_poll(%d ds, %d ms) == %d\n",
01084                  nfds, timeout_ms, pollrc));
01085 
01086     if(pollrc > 0) {
01087       retcode = pollrc;
01088       /* copy revents results from the poll to the curl_multi_wait poll
01089          struct, the bit values of the actual underlying poll() implementation
01090          may not be the same as the ones in the public libcurl API! */
01091       for(i = 0; i < extra_nfds; i++) {
01092         unsigned short mask = 0;
01093         unsigned r = ufds[curlfds + i].revents;
01094 
01095         if(r & POLLIN)
01096           mask |= CURL_WAIT_POLLIN;
01097         if(r & POLLOUT)
01098           mask |= CURL_WAIT_POLLOUT;
01099         if(r & POLLPRI)
01100           mask |= CURL_WAIT_POLLPRI;
01101 
01102         extra_fds[i].revents = mask;
01103       }
01104     }
01105   }
01106 
01107   free(ufds);
01108   if(ret)
01109     *ret = retcode;
01110   return CURLM_OK;
01111 }
01112 
01113 /*
01114  * Curl_multi_connchanged() is called to tell that there is a connection in
01115  * this multi handle that has changed state (pipelining become possible, the
01116  * number of allowed streams changed or similar), and a subsequent use of this
01117  * multi handle should move CONNECT_PEND handles back to CONNECT to have them
01118  * retry.
01119  */
01120 void Curl_multi_connchanged(struct Curl_multi *multi)
01121 {
01122   multi->recheckstate = TRUE;
01123 }
01124 
01125 /*
01126  * multi_ischanged() is called
01127  *
01128  * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
01129  * => CONNECT action.
01130  *
01131  * Set 'clear' to TRUE to have it also clear the state variable.
01132  */
01133 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
01134 {
01135   bool retval = multi->recheckstate;
01136   if(clear)
01137     multi->recheckstate = FALSE;
01138   return retval;
01139 }
01140 
01141 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
01142                                  struct Curl_easy *data,
01143                                  struct connectdata *conn)
01144 {
01145   CURLMcode rc;
01146 
01147   rc = curl_multi_add_handle(multi, data);
01148   if(!rc) {
01149     struct SingleRequest *k = &data->req;
01150 
01151     /* pass in NULL for 'conn' here since we don't want to init the
01152        connection, only this transfer */
01153     Curl_init_do(data, NULL);
01154 
01155     /* take this handle to the perform state right away */
01156     multistate(data, CURLM_STATE_PERFORM);
01157     data->easy_conn = conn;
01158     k->keepon |= KEEP_RECV; /* setup to receive! */
01159   }
01160   return rc;
01161 }
01162 
01163 static CURLcode multi_reconnect_request(struct connectdata **connp)
01164 {
01165   CURLcode result = CURLE_OK;
01166   struct connectdata *conn = *connp;
01167   struct Curl_easy *data = conn->data;
01168 
01169   /* This was a re-use of a connection and we got a write error in the
01170    * DO-phase. Then we DISCONNECT this connection and have another attempt to
01171    * CONNECT and then DO again! The retry cannot possibly find another
01172    * connection to re-use, since we only keep one possible connection for
01173    * each.  */
01174 
01175   infof(data, "Re-used connection seems dead, get a new one\n");
01176 
01177   connclose(conn, "Reconnect dead connection"); /* enforce close */
01178   result = multi_done(&conn, result, FALSE); /* we are so done with this */
01179 
01180   /* conn may no longer be a good pointer, clear it to avoid mistakes by
01181      parent functions */
01182   *connp = NULL;
01183 
01184   /*
01185    * We need to check for CURLE_SEND_ERROR here as well. This could happen
01186    * when the request failed on a FTP connection and thus multi_done() itself
01187    * tried to use the connection (again).
01188    */
01189   if(!result || (CURLE_SEND_ERROR == result)) {
01190     bool async;
01191     bool protocol_done = TRUE;
01192 
01193     /* Now, redo the connect and get a new connection */
01194     result = Curl_connect(data, connp, &async, &protocol_done);
01195     if(!result) {
01196       /* We have connected or sent away a name resolve query fine */
01197 
01198       conn = *connp; /* setup conn to again point to something nice */
01199       if(async) {
01200         /* Now, if async is TRUE here, we need to wait for the name
01201            to resolve */
01202         result = Curl_resolver_wait_resolv(conn, NULL);
01203         if(result)
01204           return result;
01205 
01206         /* Resolved, continue with the connection */
01207         result = Curl_async_resolved(conn, &protocol_done);
01208         if(result)
01209           return result;
01210       }
01211     }
01212   }
01213 
01214   return result;
01215 }
01216 
01217 /*
01218  * do_complete is called when the DO actions are complete.
01219  *
01220  * We init chunking and trailer bits to their default values here immediately
01221  * before receiving any header data for the current request in the pipeline.
01222  */
01223 static void do_complete(struct connectdata *conn)
01224 {
01225   conn->data->req.chunk=FALSE;
01226   conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
01227                            conn->sockfd:conn->writesockfd)+1;
01228   Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
01229 }
01230 
01231 static CURLcode multi_do(struct connectdata **connp, bool *done)
01232 {
01233   CURLcode result=CURLE_OK;
01234   struct connectdata *conn = *connp;
01235   struct Curl_easy *data = conn->data;
01236 
01237   if(conn->handler->do_it) {
01238     /* generic protocol-specific function pointer set in curl_connect() */
01239     result = conn->handler->do_it(conn, done);
01240 
01241     /* This was formerly done in transfer.c, but we better do it here */
01242     if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
01243       /*
01244        * If the connection is using an easy handle, call reconnect
01245        * to re-establish the connection.  Otherwise, let the multi logic
01246        * figure out how to re-establish the connection.
01247        */
01248       if(!data->multi) {
01249         result = multi_reconnect_request(connp);
01250 
01251         if(!result) {
01252           /* ... finally back to actually retry the DO phase */
01253           conn = *connp; /* re-assign conn since multi_reconnect_request
01254                             creates a new connection */
01255           result = conn->handler->do_it(conn, done);
01256         }
01257       }
01258       else
01259         return result;
01260     }
01261 
01262     if(!result && *done)
01263       /* do_complete must be called after the protocol-specific DO function */
01264       do_complete(conn);
01265   }
01266   return result;
01267 }
01268 
01269 /*
01270  * multi_do_more() is called during the DO_MORE multi state. It is basically a
01271  * second stage DO state which (wrongly) was introduced to support FTP's
01272  * second connection.
01273  *
01274  * TODO: A future libcurl should be able to work away this state.
01275  *
01276  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
01277  * DOING state there's more work to do!
01278  */
01279 
01280 static CURLcode multi_do_more(struct connectdata *conn, int *complete)
01281 {
01282   CURLcode result=CURLE_OK;
01283 
01284   *complete = 0;
01285 
01286   if(conn->handler->do_more)
01287     result = conn->handler->do_more(conn, complete);
01288 
01289   if(!result && (*complete == 1))
01290     /* do_complete must be called after the protocol-specific DO function */
01291     do_complete(conn);
01292 
01293   return result;
01294 }
01295 
01296 static CURLMcode multi_runsingle(struct Curl_multi *multi,
01297                                  struct timeval now,
01298                                  struct Curl_easy *data)
01299 {
01300   struct Curl_message *msg = NULL;
01301   bool connected;
01302   bool async;
01303   bool protocol_connect = FALSE;
01304   bool dophase_done = FALSE;
01305   bool done = FALSE;
01306   CURLMcode rc;
01307   CURLcode result = CURLE_OK;
01308   struct SingleRequest *k;
01309   time_t timeout_ms;
01310   int control;
01311 
01312   if(!GOOD_EASY_HANDLE(data))
01313     return CURLM_BAD_EASY_HANDLE;
01314 
01315   do {
01316     /* A "stream" here is a logical stream if the protocol can handle that
01317        (HTTP/2), or the full connection for older protocols */
01318     bool stream_error = FALSE;
01319     rc = CURLM_OK;
01320 
01321     /* Handle the case when the pipe breaks, i.e., the connection
01322        we're using gets cleaned up and we're left with nothing. */
01323     if(data->state.pipe_broke) {
01324       infof(data, "Pipe broke: handle %p, url = %s\n",
01325             (void *)data, data->state.path);
01326 
01327       if(data->mstate < CURLM_STATE_COMPLETED) {
01328         /* Head back to the CONNECT state */
01329         multistate(data, CURLM_STATE_CONNECT);
01330         rc = CURLM_CALL_MULTI_PERFORM;
01331         result = CURLE_OK;
01332       }
01333 
01334       data->state.pipe_broke = FALSE;
01335       data->easy_conn = NULL;
01336       continue;
01337     }
01338 
01339     if(!data->easy_conn &&
01340        data->mstate > CURLM_STATE_CONNECT &&
01341        data->mstate < CURLM_STATE_DONE) {
01342       /* In all these states, the code will blindly access 'data->easy_conn'
01343          so this is precaution that it isn't NULL. And it silences static
01344          analyzers. */
01345       failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
01346       return CURLM_INTERNAL_ERROR;
01347     }
01348 
01349     if(multi_ischanged(multi, TRUE)) {
01350       DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
01351       Curl_multi_process_pending_handles(multi);
01352     }
01353 
01354     if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
01355        data->mstate < CURLM_STATE_COMPLETED)
01356       /* Make sure we set the connection's current owner */
01357       data->easy_conn->data = data;
01358 
01359     if(data->easy_conn &&
01360        (data->mstate >= CURLM_STATE_CONNECT) &&
01361        (data->mstate < CURLM_STATE_COMPLETED)) {
01362       /* we need to wait for the connect state as only then is the start time
01363          stored, but we must not check already completed handles */
01364 
01365       timeout_ms = Curl_timeleft(data, &now,
01366                                  (data->mstate <= CURLM_STATE_WAITDO)?
01367                                  TRUE:FALSE);
01368 
01369       if(timeout_ms < 0) {
01370         /* Handle timed out */
01371         if(data->mstate == CURLM_STATE_WAITRESOLVE)
01372           failf(data, "Resolving timed out after %ld milliseconds",
01373                 Curl_tvdiff(now, data->progress.t_startsingle));
01374         else if(data->mstate == CURLM_STATE_WAITCONNECT)
01375           failf(data, "Connection timed out after %ld milliseconds",
01376                 Curl_tvdiff(now, data->progress.t_startsingle));
01377         else {
01378           k = &data->req;
01379           if(k->size != -1) {
01380             failf(data, "Operation timed out after %ld milliseconds with %"
01381                   CURL_FORMAT_CURL_OFF_T " out of %"
01382                   CURL_FORMAT_CURL_OFF_T " bytes received",
01383                   Curl_tvdiff(now, data->progress.t_startsingle),
01384                   k->bytecount, k->size);
01385           }
01386           else {
01387             failf(data, "Operation timed out after %ld milliseconds with %"
01388                   CURL_FORMAT_CURL_OFF_T " bytes received",
01389                   Curl_tvdiff(now, data->progress.t_startsingle),
01390                   k->bytecount);
01391           }
01392         }
01393 
01394         /* Force connection closed if the connection has indeed been used */
01395         if(data->mstate > CURLM_STATE_DO) {
01396           streamclose(data->easy_conn, "Disconnected with pending data");
01397           stream_error = TRUE;
01398         }
01399         result = CURLE_OPERATION_TIMEDOUT;
01400         (void)multi_done(&data->easy_conn, result, TRUE);
01401         /* Skip the statemachine and go directly to error handling section. */
01402         goto statemachine_end;
01403       }
01404     }
01405 
01406     switch(data->mstate) {
01407     case CURLM_STATE_INIT:
01408       /* init this transfer. */
01409       result=Curl_pretransfer(data);
01410 
01411       if(!result) {
01412         /* after init, go CONNECT */
01413         multistate(data, CURLM_STATE_CONNECT);
01414         Curl_pgrsTime(data, TIMER_STARTOP);
01415         rc = CURLM_CALL_MULTI_PERFORM;
01416       }
01417       break;
01418 
01419     case CURLM_STATE_CONNECT_PEND:
01420       /* We will stay here until there is a connection available. Then
01421          we try again in the CURLM_STATE_CONNECT state. */
01422       break;
01423 
01424     case CURLM_STATE_CONNECT:
01425       /* Connect. We want to get a connection identifier filled in. */
01426       Curl_pgrsTime(data, TIMER_STARTSINGLE);
01427       result = Curl_connect(data, &data->easy_conn,
01428                             &async, &protocol_connect);
01429       if(CURLE_NO_CONNECTION_AVAILABLE == result) {
01430         /* There was no connection available. We will go to the pending
01431            state and wait for an available connection. */
01432         multistate(data, CURLM_STATE_CONNECT_PEND);
01433 
01434         /* add this handle to the list of connect-pending handles */
01435         if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
01436           result = CURLE_OUT_OF_MEMORY;
01437         else
01438           result = CURLE_OK;
01439         break;
01440       }
01441 
01442       if(!result) {
01443         /* Add this handle to the send or pend pipeline */
01444         result = Curl_add_handle_to_pipeline(data, data->easy_conn);
01445         if(result)
01446           stream_error = TRUE;
01447         else {
01448           if(async)
01449             /* We're now waiting for an asynchronous name lookup */
01450             multistate(data, CURLM_STATE_WAITRESOLVE);
01451           else {
01452             /* after the connect has been sent off, go WAITCONNECT unless the
01453                protocol connect is already done and we can go directly to
01454                WAITDO or DO! */
01455             rc = CURLM_CALL_MULTI_PERFORM;
01456 
01457             if(protocol_connect)
01458               multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
01459                          CURLM_STATE_WAITDO:CURLM_STATE_DO);
01460             else {
01461 #ifndef CURL_DISABLE_HTTP
01462               if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
01463                 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
01464               else
01465 #endif
01466                 multistate(data, CURLM_STATE_WAITCONNECT);
01467             }
01468           }
01469         }
01470       }
01471       break;
01472 
01473     case CURLM_STATE_WAITRESOLVE:
01474       /* awaiting an asynch name resolve to complete */
01475     {
01476       struct Curl_dns_entry *dns = NULL;
01477       struct connectdata *conn = data->easy_conn;
01478       const char *hostname;
01479 
01480       if(conn->bits.proxy)
01481         hostname = conn->proxy.name;
01482       else if(conn->bits.conn_to_host)
01483         hostname = conn->conn_to_host.name;
01484       else
01485         hostname = conn->host.name;
01486 
01487       /* check if we have the name resolved by now */
01488       dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
01489 
01490       if(dns) {
01491 #ifdef CURLRES_ASYNCH
01492         conn->async.dns = dns;
01493         conn->async.done = TRUE;
01494 #endif
01495         result = CURLE_OK;
01496         infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
01497       }
01498 
01499       if(!dns)
01500         result = Curl_resolver_is_resolved(data->easy_conn, &dns);
01501 
01502       /* Update sockets here, because the socket(s) may have been
01503          closed and the application thus needs to be told, even if it
01504          is likely that the same socket(s) will again be used further
01505          down.  If the name has not yet been resolved, it is likely
01506          that new sockets have been opened in an attempt to contact
01507          another resolver. */
01508       singlesocket(multi, data);
01509 
01510       if(dns) {
01511         /* Perform the next step in the connection phase, and then move on
01512            to the WAITCONNECT state */
01513         result = Curl_async_resolved(data->easy_conn, &protocol_connect);
01514 
01515         if(result)
01516           /* if Curl_async_resolved() returns failure, the connection struct
01517              is already freed and gone */
01518           data->easy_conn = NULL;           /* no more connection */
01519         else {
01520           /* call again please so that we get the next socket setup */
01521           rc = CURLM_CALL_MULTI_PERFORM;
01522           if(protocol_connect)
01523             multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
01524                        CURLM_STATE_WAITDO:CURLM_STATE_DO);
01525           else {
01526 #ifndef CURL_DISABLE_HTTP
01527             if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
01528               multistate(data, CURLM_STATE_WAITPROXYCONNECT);
01529             else
01530 #endif
01531               multistate(data, CURLM_STATE_WAITCONNECT);
01532           }
01533         }
01534       }
01535 
01536       if(result) {
01537         /* failure detected */
01538         stream_error = TRUE;
01539         break;
01540       }
01541     }
01542     break;
01543 
01544 #ifndef CURL_DISABLE_HTTP
01545     case CURLM_STATE_WAITPROXYCONNECT:
01546       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
01547       result = Curl_http_connect(data->easy_conn, &protocol_connect);
01548 
01549       if(data->easy_conn->bits.proxy_connect_closed) {
01550         rc = CURLM_CALL_MULTI_PERFORM;
01551         /* connect back to proxy again */
01552         result = CURLE_OK;
01553         multi_done(&data->easy_conn, CURLE_OK, FALSE);
01554         multistate(data, CURLM_STATE_CONNECT);
01555       }
01556       else if(!result) {
01557         if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
01558            data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
01559            (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) {
01560           rc = CURLM_CALL_MULTI_PERFORM;
01561           /* initiate protocol connect phase */
01562           multistate(data, CURLM_STATE_SENDPROTOCONNECT);
01563         }
01564       }
01565       break;
01566 #endif
01567 
01568     case CURLM_STATE_WAITCONNECT:
01569       /* awaiting a completion of an asynch TCP connect */
01570       result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
01571       if(connected && !result) {
01572 #ifndef CURL_DISABLE_HTTP
01573         if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
01574             !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
01575             (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
01576           multistate(data, CURLM_STATE_WAITPROXYCONNECT);
01577           break;
01578         }
01579 #endif
01580         rc = CURLM_CALL_MULTI_PERFORM;
01581         multistate(data, data->easy_conn->bits.tunnel_proxy?
01582                    CURLM_STATE_WAITPROXYCONNECT:
01583                    CURLM_STATE_SENDPROTOCONNECT);
01584       }
01585       else if(result) {
01586         /* failure detected */
01587         /* Just break, the cleaning up is handled all in one place */
01588         stream_error = TRUE;
01589         break;
01590       }
01591       break;
01592 
01593     case CURLM_STATE_SENDPROTOCONNECT:
01594       result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
01595       if(!protocol_connect)
01596         /* switch to waiting state */
01597         multistate(data, CURLM_STATE_PROTOCONNECT);
01598       else if(!result) {
01599         /* protocol connect has completed, go WAITDO or DO */
01600         multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
01601                    CURLM_STATE_WAITDO:CURLM_STATE_DO);
01602         rc = CURLM_CALL_MULTI_PERFORM;
01603       }
01604       else if(result) {
01605         /* failure detected */
01606         Curl_posttransfer(data);
01607         multi_done(&data->easy_conn, result, TRUE);
01608         stream_error = TRUE;
01609       }
01610       break;
01611 
01612     case CURLM_STATE_PROTOCONNECT:
01613       /* protocol-specific connect phase */
01614       result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
01615       if(!result && protocol_connect) {
01616         /* after the connect has completed, go WAITDO or DO */
01617         multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
01618                    CURLM_STATE_WAITDO:CURLM_STATE_DO);
01619         rc = CURLM_CALL_MULTI_PERFORM;
01620       }
01621       else if(result) {
01622         /* failure detected */
01623         Curl_posttransfer(data);
01624         multi_done(&data->easy_conn, result, TRUE);
01625         stream_error = TRUE;
01626       }
01627       break;
01628 
01629     case CURLM_STATE_WAITDO:
01630       /* Wait for our turn to DO when we're pipelining requests */
01631       if(Curl_pipeline_checkget_write(data, data->easy_conn)) {
01632         /* Grabbed the channel */
01633         multistate(data, CURLM_STATE_DO);
01634         rc = CURLM_CALL_MULTI_PERFORM;
01635       }
01636       break;
01637 
01638     case CURLM_STATE_DO:
01639       if(data->set.connect_only) {
01640         /* keep connection open for application to use the socket */
01641         connkeep(data->easy_conn, "CONNECT_ONLY");
01642         multistate(data, CURLM_STATE_DONE);
01643         result = CURLE_OK;
01644         rc = CURLM_CALL_MULTI_PERFORM;
01645       }
01646       else {
01647         /* Perform the protocol's DO action */
01648         result = multi_do(&data->easy_conn, &dophase_done);
01649 
01650         /* When multi_do() returns failure, data->easy_conn might be NULL! */
01651 
01652         if(!result) {
01653           if(!dophase_done) {
01654             /* some steps needed for wildcard matching */
01655             if(data->set.wildcardmatch) {
01656               struct WildcardData *wc = &data->wildcard;
01657               if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
01658                 /* skip some states if it is important */
01659                 multi_done(&data->easy_conn, CURLE_OK, FALSE);
01660                 multistate(data, CURLM_STATE_DONE);
01661                 rc = CURLM_CALL_MULTI_PERFORM;
01662                 break;
01663               }
01664             }
01665             /* DO was not completed in one function call, we must continue
01666                DOING... */
01667             multistate(data, CURLM_STATE_DOING);
01668             rc = CURLM_OK;
01669           }
01670 
01671           /* after DO, go DO_DONE... or DO_MORE */
01672           else if(data->easy_conn->bits.do_more) {
01673             /* we're supposed to do more, but we need to sit down, relax
01674                and wait a little while first */
01675             multistate(data, CURLM_STATE_DO_MORE);
01676             rc = CURLM_OK;
01677           }
01678           else {
01679             /* we're done with the DO, now DO_DONE */
01680             multistate(data, CURLM_STATE_DO_DONE);
01681             rc = CURLM_CALL_MULTI_PERFORM;
01682           }
01683         }
01684         else if((CURLE_SEND_ERROR == result) &&
01685                 data->easy_conn->bits.reuse) {
01686           /*
01687            * In this situation, a connection that we were trying to use
01688            * may have unexpectedly died.  If possible, send the connection
01689            * back to the CONNECT phase so we can try again.
01690            */
01691           char *newurl = NULL;
01692           followtype follow=FOLLOW_NONE;
01693           CURLcode drc;
01694           bool retry = FALSE;
01695 
01696           drc = Curl_retry_request(data->easy_conn, &newurl);
01697           if(drc) {
01698             /* a failure here pretty much implies an out of memory */
01699             result = drc;
01700             stream_error = TRUE;
01701           }
01702           else
01703             retry = (newurl)?TRUE:FALSE;
01704 
01705           Curl_posttransfer(data);
01706           drc = multi_done(&data->easy_conn, result, FALSE);
01707 
01708           /* When set to retry the connection, we must to go back to
01709            * the CONNECT state */
01710           if(retry) {
01711             if(!drc || (drc == CURLE_SEND_ERROR)) {
01712               follow = FOLLOW_RETRY;
01713               drc = Curl_follow(data, newurl, follow);
01714               if(!drc) {
01715                 multistate(data, CURLM_STATE_CONNECT);
01716                 rc = CURLM_CALL_MULTI_PERFORM;
01717                 result = CURLE_OK;
01718               }
01719               else {
01720                 /* Follow failed */
01721                 result = drc;
01722                 free(newurl);
01723               }
01724             }
01725             else {
01726               /* done didn't return OK or SEND_ERROR */
01727               result = drc;
01728               free(newurl);
01729             }
01730           }
01731           else {
01732             /* Have error handler disconnect conn if we can't retry */
01733             stream_error = TRUE;
01734             free(newurl);
01735           }
01736         }
01737         else {
01738           /* failure detected */
01739           Curl_posttransfer(data);
01740           if(data->easy_conn)
01741             multi_done(&data->easy_conn, result, FALSE);
01742           stream_error = TRUE;
01743         }
01744       }
01745       break;
01746 
01747     case CURLM_STATE_DOING:
01748       /* we continue DOING until the DO phase is complete */
01749       result = Curl_protocol_doing(data->easy_conn,
01750                                    &dophase_done);
01751       if(!result) {
01752         if(dophase_done) {
01753           /* after DO, go DO_DONE or DO_MORE */
01754           multistate(data, data->easy_conn->bits.do_more?
01755                      CURLM_STATE_DO_MORE:
01756                      CURLM_STATE_DO_DONE);
01757           rc = CURLM_CALL_MULTI_PERFORM;
01758         } /* dophase_done */
01759       }
01760       else {
01761         /* failure detected */
01762         Curl_posttransfer(data);
01763         multi_done(&data->easy_conn, result, FALSE);
01764         stream_error = TRUE;
01765       }
01766       break;
01767 
01768     case CURLM_STATE_DO_MORE:
01769       /*
01770        * When we are connected, DO MORE and then go DO_DONE
01771        */
01772       result = multi_do_more(data->easy_conn, &control);
01773 
01774       /* No need to remove this handle from the send pipeline here since that
01775          is done in multi_done() */
01776       if(!result) {
01777         if(control) {
01778           /* if positive, advance to DO_DONE
01779              if negative, go back to DOING */
01780           multistate(data, control==1?
01781                      CURLM_STATE_DO_DONE:
01782                      CURLM_STATE_DOING);
01783           rc = CURLM_CALL_MULTI_PERFORM;
01784         }
01785         else
01786           /* stay in DO_MORE */
01787           rc = CURLM_OK;
01788       }
01789       else {
01790         /* failure detected */
01791         Curl_posttransfer(data);
01792         multi_done(&data->easy_conn, result, FALSE);
01793         stream_error = TRUE;
01794       }
01795       break;
01796 
01797     case CURLM_STATE_DO_DONE:
01798       /* Move ourselves from the send to recv pipeline */
01799       Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
01800       /* Check if we can move pending requests to send pipe */
01801       Curl_multi_process_pending_handles(multi);
01802 
01803       /* Only perform the transfer if there's a good socket to work with.
01804          Having both BAD is a signal to skip immediately to DONE */
01805       if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
01806          (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
01807         multistate(data, CURLM_STATE_WAITPERFORM);
01808       else
01809         multistate(data, CURLM_STATE_DONE);
01810       rc = CURLM_CALL_MULTI_PERFORM;
01811       break;
01812 
01813     case CURLM_STATE_WAITPERFORM:
01814       /* Wait for our turn to PERFORM */
01815       if(Curl_pipeline_checkget_read(data, data->easy_conn)) {
01816         /* Grabbed the channel */
01817         multistate(data, CURLM_STATE_PERFORM);
01818         rc = CURLM_CALL_MULTI_PERFORM;
01819       }
01820       break;
01821 
01822     case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
01823       /* if both rates are within spec, resume transfer */
01824       if(Curl_pgrsUpdate(data->easy_conn))
01825         result = CURLE_ABORTED_BY_CALLBACK;
01826       else
01827         result = Curl_speedcheck(data, now);
01828 
01829       if(( (data->set.max_send_speed == 0) ||
01830            (Curl_pgrsLimitWaitTime(data->progress.uploaded,
01831                                    data->progress.ul_limit_size,
01832                                    data->set.max_send_speed,
01833                                    data->progress.ul_limit_start,
01834                                    now) <= 0))  &&
01835          ( (data->set.max_recv_speed == 0) ||
01836            (Curl_pgrsLimitWaitTime(data->progress.downloaded,
01837                                    data->progress.dl_limit_size,
01838                                    data->set.max_recv_speed,
01839                                    data->progress.dl_limit_start,
01840                                    now) <= 0)))
01841         multistate(data, CURLM_STATE_PERFORM);
01842       break;
01843 
01844     case CURLM_STATE_PERFORM:
01845     {
01846       char *newurl = NULL;
01847       bool retry = FALSE;
01848       bool comeback = FALSE;
01849 
01850       /* check if over send speed */
01851       if(data->set.max_send_speed > 0) {
01852         timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
01853                                             data->progress.ul_limit_size,
01854                                             data->set.max_send_speed,
01855                                             data->progress.ul_limit_start,
01856                                             now);
01857         if(timeout_ms > 0) {
01858           multistate(data, CURLM_STATE_TOOFAST);
01859           Curl_expire_latest(data, timeout_ms);
01860           break;
01861         }
01862       }
01863 
01864       /* check if over recv speed */
01865       if(data->set.max_recv_speed > 0) {
01866         timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
01867                                             data->progress.dl_limit_size,
01868                                             data->set.max_recv_speed,
01869                                             data->progress.dl_limit_start,
01870                                             now);
01871         if(timeout_ms > 0) {
01872           multistate(data, CURLM_STATE_TOOFAST);
01873           Curl_expire_latest(data, timeout_ms);
01874           break;
01875         }
01876       }
01877 
01878       /* read/write data if it is ready to do so */
01879       result = Curl_readwrite(data->easy_conn, data, &done, &comeback);
01880 
01881       k = &data->req;
01882 
01883       if(!(k->keepon & KEEP_RECV))
01884         /* We're done receiving */
01885         Curl_pipeline_leave_read(data->easy_conn);
01886 
01887       if(!(k->keepon & KEEP_SEND))
01888         /* We're done sending */
01889         Curl_pipeline_leave_write(data->easy_conn);
01890 
01891       if(done || (result == CURLE_RECV_ERROR)) {
01892         /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
01893          * condition and the server closed the re-used connection exactly when
01894          * we wanted to use it, so figure out if that is indeed the case.
01895          */
01896         CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
01897         if(!ret)
01898           retry = (newurl)?TRUE:FALSE;
01899 
01900         if(retry) {
01901           /* if we are to retry, set the result to OK and consider the
01902              request as done */
01903           result = CURLE_OK;
01904           done = TRUE;
01905         }
01906       }
01907 
01908       if(result) {
01909         /*
01910          * The transfer phase returned error, we mark the connection to get
01911          * closed to prevent being re-used. This is because we can't possibly
01912          * know if the connection is in a good shape or not now.  Unless it is
01913          * a protocol which uses two "channels" like FTP, as then the error
01914          * happened in the data connection.
01915          */
01916 
01917         if(!(data->easy_conn->handler->flags & PROTOPT_DUAL) &&
01918            result != CURLE_HTTP2_STREAM)
01919           streamclose(data->easy_conn, "Transfer returned error");
01920 
01921         Curl_posttransfer(data);
01922         multi_done(&data->easy_conn, result, TRUE);
01923       }
01924       else if(done) {
01925         followtype follow=FOLLOW_NONE;
01926 
01927         /* call this even if the readwrite function returned error */
01928         Curl_posttransfer(data);
01929 
01930         /* we're no longer receiving */
01931         Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
01932 
01933         /* expire the new receiving pipeline head */
01934         if(data->easy_conn->recv_pipe->head)
01935           Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 0);
01936 
01937         /* Check if we can move pending requests to send pipe */
01938         Curl_multi_process_pending_handles(multi);
01939 
01940         /* When we follow redirects or is set to retry the connection, we must
01941            to go back to the CONNECT state */
01942         if(data->req.newurl || retry) {
01943           if(!retry) {
01944             /* if the URL is a follow-location and not just a retried request
01945                then figure out the URL here */
01946             free(newurl);
01947             newurl = data->req.newurl;
01948             data->req.newurl = NULL;
01949             follow = FOLLOW_REDIR;
01950           }
01951           else
01952             follow = FOLLOW_RETRY;
01953           result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
01954           if(!result) {
01955             result = Curl_follow(data, newurl, follow);
01956             if(!result) {
01957               multistate(data, CURLM_STATE_CONNECT);
01958               rc = CURLM_CALL_MULTI_PERFORM;
01959               newurl = NULL; /* handed over the memory ownership to
01960                                 Curl_follow(), make sure we don't free() it
01961                                 here */
01962             }
01963           }
01964         }
01965         else {
01966           /* after the transfer is done, go DONE */
01967 
01968           /* but first check to see if we got a location info even though we're
01969              not following redirects */
01970           if(data->req.location) {
01971             free(newurl);
01972             newurl = data->req.location;
01973             data->req.location = NULL;
01974             result = Curl_follow(data, newurl, FOLLOW_FAKE);
01975             if(!result)
01976               newurl = NULL; /* allocation was handed over Curl_follow() */
01977             else
01978               stream_error = TRUE;
01979           }
01980 
01981           multistate(data, CURLM_STATE_DONE);
01982           rc = CURLM_CALL_MULTI_PERFORM;
01983         }
01984       }
01985       else if(comeback)
01986         rc = CURLM_CALL_MULTI_PERFORM;
01987 
01988       free(newurl);
01989       break;
01990     }
01991 
01992     case CURLM_STATE_DONE:
01993       /* this state is highly transient, so run another loop after this */
01994       rc = CURLM_CALL_MULTI_PERFORM;
01995 
01996       if(data->easy_conn) {
01997         CURLcode res;
01998 
01999         /* Remove ourselves from the receive pipeline, if we are there. */
02000         Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
02001         /* Check if we can move pending requests to send pipe */
02002         Curl_multi_process_pending_handles(multi);
02003 
02004         /* post-transfer command */
02005         res = multi_done(&data->easy_conn, result, FALSE);
02006 
02007         /* allow a previously set error code take precedence */
02008         if(!result)
02009           result = res;
02010 
02011         /*
02012          * If there are other handles on the pipeline, multi_done won't set
02013          * easy_conn to NULL.  In such a case, curl_multi_remove_handle() can
02014          * access free'd data, if the connection is free'd and the handle
02015          * removed before we perform the processing in CURLM_STATE_COMPLETED
02016          */
02017         if(data->easy_conn)
02018           data->easy_conn = NULL;
02019       }
02020 
02021       if(data->set.wildcardmatch) {
02022         if(data->wildcard.state != CURLWC_DONE) {
02023           /* if a wildcard is set and we are not ending -> lets start again
02024              with CURLM_STATE_INIT */
02025           multistate(data, CURLM_STATE_INIT);
02026           break;
02027         }
02028       }
02029 
02030       /* after we have DONE what we're supposed to do, go COMPLETED, and
02031          it doesn't matter what the multi_done() returned! */
02032       multistate(data, CURLM_STATE_COMPLETED);
02033       break;
02034 
02035     case CURLM_STATE_COMPLETED:
02036       /* this is a completed transfer, it is likely to still be connected */
02037 
02038       /* This node should be delinked from the list now and we should post
02039          an information message that we are complete. */
02040 
02041       /* Important: reset the conn pointer so that we don't point to memory
02042          that could be freed anytime */
02043       data->easy_conn = NULL;
02044 
02045       Curl_expire_clear(data); /* stop all timers */
02046       break;
02047 
02048     case CURLM_STATE_MSGSENT:
02049       data->result = result;
02050       return CURLM_OK; /* do nothing */
02051 
02052     default:
02053       return CURLM_INTERNAL_ERROR;
02054     }
02055     statemachine_end:
02056 
02057     if(data->mstate < CURLM_STATE_COMPLETED) {
02058       if(result) {
02059         /*
02060          * If an error was returned, and we aren't in completed state now,
02061          * then we go to completed and consider this transfer aborted.
02062          */
02063 
02064         /* NOTE: no attempt to disconnect connections must be made
02065            in the case blocks above - cleanup happens only here */
02066 
02067         data->state.pipe_broke = FALSE;
02068 
02069         /* Check if we can move pending requests to send pipe */
02070         Curl_multi_process_pending_handles(multi);
02071 
02072         if(data->easy_conn) {
02073           /* if this has a connection, unsubscribe from the pipelines */
02074           Curl_pipeline_leave_write(data->easy_conn);
02075           Curl_pipeline_leave_read(data->easy_conn);
02076           Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
02077           Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
02078 
02079           if(stream_error) {
02080             /* Don't attempt to send data over a connection that timed out */
02081             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
02082             /* disconnect properly */
02083             Curl_disconnect(data->easy_conn, dead_connection);
02084 
02085             /* This is where we make sure that the easy_conn pointer is reset.
02086                We don't have to do this in every case block above where a
02087                failure is detected */
02088             data->easy_conn = NULL;
02089           }
02090         }
02091         else if(data->mstate == CURLM_STATE_CONNECT) {
02092           /* Curl_connect() failed */
02093           (void)Curl_posttransfer(data);
02094         }
02095 
02096         multistate(data, CURLM_STATE_COMPLETED);
02097       }
02098       /* if there's still a connection to use, call the progress function */
02099       else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
02100         /* aborted due to progress callback return code must close the
02101            connection */
02102         result = CURLE_ABORTED_BY_CALLBACK;
02103         streamclose(data->easy_conn, "Aborted by callback");
02104 
02105         /* if not yet in DONE state, go there, otherwise COMPLETED */
02106         multistate(data, (data->mstate < CURLM_STATE_DONE)?
02107                    CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
02108         rc = CURLM_CALL_MULTI_PERFORM;
02109       }
02110     }
02111 
02112     if(CURLM_STATE_COMPLETED == data->mstate) {
02113       /* now fill in the Curl_message with this info */
02114       msg = &data->msg;
02115 
02116       msg->extmsg.msg = CURLMSG_DONE;
02117       msg->extmsg.easy_handle = data;
02118       msg->extmsg.data.result = result;
02119 
02120       rc = multi_addmsg(multi, msg);
02121 
02122       multistate(data, CURLM_STATE_MSGSENT);
02123     }
02124   } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
02125 
02126   data->result = result;
02127 
02128 
02129   return rc;
02130 }
02131 
02132 
02133 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
02134 {
02135   struct Curl_easy *data;
02136   CURLMcode returncode=CURLM_OK;
02137   struct Curl_tree *t;
02138   struct timeval now = Curl_tvnow();
02139 
02140   if(!GOOD_MULTI_HANDLE(multi))
02141     return CURLM_BAD_HANDLE;
02142 
02143   data=multi->easyp;
02144   while(data) {
02145     CURLMcode result;
02146     SIGPIPE_VARIABLE(pipe_st);
02147 
02148     sigpipe_ignore(data, &pipe_st);
02149     result = multi_runsingle(multi, now, data);
02150     sigpipe_restore(&pipe_st);
02151 
02152     if(result)
02153       returncode = result;
02154 
02155     data = data->next; /* operate on next handle */
02156   }
02157 
02158   /*
02159    * Simply remove all expired timers from the splay since handles are dealt
02160    * with unconditionally by this function and curl_multi_timeout() requires
02161    * that already passed/handled expire times are removed from the splay.
02162    *
02163    * It is important that the 'now' value is set at the entry of this function
02164    * and not for the current time as it may have ticked a little while since
02165    * then and then we risk this loop to remove timers that actually have not
02166    * been handled!
02167    */
02168   do {
02169     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
02170     if(t)
02171       /* the removed may have another timeout in queue */
02172       (void)add_next_timeout(now, multi, t->payload);
02173 
02174   } while(t);
02175 
02176   *running_handles = multi->num_alive;
02177 
02178   if(CURLM_OK >= returncode)
02179     update_timer(multi);
02180 
02181   return returncode;
02182 }
02183 
02184 static void close_all_connections(struct Curl_multi *multi)
02185 {
02186   struct connectdata *conn;
02187 
02188   conn = Curl_conncache_find_first_connection(&multi->conn_cache);
02189   while(conn) {
02190     SIGPIPE_VARIABLE(pipe_st);
02191     conn->data = multi->closure_handle;
02192 
02193     sigpipe_ignore(conn->data, &pipe_st);
02194     conn->data->easy_conn = NULL; /* clear the easy handle's connection
02195                                      pointer */
02196     /* This will remove the connection from the cache */
02197     connclose(conn, "kill all");
02198     (void)Curl_disconnect(conn, FALSE);
02199     sigpipe_restore(&pipe_st);
02200 
02201     conn = Curl_conncache_find_first_connection(&multi->conn_cache);
02202   }
02203 }
02204 
02205 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
02206 {
02207   struct Curl_easy *data;
02208   struct Curl_easy *nextdata;
02209 
02210   if(GOOD_MULTI_HANDLE(multi)) {
02211     bool restore_pipe = FALSE;
02212     SIGPIPE_VARIABLE(pipe_st);
02213 
02214     multi->type = 0; /* not good anymore */
02215 
02216     /* Close all the connections in the connection cache */
02217     close_all_connections(multi);
02218 
02219     if(multi->closure_handle) {
02220       sigpipe_ignore(multi->closure_handle, &pipe_st);
02221       restore_pipe = TRUE;
02222 
02223       multi->closure_handle->dns.hostcache = &multi->hostcache;
02224       Curl_hostcache_clean(multi->closure_handle,
02225                            multi->closure_handle->dns.hostcache);
02226 
02227       Curl_close(multi->closure_handle);
02228     }
02229 
02230     Curl_hash_destroy(&multi->sockhash);
02231     Curl_conncache_destroy(&multi->conn_cache);
02232     Curl_llist_destroy(multi->msglist, NULL);
02233     Curl_llist_destroy(multi->pending, NULL);
02234 
02235     /* remove all easy handles */
02236     data = multi->easyp;
02237     while(data) {
02238       nextdata=data->next;
02239       if(data->dns.hostcachetype == HCACHE_MULTI) {
02240         /* clear out the usage of the shared DNS cache */
02241         Curl_hostcache_clean(data, data->dns.hostcache);
02242         data->dns.hostcache = NULL;
02243         data->dns.hostcachetype = HCACHE_NONE;
02244       }
02245 
02246       /* Clear the pointer to the connection cache */
02247       data->state.conn_cache = NULL;
02248       data->multi = NULL; /* clear the association */
02249 
02250       data = nextdata;
02251     }
02252 
02253     Curl_hash_destroy(&multi->hostcache);
02254 
02255     /* Free the blacklists by setting them to NULL */
02256     Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
02257     Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
02258 
02259     free(multi);
02260     if(restore_pipe)
02261       sigpipe_restore(&pipe_st);
02262 
02263     return CURLM_OK;
02264   }
02265   else
02266     return CURLM_BAD_HANDLE;
02267 }
02268 
02269 /*
02270  * curl_multi_info_read()
02271  *
02272  * This function is the primary way for a multi/multi_socket application to
02273  * figure out if a transfer has ended. We MUST make this function as fast as
02274  * possible as it will be polled frequently and we MUST NOT scan any lists in
02275  * here to figure out things. We must scale fine to thousands of handles and
02276  * beyond. The current design is fully O(1).
02277  */
02278 
02279 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
02280 {
02281   struct Curl_message *msg;
02282 
02283   *msgs_in_queue = 0; /* default to none */
02284 
02285   if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
02286     /* there is one or more messages in the list */
02287     struct curl_llist_element *e;
02288 
02289     /* extract the head of the list to return */
02290     e = multi->msglist->head;
02291 
02292     msg = e->ptr;
02293 
02294     /* remove the extracted entry */
02295     Curl_llist_remove(multi->msglist, e, NULL);
02296 
02297     *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
02298 
02299     return &msg->extmsg;
02300   }
02301   else
02302     return NULL;
02303 }
02304 
02305 /*
02306  * singlesocket() checks what sockets we deal with and their "action state"
02307  * and if we have a different state in any of those sockets from last time we
02308  * call the callback accordingly.
02309  */
02310 static void singlesocket(struct Curl_multi *multi,
02311                          struct Curl_easy *data)
02312 {
02313   curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
02314   int i;
02315   struct Curl_sh_entry *entry;
02316   curl_socket_t s;
02317   int num;
02318   unsigned int curraction;
02319 
02320   for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
02321     socks[i] = CURL_SOCKET_BAD;
02322 
02323   /* Fill in the 'current' struct with the state as it is now: what sockets to
02324      supervise and for what actions */
02325   curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
02326 
02327   /* We have 0 .. N sockets already and we get to know about the 0 .. M
02328      sockets we should have from now on. Detect the differences, remove no
02329      longer supervised ones and add new ones */
02330 
02331   /* walk over the sockets we got right now */
02332   for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
02333         (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
02334       i++) {
02335     int action = CURL_POLL_NONE;
02336 
02337     s = socks[i];
02338 
02339     /* get it from the hash */
02340     entry = sh_getentry(&multi->sockhash, s);
02341 
02342     if(curraction & GETSOCK_READSOCK(i))
02343       action |= CURL_POLL_IN;
02344     if(curraction & GETSOCK_WRITESOCK(i))
02345       action |= CURL_POLL_OUT;
02346 
02347     if(entry) {
02348       /* yeps, already present so check if it has the same action set */
02349       if(entry->action == action)
02350         /* same, continue */
02351         continue;
02352     }
02353     else {
02354       /* this is a socket we didn't have before, add it! */
02355       entry = sh_addentry(&multi->sockhash, s, data);
02356       if(!entry)
02357         /* fatal */
02358         return;
02359     }
02360 
02361     /* we know (entry != NULL) at this point, see the logic above */
02362     if(multi->socket_cb)
02363       multi->socket_cb(data,
02364                        s,
02365                        action,
02366                        multi->socket_userp,
02367                        entry->socketp);
02368 
02369     entry->action = action; /* store the current action state */
02370   }
02371 
02372   num = i; /* number of sockets */
02373 
02374   /* when we've walked over all the sockets we should have right now, we must
02375      make sure to detect sockets that are removed */
02376   for(i=0; i< data->numsocks; i++) {
02377     int j;
02378     s = data->sockets[i];
02379     for(j=0; j<num; j++) {
02380       if(s == socks[j]) {
02381         /* this is still supervised */
02382         s = CURL_SOCKET_BAD;
02383         break;
02384       }
02385     }
02386 
02387     entry = sh_getentry(&multi->sockhash, s);
02388     if(entry) {
02389       /* this socket has been removed. Tell the app to remove it */
02390       bool remove_sock_from_hash = TRUE;
02391 
02392       /* check if the socket to be removed serves a connection which has
02393          other easy-s in a pipeline. In this case the socket should not be
02394          removed. */
02395       struct connectdata *easy_conn = data->easy_conn;
02396       if(easy_conn) {
02397         if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
02398           /* the handle should not be removed from the pipe yet */
02399           remove_sock_from_hash = FALSE;
02400 
02401           /* Update the sockhash entry to instead point to the next in line
02402              for the recv_pipe, or the first (in case this particular easy
02403              isn't already) */
02404           if(entry->easy == data) {
02405             if(Curl_recvpipe_head(data, easy_conn))
02406               entry->easy = easy_conn->recv_pipe->head->next->ptr;
02407             else
02408               entry->easy = easy_conn->recv_pipe->head->ptr;
02409           }
02410         }
02411         if(easy_conn->send_pipe  && easy_conn->send_pipe->size > 1) {
02412           /* the handle should not be removed from the pipe yet */
02413           remove_sock_from_hash = FALSE;
02414 
02415           /* Update the sockhash entry to instead point to the next in line
02416              for the send_pipe, or the first (in case this particular easy
02417              isn't already) */
02418           if(entry->easy == data) {
02419             if(Curl_sendpipe_head(data, easy_conn))
02420               entry->easy = easy_conn->send_pipe->head->next->ptr;
02421             else
02422               entry->easy = easy_conn->send_pipe->head->ptr;
02423           }
02424         }
02425         /* Don't worry about overwriting recv_pipe head with send_pipe_head,
02426            when action will be asked on the socket (see multi_socket()), the
02427            head of the correct pipe will be taken according to the
02428            action. */
02429       }
02430 
02431       if(remove_sock_from_hash) {
02432         /* in this case 'entry' is always non-NULL */
02433         if(multi->socket_cb)
02434           multi->socket_cb(data,
02435                            s,
02436                            CURL_POLL_REMOVE,
02437                            multi->socket_userp,
02438                            entry->socketp);
02439         sh_delentry(&multi->sockhash, s);
02440       }
02441     } /* if sockhash entry existed */
02442   } /* for loop over numsocks */
02443 
02444   memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
02445   data->numsocks = num;
02446 }
02447 
02448 /*
02449  * Curl_multi_closed()
02450  *
02451  * Used by the connect code to tell the multi_socket code that one of the
02452  * sockets we were using is about to be closed.  This function will then
02453  * remove it from the sockethash for this handle to make the multi_socket API
02454  * behave properly, especially for the case when libcurl will create another
02455  * socket again and it gets the same file descriptor number.
02456  */
02457 
02458 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
02459 {
02460   struct Curl_multi *multi = conn->data->multi;
02461   if(multi) {
02462     /* this is set if this connection is part of a handle that is added to
02463        a multi handle, and only then this is necessary */
02464     struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
02465 
02466     if(entry) {
02467       if(multi->socket_cb)
02468         multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
02469                          multi->socket_userp,
02470                          entry->socketp);
02471 
02472       /* now remove it from the socket hash */
02473       sh_delentry(&multi->sockhash, s);
02474     }
02475   }
02476 }
02477 
02478 
02479 
02480 /*
02481  * add_next_timeout()
02482  *
02483  * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
02484  * when it has just been removed from the splay tree because the timeout has
02485  * expired. This function is then to advance in the list to pick the next
02486  * timeout to use (skip the already expired ones) and add this node back to
02487  * the splay tree again.
02488  *
02489  * The splay tree only has each sessionhandle as a single node and the nearest
02490  * timeout is used to sort it on.
02491  */
02492 static CURLMcode add_next_timeout(struct timeval now,
02493                                   struct Curl_multi *multi,
02494                                   struct Curl_easy *d)
02495 {
02496   struct timeval *tv = &d->state.expiretime;
02497   struct curl_llist *list = d->state.timeoutlist;
02498   struct curl_llist_element *e;
02499 
02500   /* move over the timeout list for this specific handle and remove all
02501      timeouts that are now passed tense and store the next pending
02502      timeout in *tv */
02503   for(e = list->head; e;) {
02504     struct curl_llist_element *n = e->next;
02505     time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
02506     if(diff <= 0)
02507       /* remove outdated entry */
02508       Curl_llist_remove(list, e, NULL);
02509     else
02510       /* the list is sorted so get out on the first mismatch */
02511       break;
02512     e = n;
02513   }
02514   e = list->head;
02515   if(!e) {
02516     /* clear the expire times within the handles that we remove from the
02517        splay tree */
02518     tv->tv_sec = 0;
02519     tv->tv_usec = 0;
02520   }
02521   else {
02522     /* copy the first entry to 'tv' */
02523     memcpy(tv, e->ptr, sizeof(*tv));
02524 
02525     /* remove first entry from list */
02526     Curl_llist_remove(list, e, NULL);
02527 
02528     /* insert this node again into the splay */
02529     multi->timetree = Curl_splayinsert(*tv, multi->timetree,
02530                                        &d->state.timenode);
02531   }
02532   return CURLM_OK;
02533 }
02534 
02535 static CURLMcode multi_socket(struct Curl_multi *multi,
02536                               bool checkall,
02537                               curl_socket_t s,
02538                               int ev_bitmask,
02539                               int *running_handles)
02540 {
02541   CURLMcode result = CURLM_OK;
02542   struct Curl_easy *data = NULL;
02543   struct Curl_tree *t;
02544   struct timeval now = Curl_tvnow();
02545 
02546   if(checkall) {
02547     /* *perform() deals with running_handles on its own */
02548     result = curl_multi_perform(multi, running_handles);
02549 
02550     /* walk through each easy handle and do the socket state change magic
02551        and callbacks */
02552     if(result != CURLM_BAD_HANDLE) {
02553       data=multi->easyp;
02554       while(data) {
02555         singlesocket(multi, data);
02556         data = data->next;
02557       }
02558     }
02559 
02560     /* or should we fall-through and do the timer-based stuff? */
02561     return result;
02562   }
02563   else if(s != CURL_SOCKET_TIMEOUT) {
02564 
02565     struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
02566 
02567     if(!entry)
02568       /* Unmatched socket, we can't act on it but we ignore this fact.  In
02569          real-world tests it has been proved that libevent can in fact give
02570          the application actions even though the socket was just previously
02571          asked to get removed, so thus we better survive stray socket actions
02572          and just move on. */
02573       ;
02574     else {
02575       SIGPIPE_VARIABLE(pipe_st);
02576 
02577       data = entry->easy;
02578 
02579       if(data->magic != CURLEASY_MAGIC_NUMBER)
02580         /* bad bad bad bad bad bad bad */
02581         return CURLM_INTERNAL_ERROR;
02582 
02583       /* If the pipeline is enabled, take the handle which is in the head of
02584          the pipeline. If we should write into the socket, take the send_pipe
02585          head.  If we should read from the socket, take the recv_pipe head. */
02586       if(data->easy_conn) {
02587         if((ev_bitmask & CURL_POLL_OUT) &&
02588            data->easy_conn->send_pipe &&
02589            data->easy_conn->send_pipe->head)
02590           data = data->easy_conn->send_pipe->head->ptr;
02591         else if((ev_bitmask & CURL_POLL_IN) &&
02592                 data->easy_conn->recv_pipe &&
02593                 data->easy_conn->recv_pipe->head)
02594           data = data->easy_conn->recv_pipe->head->ptr;
02595       }
02596 
02597       if(data->easy_conn &&
02598          !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
02599         /* set socket event bitmask if they're not locked */
02600         data->easy_conn->cselect_bits = ev_bitmask;
02601 
02602       sigpipe_ignore(data, &pipe_st);
02603       result = multi_runsingle(multi, now, data);
02604       sigpipe_restore(&pipe_st);
02605 
02606       if(data->easy_conn &&
02607          !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
02608         /* clear the bitmask only if not locked */
02609         data->easy_conn->cselect_bits = 0;
02610 
02611       if(CURLM_OK >= result)
02612         /* get the socket(s) and check if the state has been changed since
02613            last */
02614         singlesocket(multi, data);
02615 
02616       /* Now we fall-through and do the timer-based stuff, since we don't want
02617          to force the user to have to deal with timeouts as long as at least
02618          one connection in fact has traffic. */
02619 
02620       data = NULL; /* set data to NULL again to avoid calling
02621                       multi_runsingle() in case there's no need to */
02622       now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
02623                              may have taken some time */
02624     }
02625   }
02626   else {
02627     /* Asked to run due to time-out. Clear the 'lastcall' variable to force
02628        update_timer() to trigger a callback to the app again even if the same
02629        timeout is still the one to run after this call. That handles the case
02630        when the application asks libcurl to run the timeout prematurely. */
02631     memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
02632   }
02633 
02634   /*
02635    * The loop following here will go on as long as there are expire-times left
02636    * to process in the splay and 'data' will be re-assigned for every expired
02637    * handle we deal with.
02638    */
02639   do {
02640     /* the first loop lap 'data' can be NULL */
02641     if(data) {
02642       SIGPIPE_VARIABLE(pipe_st);
02643 
02644       sigpipe_ignore(data, &pipe_st);
02645       result = multi_runsingle(multi, now, data);
02646       sigpipe_restore(&pipe_st);
02647 
02648       if(CURLM_OK >= result)
02649         /* get the socket(s) and check if the state has been changed since
02650            last */
02651         singlesocket(multi, data);
02652     }
02653 
02654     /* Check if there's one (more) expired timer to deal with! This function
02655        extracts a matching node if there is one */
02656 
02657     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
02658     if(t) {
02659       data = t->payload; /* assign this for next loop */
02660       (void)add_next_timeout(now, multi, t->payload);
02661     }
02662 
02663   } while(t);
02664 
02665   *running_handles = multi->num_alive;
02666   return result;
02667 }
02668 
02669 #undef curl_multi_setopt
02670 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
02671                             CURLMoption option, ...)
02672 {
02673   CURLMcode res = CURLM_OK;
02674   va_list param;
02675 
02676   if(!GOOD_MULTI_HANDLE(multi))
02677     return CURLM_BAD_HANDLE;
02678 
02679   va_start(param, option);
02680 
02681   switch(option) {
02682   case CURLMOPT_SOCKETFUNCTION:
02683     multi->socket_cb = va_arg(param, curl_socket_callback);
02684     break;
02685   case CURLMOPT_SOCKETDATA:
02686     multi->socket_userp = va_arg(param, void *);
02687     break;
02688   case CURLMOPT_PUSHFUNCTION:
02689     multi->push_cb = va_arg(param, curl_push_callback);
02690     break;
02691   case CURLMOPT_PUSHDATA:
02692     multi->push_userp = va_arg(param, void *);
02693     break;
02694   case CURLMOPT_PIPELINING:
02695     multi->pipelining = va_arg(param, long);
02696     break;
02697   case CURLMOPT_TIMERFUNCTION:
02698     multi->timer_cb = va_arg(param, curl_multi_timer_callback);
02699     break;
02700   case CURLMOPT_TIMERDATA:
02701     multi->timer_userp = va_arg(param, void *);
02702     break;
02703   case CURLMOPT_MAXCONNECTS:
02704     multi->maxconnects = va_arg(param, long);
02705     break;
02706   case CURLMOPT_MAX_HOST_CONNECTIONS:
02707     multi->max_host_connections = va_arg(param, long);
02708     break;
02709   case CURLMOPT_MAX_PIPELINE_LENGTH:
02710     multi->max_pipeline_length = va_arg(param, long);
02711     break;
02712   case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
02713     multi->content_length_penalty_size = va_arg(param, long);
02714     break;
02715   case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
02716     multi->chunk_length_penalty_size = va_arg(param, long);
02717     break;
02718   case CURLMOPT_PIPELINING_SITE_BL:
02719     res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
02720                                            &multi->pipelining_site_bl);
02721     break;
02722   case CURLMOPT_PIPELINING_SERVER_BL:
02723     res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
02724                                              &multi->pipelining_server_bl);
02725     break;
02726   case CURLMOPT_MAX_TOTAL_CONNECTIONS:
02727     multi->max_total_connections = va_arg(param, long);
02728     break;
02729   default:
02730     res = CURLM_UNKNOWN_OPTION;
02731     break;
02732   }
02733   va_end(param);
02734   return res;
02735 }
02736 
02737 /* we define curl_multi_socket() in the public multi.h header */
02738 #undef curl_multi_socket
02739 
02740 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
02741                             int *running_handles)
02742 {
02743   CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
02744   if(CURLM_OK >= result)
02745     update_timer(multi);
02746   return result;
02747 }
02748 
02749 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
02750                                    int ev_bitmask, int *running_handles)
02751 {
02752   CURLMcode result = multi_socket(multi, FALSE, s,
02753                                   ev_bitmask, running_handles);
02754   if(CURLM_OK >= result)
02755     update_timer(multi);
02756   return result;
02757 }
02758 
02759 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
02760 
02761 {
02762   CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
02763                                   running_handles);
02764   if(CURLM_OK >= result)
02765     update_timer(multi);
02766   return result;
02767 }
02768 
02769 static CURLMcode multi_timeout(struct Curl_multi *multi,
02770                                long *timeout_ms)
02771 {
02772   static struct timeval tv_zero = {0, 0};
02773 
02774   if(multi->timetree) {
02775     /* we have a tree of expire times */
02776     struct timeval now = Curl_tvnow();
02777 
02778     /* splay the lowest to the bottom */
02779     multi->timetree = Curl_splay(tv_zero, multi->timetree);
02780 
02781     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
02782       /* some time left before expiration */
02783       *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
02784       if(!*timeout_ms)
02785         /*
02786          * Since we only provide millisecond resolution on the returned value
02787          * and the diff might be less than one millisecond here, we don't
02788          * return zero as that may cause short bursts of busyloops on fast
02789          * processors while the diff is still present but less than one
02790          * millisecond! instead we return 1 until the time is ripe.
02791          */
02792         *timeout_ms=1;
02793     }
02794     else
02795       /* 0 means immediately */
02796       *timeout_ms = 0;
02797   }
02798   else
02799     *timeout_ms = -1;
02800 
02801   return CURLM_OK;
02802 }
02803 
02804 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
02805                              long *timeout_ms)
02806 {
02807   /* First, make some basic checks that the CURLM handle is a good handle */
02808   if(!GOOD_MULTI_HANDLE(multi))
02809     return CURLM_BAD_HANDLE;
02810 
02811   return multi_timeout(multi, timeout_ms);
02812 }
02813 
02814 /*
02815  * Tell the application it should update its timers, if it subscribes to the
02816  * update timer callback.
02817  */
02818 static int update_timer(struct Curl_multi *multi)
02819 {
02820   long timeout_ms;
02821 
02822   if(!multi->timer_cb)
02823     return 0;
02824   if(multi_timeout(multi, &timeout_ms)) {
02825     return -1;
02826   }
02827   if(timeout_ms < 0) {
02828     static const struct timeval none={0, 0};
02829     if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
02830       multi->timer_lastcall = none;
02831       /* there's no timeout now but there was one previously, tell the app to
02832          disable it */
02833       return multi->timer_cb(multi, -1, multi->timer_userp);
02834     }
02835     return 0;
02836   }
02837 
02838   /* When multi_timeout() is done, multi->timetree points to the node with the
02839    * timeout we got the (relative) time-out time for. We can thus easily check
02840    * if this is the same (fixed) time as we got in a previous call and then
02841    * avoid calling the callback again. */
02842   if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
02843     return 0;
02844 
02845   multi->timer_lastcall = multi->timetree->key;
02846 
02847   return multi->timer_cb(multi, timeout_ms, multi->timer_userp);
02848 }
02849 
02850 /*
02851  * multi_freetimeout()
02852  *
02853  * Callback used by the llist system when a single timeout list entry is
02854  * destroyed.
02855  */
02856 static void multi_freetimeout(void *user, void *entryptr)
02857 {
02858   (void)user;
02859 
02860   /* the entry was plain malloc()'ed */
02861   free(entryptr);
02862 }
02863 
02864 /*
02865  * multi_addtimeout()
02866  *
02867  * Add a timestamp to the list of timeouts. Keep the list sorted so that head
02868  * of list is always the timeout nearest in time.
02869  *
02870  */
02871 static CURLMcode
02872 multi_addtimeout(struct curl_llist *timeoutlist,
02873                  struct timeval *stamp)
02874 {
02875   struct curl_llist_element *e;
02876   struct timeval *timedup;
02877   struct curl_llist_element *prev = NULL;
02878 
02879   timedup = malloc(sizeof(*timedup));
02880   if(!timedup)
02881     return CURLM_OUT_OF_MEMORY;
02882 
02883   /* copy the timestamp */
02884   memcpy(timedup, stamp, sizeof(*timedup));
02885 
02886   if(Curl_llist_count(timeoutlist)) {
02887     /* find the correct spot in the list */
02888     for(e = timeoutlist->head; e; e = e->next) {
02889       struct timeval *checktime = e->ptr;
02890       time_t diff = curlx_tvdiff(*checktime, *timedup);
02891       if(diff > 0)
02892         break;
02893       prev = e;
02894     }
02895 
02896   }
02897   /* else
02898      this is the first timeout on the list */
02899 
02900   if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
02901     free(timedup);
02902     return CURLM_OUT_OF_MEMORY;
02903   }
02904 
02905   return CURLM_OK;
02906 }
02907 
02908 /*
02909  * Curl_expire()
02910  *
02911  * given a number of milliseconds from now to use to set the 'act before
02912  * this'-time for the transfer, to be extracted by curl_multi_timeout()
02913  *
02914  * The timeout will be added to a queue of timeouts if it defines a moment in
02915  * time that is later than the current head of queue.
02916  */
02917 void Curl_expire(struct Curl_easy *data, time_t milli)
02918 {
02919   struct Curl_multi *multi = data->multi;
02920   struct timeval *nowp = &data->state.expiretime;
02921   int rc;
02922   struct timeval set;
02923 
02924   /* this is only interesting while there is still an associated multi struct
02925      remaining! */
02926   if(!multi)
02927     return;
02928 
02929   set = Curl_tvnow();
02930   set.tv_sec += (long)(milli/1000);
02931   set.tv_usec += (milli%1000)*1000;
02932 
02933   if(set.tv_usec >= 1000000) {
02934     set.tv_sec++;
02935     set.tv_usec -= 1000000;
02936   }
02937 
02938   if(nowp->tv_sec || nowp->tv_usec) {
02939     /* This means that the struct is added as a node in the splay tree.
02940        Compare if the new time is earlier, and only remove-old/add-new if it
02941        is. */
02942     time_t diff = curlx_tvdiff(set, *nowp);
02943     if(diff > 0) {
02944       /* the new expire time was later so just add it to the queue
02945          and get out */
02946       multi_addtimeout(data->state.timeoutlist, &set);
02947       return;
02948     }
02949 
02950     /* the new time is newer than the presently set one, so add the current
02951        to the queue and update the head */
02952     multi_addtimeout(data->state.timeoutlist, nowp);
02953 
02954     /* Since this is an updated time, we must remove the previous entry from
02955        the splay tree first and then re-add the new value */
02956     rc = Curl_splayremovebyaddr(multi->timetree,
02957                                 &data->state.timenode,
02958                                 &multi->timetree);
02959     if(rc)
02960       infof(data, "Internal error removing splay node = %d\n", rc);
02961   }
02962 
02963   *nowp = set;
02964   data->state.timenode.payload = data;
02965   multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
02966                                      &data->state.timenode);
02967 }
02968 
02969 /*
02970  * Curl_expire_latest()
02971  *
02972  * This is like Curl_expire() but will only add a timeout node to the list of
02973  * timers if there is no timeout that will expire before the given time.
02974  *
02975  * Use this function if the code logic risks calling this function many times
02976  * or if there's no particular conditional wait in the code for this specific
02977  * time-out period to expire.
02978  *
02979  */
02980 void Curl_expire_latest(struct Curl_easy *data, time_t milli)
02981 {
02982   struct timeval *expire = &data->state.expiretime;
02983 
02984   struct timeval set;
02985 
02986   set = Curl_tvnow();
02987   set.tv_sec += (long)(milli / 1000);
02988   set.tv_usec += (milli % 1000) * 1000;
02989 
02990   if(set.tv_usec >= 1000000) {
02991     set.tv_sec++;
02992     set.tv_usec -= 1000000;
02993   }
02994 
02995   if(expire->tv_sec || expire->tv_usec) {
02996     /* This means that the struct is added as a node in the splay tree.
02997        Compare if the new time is earlier, and only remove-old/add-new if it
02998          is. */
02999     time_t diff = curlx_tvdiff(set, *expire);
03000     if(diff > 0)
03001       /* the new expire time was later than the top time, so just skip this */
03002       return;
03003   }
03004 
03005   /* Just add the timeout like normal */
03006   Curl_expire(data, milli);
03007 }
03008 
03009 
03010 /*
03011  * Curl_expire_clear()
03012  *
03013  * Clear ALL timeout values for this handle.
03014  */
03015 void Curl_expire_clear(struct Curl_easy *data)
03016 {
03017   struct Curl_multi *multi = data->multi;
03018   struct timeval *nowp = &data->state.expiretime;
03019   int rc;
03020 
03021   /* this is only interesting while there is still an associated multi struct
03022      remaining! */
03023   if(!multi)
03024     return;
03025 
03026   if(nowp->tv_sec || nowp->tv_usec) {
03027     /* Since this is an cleared time, we must remove the previous entry from
03028        the splay tree */
03029     struct curl_llist *list = data->state.timeoutlist;
03030 
03031     rc = Curl_splayremovebyaddr(multi->timetree,
03032                                 &data->state.timenode,
03033                                 &multi->timetree);
03034     if(rc)
03035       infof(data, "Internal error clearing splay node = %d\n", rc);
03036 
03037     /* flush the timeout list too */
03038     while(list->size > 0)
03039       Curl_llist_remove(list, list->tail, NULL);
03040 
03041 #ifdef DEBUGBUILD
03042     infof(data, "Expire cleared\n");
03043 #endif
03044     nowp->tv_sec = 0;
03045     nowp->tv_usec = 0;
03046   }
03047 }
03048 
03049 
03050 
03051 
03052 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
03053                             void *hashp)
03054 {
03055   struct Curl_sh_entry *there = NULL;
03056 
03057   there = sh_getentry(&multi->sockhash, s);
03058 
03059   if(!there)
03060     return CURLM_BAD_SOCKET;
03061 
03062   there->socketp = hashp;
03063 
03064   return CURLM_OK;
03065 }
03066 
03067 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
03068 {
03069   return multi ? multi->max_host_connections : 0;
03070 }
03071 
03072 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
03073 {
03074   return multi ? multi->max_total_connections : 0;
03075 }
03076 
03077 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
03078 {
03079   return multi ? multi->content_length_penalty_size : 0;
03080 }
03081 
03082 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
03083 {
03084   return multi ? multi->chunk_length_penalty_size : 0;
03085 }
03086 
03087 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
03088 {
03089   return multi->pipelining_site_bl;
03090 }
03091 
03092 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
03093 {
03094   return multi->pipelining_server_bl;
03095 }
03096 
03097 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
03098 {
03099   struct curl_llist_element *e = multi->pending->head;
03100 
03101   while(e) {
03102     struct Curl_easy *data = e->ptr;
03103     struct curl_llist_element *next = e->next;
03104 
03105     if(data->mstate == CURLM_STATE_CONNECT_PEND) {
03106       multistate(data, CURLM_STATE_CONNECT);
03107 
03108       /* Remove this node from the list */
03109       Curl_llist_remove(multi->pending, e, NULL);
03110 
03111       /* Make sure that the handle will be processed soonish. */
03112       Curl_expire_latest(data, 0);
03113     }
03114 
03115     e = next; /* operate on next handle */
03116   }
03117 }
03118 
03119 #ifdef DEBUGBUILD
03120 void Curl_multi_dump(struct Curl_multi *multi)
03121 {
03122   struct Curl_easy *data;
03123   int i;
03124   fprintf(stderr, "* Multi status: %d handles, %d alive\n",
03125           multi->num_easy, multi->num_alive);
03126   for(data=multi->easyp; data; data = data->next) {
03127     if(data->mstate < CURLM_STATE_COMPLETED) {
03128       /* only display handles that are not completed */
03129       fprintf(stderr, "handle %p, state %s, %d sockets\n",
03130               (void *)data,
03131               statename[data->mstate], data->numsocks);
03132       for(i=0; i < data->numsocks; i++) {
03133         curl_socket_t s = data->sockets[i];
03134         struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
03135 
03136         fprintf(stderr, "%d ", (int)s);
03137         if(!entry) {
03138           fprintf(stderr, "INTERNAL CONFUSION\n");
03139           continue;
03140         }
03141         fprintf(stderr, "[%s %s] ",
03142                 entry->action&CURL_POLL_IN?"RECVING":"",
03143                 entry->action&CURL_POLL_OUT?"SENDING":"");
03144       }
03145       if(data->numsocks)
03146         fprintf(stderr, "\n");
03147     }
03148   }
03149 }
03150 #endif


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:05