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