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


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16