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