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