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