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