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