1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #include <curl/curl.h>
40 #include "speedcheck.h"
41 #include "conncache.h"
42 #include "multihandle.h"
45 #include "curl_printf.h"
46 #include "curl_memory.h"
47 /* The last #include file should be: */
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.
55 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
56 #define CURL_SOCKET_HASH_TABLE_SIZE 911
59 #define CURL_CONNECTION_HASH_SIZE 97
61 #define CURL_MULTI_HANDLE 0x000bab1e
63 #define GOOD_MULTI_HANDLE(x) \
64 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
66 static void singlesocket(struct Curl_multi *multi,
67 struct SessionHandle *data);
68 static int update_timer(struct Curl_multi *multi);
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,
77 static const char * const statename[]={
100 static void multi_freetimeout(void *a, void *b);
102 /* function pointer called once when switching TO a state */
103 typedef void (*init_multistate_func)(struct SessionHandle *data);
105 /* always use this function to change state, to make debugging easier */
106 static void mstate(struct SessionHandle *data, CURLMstate state
112 CURLMstate oldstate = data->mstate;
113 static const init_multistate_func finit[CURLM_STATE_LAST] = {
116 Curl_init_CONNECT, /* CONNECT */
117 /* the rest is NULL too */
120 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
124 if(oldstate == state)
125 /* don't bother when the new state is the same as the old state */
128 data->mstate = state;
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;
136 connection_id = data->easy_conn->connection_id;
139 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
140 statename[oldstate], statename[data->mstate],
141 (void *)data, lineno, connection_id);
145 if(state == CURLM_STATE_COMPLETED)
146 /* changing to COMPLETED means there's one less easy handle 'alive' */
147 data->multi->num_alive--;
149 /* if this state has an init-function, run it */
155 #define multistate(x,y) mstate(x,y)
157 #define multistate(x,y) mstate(x,y, __LINE__)
161 * We add one of these structs to the sockhash for a particular socket
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() */
170 /* bits for 'action' having no bits means this socket is not expecting any
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,
179 if(s != CURL_SOCKET_BAD)
180 /* only look for proper sockets */
181 return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
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,
188 struct SessionHandle *data)
190 struct Curl_sh_entry *there = sh_getentry(sh, s);
191 struct Curl_sh_entry *check;
194 /* it is present, return fine */
197 /* not present, add it */
198 check = calloc(1, sizeof(struct Curl_sh_entry));
200 return NULL; /* major failure */
205 /* make/add new hash entry */
206 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
208 return NULL; /* major failure */
211 return check; /* things are good in sockhash land */
215 /* delete the given socket + handle from the hash */
216 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
218 /* We remove the hash entry. This will end up in a call to
220 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
224 * free a sockhash entry
226 static void sh_freeentry(void *freethis)
228 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
233 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
235 (void) k1_len; (void) k2_len;
237 return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
240 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
242 curl_socket_t fd = *((curl_socket_t *) key);
245 return (fd % slots_num);
249 * sh_init() creates a new socket hash and returns the handle for it.
251 * Quote from README.multi_socket:
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
266 static int sh_init(struct curl_hash *hash, int hashsize)
268 return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
275 * Called when a transfer is completed. Adds the given msg pointer to
276 * the list kept in the multi handle.
278 static CURLMcode multi_addmsg(struct Curl_multi *multi,
279 struct Curl_message *msg)
281 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
282 return CURLM_OUT_OF_MEMORY;
290 * Callback used by the llist system when a single list entry is destroyed.
292 static void multi_freeamsg(void *a, void *b)
298 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
299 int chashsize) /* connection hash */
301 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
306 multi->type = CURL_MULTI_HANDLE;
308 if(Curl_mk_dnscache(&multi->hostcache))
311 if(sh_init(&multi->sockhash, hashsize))
314 if(Curl_conncache_init(&multi->conn_cache, chashsize))
317 multi->msglist = Curl_llist_alloc(multi_freeamsg);
321 multi->pending = Curl_llist_alloc(multi_freeamsg);
325 /* allocate a new easy handle to use when closing cached connections */
326 multi->closure_handle = curl_easy_init();
327 if(!multi->closure_handle)
330 multi->closure_handle->multi = multi;
331 multi->closure_handle->state.conn_cache = &multi->conn_cache;
333 multi->max_pipeline_length = 5;
335 /* -1 means it not set by user, use the default value */
336 multi->maxconnects = -1;
337 return (CURLM *) multi;
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);
353 CURLM *curl_multi_init(void)
355 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
356 CURL_CONNECTION_HASH_SIZE);
359 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
362 struct curl_llist *timeoutlist;
363 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
364 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
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;
370 /* Verify that we got a somewhat good easy handle too */
371 if(!GOOD_EASY_HANDLE(easy_handle))
372 return CURLM_BAD_EASY_HANDLE;
374 /* Prevent users from adding same easy handle more than once and prevent
375 adding to more than one multi stack */
377 return CURLM_ADDED_ALREADY;
379 /* Allocate and initialize timeout list for easy handle */
380 timeoutlist = Curl_llist_alloc(multi_freetimeout);
382 return CURLM_OUT_OF_MEMORY;
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.
391 /* Make easy handle use timeout list initialized above */
392 data->state.timeoutlist = timeoutlist;
395 /* set the easy handle */
396 multistate(data, CURLM_STATE_INIT);
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();
403 /* only do this if the global cache init works */
404 data->dns.hostcache = global;
405 data->dns.hostcachetype = HCACHE_GLOBAL;
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;
416 /* Point to the multi's connection cache */
417 data->state.conn_cache = &multi->conn_cache;
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. */
423 /* We add this new entry last in the list. */
425 data->next = NULL; /* end of the line */
427 struct SessionHandle *last = multi->easylp;
430 multi->easylp = data; /* the new last node */
433 /* first node, make prev NULL! */
435 multi->easylp = multi->easyp = data; /* both first and last */
438 /* make the SessionHandle refer back to this multi handle */
439 data->multi = multi_handle;
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
447 Curl_expire(data, 1);
449 /* increase the node-counter */
452 /* increase the alive-counter */
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.
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
465 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
472 /* Debug-function, used like this:
474 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
476 * Enable the hash print function first by editing hash.c
478 static void debug_print_sock_hash(void *p)
480 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
482 fprintf(stderr, " [easy %p/magic %x/socket %d]",
483 (void *)sh->data, sh->data->magic, (int)sh->socket);
487 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
490 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
491 struct SessionHandle *easy = curl_handle;
492 struct SessionHandle *data = easy;
495 struct curl_llist_element *e;
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;
501 /* Verify that we got a somewhat good easy handle too */
502 if(!GOOD_EASY_HANDLE(curl_handle))
503 return CURLM_BAD_EASY_HANDLE;
505 /* Prevent users from trying to remove same easy handle more than once */
507 return CURLM_OK; /* it is already removed so let's say it is fine! */
509 premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
510 easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
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. */
516 /* this handle is "alive" so we need to count down the total number of
517 alive connections when this is removed */
520 /* When this handle gets removed, other handles may be able to get the
522 Curl_multi_process_pending_handles(multi);
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
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;
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);
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;
549 if(data->easy_conn) {
551 /* we must call Curl_done() here (if we still "own it") so that we don't
552 leave a half-baked one around */
555 /* Curl_done() clears the conn->data field to lose the association
556 between the easy handle and the connection
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);
563 /* Clear connection pipelines, if Curl_done above was not called */
564 Curl_getoff_all_pipelines(data, data->easy_conn);
567 Curl_wildcard_dtor(&data->wildcard);
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;
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;
580 /* change state without using multistate(), only to make singlesocket() do
582 data->mstate = CURLM_STATE_COMPLETED;
583 singlesocket(multi, easy); /* to let the application know what sockets that
584 vanish with this handle */
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;
592 data->multi = NULL; /* clear the association to this multi handle */
594 /* make sure there's no pending message in the queue sent from this easy
597 for(e = multi->msglist->head; e; e = e->next) {
598 struct Curl_message *msg = e->ptr;
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 */
607 /* make the previous node point to our next */
609 data->prev->next = data->next;
611 multi->easyp = data->next; /* point to first node */
613 /* make our next point to our previous node */
615 data->next->prev = data->prev;
617 multi->easylp = data->prev; /* point to last node */
620 We do not touch the easy handle here! */
621 multi->num_easy--; /* one less to care about now */
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)
630 return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
633 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
635 data->easy_conn = NULL;
638 static int waitconnect_getsock(struct connectdata *conn,
647 return GETSOCK_BLANK;
650 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
651 sock[s] = conn->tempsock[i];
652 rc |= GETSOCK_WRITESOCK(s++);
659 static int waitproxyconnect_getsock(struct connectdata *conn,
664 return GETSOCK_BLANK;
666 sock[0] = conn->sock[FIRSTSOCKET];
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);
673 return GETSOCK_WRITESOCK(0);
676 static int domore_getsock(struct connectdata *conn,
677 curl_socket_t *socks,
680 if(conn && conn->handler->domore_getsock)
681 return conn->handler->domore_getsock(conn, socks, numsocks);
682 return GETSOCK_BLANK;
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
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().
696 if(data->state.pipe_broke || !data->easy_conn)
699 if(data->mstate > CURLM_STATE_CONNECT &&
700 data->mstate < CURLM_STATE_COMPLETED) {
701 /* Set up ownership correctly */
702 data->easy_conn->data = data;
705 switch(data->mstate) {
707 #if 0 /* switch back on these cases to get the compiler to check for all enums
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
722 case CURLM_STATE_WAITRESOLVE:
723 return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
725 case CURLM_STATE_PROTOCONNECT:
726 case CURLM_STATE_SENDPROTOCONNECT:
727 return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
730 case CURLM_STATE_DOING:
731 return Curl_doing_getsock(data->easy_conn, socks, numsocks);
733 case CURLM_STATE_WAITPROXYCONNECT:
734 return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
736 case CURLM_STATE_WAITCONNECT:
737 return waitconnect_getsock(data->easy_conn, socks, numsocks);
739 case CURLM_STATE_DO_MORE:
740 return domore_getsock(data->easy_conn, socks, numsocks);
742 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
743 to waiting for the same as the *PERFORM
745 case CURLM_STATE_PERFORM:
746 case CURLM_STATE_WAITPERFORM:
747 return Curl_single_getsock(data->easy_conn, socks, numsocks);
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)
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;
762 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
765 (void)exc_fd_set; /* not used */
767 if(!GOOD_MULTI_HANDLE(multi))
768 return CURLM_BAD_HANDLE;
772 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
774 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
775 curl_socket_t s = CURL_SOCKET_BAD;
777 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
778 FD_SET(sockbunch[i], read_fd_set);
781 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
782 FD_SET(sockbunch[i], write_fd_set);
785 if(s == CURL_SOCKET_BAD)
786 /* this socket is unused, break out of loop */
789 if((int)s > this_max_fd)
790 this_max_fd = (int)s;
794 data = data->next; /* check next handle */
797 *max_fd = this_max_fd;
802 CURLMcode curl_multi_wait(CURLM *multi_handle,
803 struct curl_waitfd extra_fds[],
804 unsigned int extra_nfds,
808 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
809 struct SessionHandle *data;
810 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
813 unsigned int nfds = 0;
814 unsigned int curlfds;
815 struct pollfd *ufds = NULL;
816 long timeout_internal;
819 if(!GOOD_MULTI_HANDLE(multi))
820 return CURLM_BAD_HANDLE;
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;
829 /* Count up how many fds we have from the multi handle */
832 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
834 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
835 curl_socket_t s = CURL_SOCKET_BAD;
837 if(bitmap & GETSOCK_READSOCK(i)) {
841 if(bitmap & GETSOCK_WRITESOCK(i)) {
845 if(s == CURL_SOCKET_BAD) {
850 data = data->next; /* check next handle */
853 curlfds = nfds; /* number of internal file descriptors */
854 nfds += extra_nfds; /* add the externally provided ones */
856 if(nfds || extra_nfds) {
857 ufds = malloc(nfds * sizeof(struct pollfd));
859 return CURLM_OUT_OF_MEMORY;
863 /* only do the second loop if we found descriptors in the first stage run
867 /* Add the curl handles to our pollfds first */
870 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
872 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
873 curl_socket_t s = CURL_SOCKET_BAD;
875 if(bitmap & GETSOCK_READSOCK(i)) {
876 ufds[nfds].fd = sockbunch[i];
877 ufds[nfds].events = POLLIN;
881 if(bitmap & GETSOCK_WRITESOCK(i)) {
882 ufds[nfds].fd = sockbunch[i];
883 ufds[nfds].events = POLLOUT;
887 if(s == CURL_SOCKET_BAD) {
892 data = data->next; /* check next handle */
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;
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));
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;
926 mask |= CURL_WAIT_POLLIN;
928 mask |= CURL_WAIT_POLLOUT;
930 mask |= CURL_WAIT_POLLPRI;
932 extra_fds[i].revents = mask;
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
950 void Curl_multi_connchanged(struct Curl_multi *multi)
952 multi->recheckstate = TRUE;
956 * multi_ischanged() is called
958 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
961 * Set 'clear' to TRUE to have it also clear the state variable.
963 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
965 bool retval = multi->recheckstate;
967 multi->recheckstate = FALSE;
971 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
972 struct SessionHandle *data,
973 struct connectdata *conn)
977 rc = curl_multi_add_handle(multi, data);
979 struct SingleRequest *k = &data->req;
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);
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! */
993 static CURLMcode multi_runsingle(struct Curl_multi *multi,
995 struct SessionHandle *data)
997 struct Curl_message *msg = NULL;
1000 bool protocol_connect = FALSE;
1001 bool dophase_done = FALSE;
1004 CURLcode result = CURLE_OK;
1005 struct SingleRequest *k;
1009 if(!GOOD_EASY_HANDLE(data))
1010 return CURLM_BAD_EASY_HANDLE;
1013 bool disconnect_conn = FALSE;
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);
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;
1029 data->state.pipe_broke = FALSE;
1030 data->easy_conn = NULL;
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
1040 failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
1041 return CURLM_INTERNAL_ERROR;
1044 if(multi_ischanged(multi, TRUE)) {
1045 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
1046 Curl_multi_process_pending_handles(multi);
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;
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 */
1060 timeout_ms = Curl_timeleft(data, &now,
1061 (data->mstate <= CURLM_STATE_WAITDO)?
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));
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);
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),
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;
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;
1101 switch(data->mstate) {
1102 case CURLM_STATE_INIT:
1103 /* init this transfer. */
1104 result=Curl_pretransfer(data);
1107 /* after init, go CONNECT */
1108 multistate(data, CURLM_STATE_CONNECT);
1109 Curl_pgrsTime(data, TIMER_STARTOP);
1110 rc = CURLM_CALL_MULTI_PERFORM;
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. */
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);
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;
1138 /* Add this handle to the send or pend pipeline */
1139 result = Curl_add_handle_to_pipeline(data, data->easy_conn);
1141 disconnect_conn = TRUE;
1144 /* We're now waiting for an asynchronous name lookup */
1145 multistate(data, CURLM_STATE_WAITRESOLVE);
1147 /* after the connect has been sent off, go WAITCONNECT unless the
1148 protocol connect is already done and we can go directly to
1150 rc = CURLM_CALL_MULTI_PERFORM;
1152 if(protocol_connect)
1153 multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
1154 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1156 #ifndef CURL_DISABLE_HTTP
1157 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1158 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1161 multistate(data, CURLM_STATE_WAITCONNECT);
1168 case CURLM_STATE_WAITRESOLVE:
1169 /* awaiting an asynch name resolve to complete */
1171 struct Curl_dns_entry *dns = NULL;
1172 struct connectdata *conn = data->easy_conn;
1174 /* check if we have the name resolved by now */
1175 dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
1178 #ifdef CURLRES_ASYNCH
1179 conn->async.dns = dns;
1180 conn->async.done = TRUE;
1183 infof(data, "Hostname was found in DNS cache\n");
1187 result = Curl_resolver_is_resolved(data->easy_conn, &dns);
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);
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);
1203 /* if Curl_async_resolved() returns failure, the connection struct
1204 is already freed and gone */
1205 data->easy_conn = NULL; /* no more connection */
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);
1213 #ifndef CURL_DISABLE_HTTP
1214 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1215 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1218 multistate(data, CURLM_STATE_WAITCONNECT);
1224 /* failure detected */
1225 disconnect_conn = TRUE;
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);
1236 if(data->easy_conn->bits.proxy_connect_closed) {
1237 rc = CURLM_CALL_MULTI_PERFORM;
1238 /* connect back to proxy again */
1240 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1241 multistate(data, CURLM_STATE_CONNECT);
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);
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);
1263 /* failure detected */
1264 /* Just break, the cleaning up is handled all in one place */
1265 disconnect_conn = TRUE;
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);
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;
1282 /* failure detected */
1283 Curl_posttransfer(data);
1284 Curl_done(&data->easy_conn, result, TRUE);
1285 disconnect_conn = TRUE;
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;
1299 /* failure detected */
1300 Curl_posttransfer(data);
1301 Curl_done(&data->easy_conn, result, TRUE);
1302 disconnect_conn = TRUE;
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;
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);
1321 rc = CURLM_CALL_MULTI_PERFORM;
1324 /* Perform the protocol's DO action */
1325 result = Curl_do(&data->easy_conn, &dophase_done);
1327 /* When Curl_do() returns failure, data->easy_conn might be NULL! */
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;
1342 /* DO was not completed in one function call, we must continue
1344 multistate(data, CURLM_STATE_DOING);
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);
1356 /* we're done with the DO, now DO_DONE */
1357 multistate(data, CURLM_STATE_DO_DONE);
1358 rc = CURLM_CALL_MULTI_PERFORM;
1361 else if((CURLE_SEND_ERROR == result) &&
1362 data->easy_conn->bits.reuse) {
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.
1368 char *newurl = NULL;
1369 followtype follow=FOLLOW_NONE;
1373 drc = Curl_retry_request(data->easy_conn, &newurl);
1375 /* a failure here pretty much implies an out of memory */
1377 disconnect_conn = TRUE;
1380 retry = (newurl)?TRUE:FALSE;
1382 Curl_posttransfer(data);
1383 drc = Curl_done(&data->easy_conn, result, FALSE);
1385 /* When set to retry the connection, we must to go back to
1386 * the CONNECT state */
1388 if(!drc || (drc == CURLE_SEND_ERROR)) {
1389 follow = FOLLOW_RETRY;
1390 drc = Curl_follow(data, newurl, follow);
1392 multistate(data, CURLM_STATE_CONNECT);
1393 rc = CURLM_CALL_MULTI_PERFORM;
1403 /* done didn't return OK or SEND_ERROR */
1409 /* Have error handler disconnect conn if we can't retry */
1410 disconnect_conn = TRUE;
1415 /* failure detected */
1416 Curl_posttransfer(data);
1418 Curl_done(&data->easy_conn, result, FALSE);
1419 disconnect_conn = TRUE;
1424 case CURLM_STATE_DOING:
1425 /* we continue DOING until the DO phase is complete */
1426 result = Curl_protocol_doing(data->easy_conn,
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 */
1438 /* failure detected */
1439 Curl_posttransfer(data);
1440 Curl_done(&data->easy_conn, result, FALSE);
1441 disconnect_conn = TRUE;
1445 case CURLM_STATE_DO_MORE:
1447 * When we are connected, DO MORE and then go DO_DONE
1449 result = Curl_do_more(data->easy_conn, &control);
1451 /* No need to remove this handle from the send pipeline here since that
1452 is done in Curl_done() */
1455 /* if positive, advance to DO_DONE
1456 if negative, go back to DOING */
1457 multistate(data, control==1?
1458 CURLM_STATE_DO_DONE:
1460 rc = CURLM_CALL_MULTI_PERFORM;
1463 /* stay in DO_MORE */
1467 /* failure detected */
1468 Curl_posttransfer(data);
1469 Curl_done(&data->easy_conn, result, FALSE);
1470 disconnect_conn = TRUE;
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);
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);
1486 multistate(data, CURLM_STATE_DONE);
1487 rc = CURLM_CALL_MULTI_PERFORM;
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;
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;
1504 result = Curl_speedcheck(data, now);
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);
1513 case CURLM_STATE_PERFORM:
1515 char *newurl = NULL;
1518 /* check if over send speed */
1519 if((data->set.max_send_speed > 0) &&
1520 (data->progress.ulspeed > data->set.max_send_speed)) {
1523 multistate(data, CURLM_STATE_TOOFAST);
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);
1534 /* check if over recv speed */
1535 if((data->set.max_recv_speed > 0) &&
1536 (data->progress.dlspeed > data->set.max_recv_speed)) {
1539 multistate(data, CURLM_STATE_TOOFAST);
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);
1550 /* read/write data if it is ready to do so */
1551 result = Curl_readwrite(data->easy_conn, data, &done);
1555 if(!(k->keepon & KEEP_RECV))
1556 /* We're done receiving */
1557 Curl_pipeline_leave_read(data->easy_conn);
1559 if(!(k->keepon & KEEP_SEND))
1560 /* We're done sending */
1561 Curl_pipeline_leave_write(data->easy_conn);
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.
1568 CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
1570 retry = (newurl)?TRUE:FALSE;
1573 /* if we are to retry, set the result to OK and consider the
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.
1589 if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
1590 connclose(data->easy_conn, "Transfer returned error");
1592 Curl_posttransfer(data);
1593 Curl_done(&data->easy_conn, result, FALSE);
1596 followtype follow=FOLLOW_NONE;
1598 /* call this even if the readwrite function returned error */
1599 Curl_posttransfer(data);
1601 /* we're no longer receiving */
1602 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
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);
1608 /* Check if we can move pending requests to send pipe */
1609 Curl_multi_process_pending_handles(multi);
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) {
1615 /* if the URL is a follow-location and not just a retried request
1616 then figure out the URL here */
1618 newurl = data->req.newurl;
1619 data->req.newurl = NULL;
1620 follow = FOLLOW_REDIR;
1623 follow = FOLLOW_RETRY;
1624 result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1626 result = Curl_follow(data, newurl, follow);
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
1637 /* after the transfer is done, go DONE */
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) {
1643 newurl = data->req.location;
1644 data->req.location = NULL;
1645 result = Curl_follow(data, newurl, FOLLOW_FAKE);
1647 newurl = NULL; /* allocation was handed over Curl_follow() */
1649 disconnect_conn = TRUE;
1652 multistate(data, CURLM_STATE_DONE);
1653 rc = CURLM_CALL_MULTI_PERFORM;
1661 case CURLM_STATE_DONE:
1662 /* this state is highly transient, so run another loop after this */
1663 rc = CURLM_CALL_MULTI_PERFORM;
1665 if(data->easy_conn) {
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);
1673 /* post-transfer command */
1674 res = Curl_done(&data->easy_conn, result, FALSE);
1676 /* allow a previously set error code take precedence */
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
1687 data->easy_conn = NULL;
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);
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);
1704 case CURLM_STATE_COMPLETED:
1705 /* this is a completed transfer, it is likely to still be connected */
1707 /* This node should be delinked from the list now and we should post
1708 an information message that we are complete. */
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;
1714 Curl_expire(data, 0); /* stop all timers */
1717 case CURLM_STATE_MSGSENT:
1718 data->result = result;
1719 return CURLM_OK; /* do nothing */
1722 return CURLM_INTERNAL_ERROR;
1726 if(data->mstate < CURLM_STATE_COMPLETED) {
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.
1733 /* NOTE: no attempt to disconnect connections must be made
1734 in the case blocks above - cleanup happens only here */
1736 data->state.pipe_broke = FALSE;
1738 /* Check if we can move pending requests to send pipe */
1739 Curl_multi_process_pending_handles(multi);
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);
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);
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;
1760 else if(data->mstate == CURLM_STATE_CONNECT) {
1761 /* Curl_connect() failed */
1762 (void)Curl_posttransfer(data);
1765 multistate(data, CURLM_STATE_COMPLETED);
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
1771 result = CURLE_ABORTED_BY_CALLBACK;
1772 connclose(data->easy_conn, "Aborted by callback");
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;
1781 if(CURLM_STATE_COMPLETED == data->mstate) {
1782 /* now fill in the Curl_message with this info */
1785 msg->extmsg.msg = CURLMSG_DONE;
1786 msg->extmsg.easy_handle = data;
1787 msg->extmsg.data.result = result;
1789 rc = multi_addmsg(multi, msg);
1791 multistate(data, CURLM_STATE_MSGSENT);
1793 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
1795 data->result = result;
1802 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
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();
1810 if(!GOOD_MULTI_HANDLE(multi))
1811 return CURLM_BAD_HANDLE;
1816 struct WildcardData *wc = &data->wildcard;
1817 SIGPIPE_VARIABLE(pipe_st);
1819 if(data->set.wildcardmatch) {
1821 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1823 return CURLM_OUT_OF_MEMORY;
1827 sigpipe_ignore(data, &pipe_st);
1828 result = multi_runsingle(multi, now, data);
1829 sigpipe_restore(&pipe_st);
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);
1838 returncode = result;
1840 data = data->next; /* operate on next handle */
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.
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
1854 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1856 /* the removed may have another timeout in queue */
1857 (void)add_next_timeout(now, multi, t->payload);
1861 *running_handles = multi->num_alive;
1863 if(CURLM_OK >= returncode)
1864 update_timer(multi);
1869 static void close_all_connections(struct Curl_multi *multi)
1871 struct connectdata *conn;
1873 conn = Curl_conncache_find_first_connection(&multi->conn_cache);
1875 SIGPIPE_VARIABLE(pipe_st);
1876 conn->data = multi->closure_handle;
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);
1883 conn = Curl_conncache_find_first_connection(&multi->conn_cache);
1887 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1889 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1890 struct SessionHandle *data;
1891 struct SessionHandle *nextdata;
1893 if(GOOD_MULTI_HANDLE(multi)) {
1894 bool restore_pipe = FALSE;
1895 SIGPIPE_VARIABLE(pipe_st);
1897 multi->type = 0; /* not good anymore */
1899 /* Close all the connections in the connection cache */
1900 close_all_connections(multi);
1902 if(multi->closure_handle) {
1903 sigpipe_ignore(multi->closure_handle, &pipe_st);
1904 restore_pipe = TRUE;
1906 multi->closure_handle->dns.hostcache = &multi->hostcache;
1907 Curl_hostcache_clean(multi->closure_handle,
1908 multi->closure_handle->dns.hostcache);
1910 Curl_close(multi->closure_handle);
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);
1918 /* remove all easy handles */
1919 data = multi->easyp;
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;
1929 /* Clear the pointer to the connection cache */
1930 data->state.conn_cache = NULL;
1931 data->multi = NULL; /* clear the association */
1936 Curl_hash_destroy(&multi->hostcache);
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);
1944 sigpipe_restore(&pipe_st);
1949 return CURLM_BAD_HANDLE;
1953 * curl_multi_info_read()
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).
1962 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1964 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1965 struct Curl_message *msg;
1967 *msgs_in_queue = 0; /* default to none */
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;
1973 /* extract the head of the list to return */
1974 e = multi->msglist->head;
1978 /* remove the extracted entry */
1979 Curl_llist_remove(multi->msglist, e, NULL);
1981 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1983 return &msg->extmsg;
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.
1994 static void singlesocket(struct Curl_multi *multi,
1995 struct SessionHandle *data)
1997 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1999 struct Curl_sh_entry *entry;
2002 unsigned int curraction;
2004 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
2005 socks[i] = CURL_SOCKET_BAD;
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);
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 */
2015 /* walk over the sockets we got right now */
2016 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
2017 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2019 int action = CURL_POLL_NONE;
2023 /* get it from the hash */
2024 entry = sh_getentry(&multi->sockhash, s);
2026 if(curraction & GETSOCK_READSOCK(i))
2027 action |= CURL_POLL_IN;
2028 if(curraction & GETSOCK_WRITESOCK(i))
2029 action |= CURL_POLL_OUT;
2032 /* yeps, already present so check if it has the same action set */
2033 if(entry->action == action)
2034 /* same, continue */
2038 /* this is a socket we didn't have before, add it! */
2039 entry = sh_addentry(&multi->sockhash, s, data);
2045 /* we know (entry != NULL) at this point, see the logic above */
2046 if(multi->socket_cb)
2047 multi->socket_cb(data,
2050 multi->socket_userp,
2053 entry->action = action; /* store the current action state */
2056 num = i; /* number of sockets */
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++) {
2062 s = data->sockets[i];
2063 for(j=0; j<num; j++) {
2065 /* this is still supervised */
2066 s = CURL_SOCKET_BAD;
2071 entry = sh_getentry(&multi->sockhash, s);
2073 /* this socket has been removed. Tell the app to remove it */
2074 bool remove_sock_from_hash = TRUE;
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
2079 struct connectdata *easy_conn = data->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;
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
2088 if(entry->easy == data) {
2089 if(Curl_recvpipe_head(data, easy_conn))
2090 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2092 entry->easy = easy_conn->recv_pipe->head->ptr;
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;
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
2102 if(entry->easy == data) {
2103 if(Curl_sendpipe_head(data, easy_conn))
2104 entry->easy = easy_conn->send_pipe->head->next->ptr;
2106 entry->easy = easy_conn->send_pipe->head->ptr;
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
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,
2121 multi->socket_userp,
2123 sh_delentry(&multi->sockhash, s);
2125 } /* if sockhash entry existed */
2126 } /* for loop over numsocks */
2128 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2129 data->numsocks = num;
2133 * Curl_multi_closed()
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.
2142 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2144 struct Curl_multi *multi = conn->data->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);
2151 if(multi->socket_cb)
2152 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2153 multi->socket_userp,
2156 /* now remove it from the socket hash */
2157 sh_delentry(&multi->sockhash, s);
2165 * add_next_timeout()
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.
2173 * The splay tree only has each sessionhandle as a single node and the nearest
2174 * timeout is used to sort it on.
2176 static CURLMcode add_next_timeout(struct timeval now,
2177 struct Curl_multi *multi,
2178 struct SessionHandle *d)
2180 struct timeval *tv = &d->state.expiretime;
2181 struct curl_llist *list = d->state.timeoutlist;
2182 struct curl_llist_element *e;
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
2187 for(e = list->head; e; ) {
2188 struct curl_llist_element *n = e->next;
2189 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2191 /* remove outdated entry */
2192 Curl_llist_remove(list, e, NULL);
2194 /* the list is sorted so get out on the first mismatch */
2200 /* clear the expire times within the handles that we remove from the
2206 /* copy the first entry to 'tv' */
2207 memcpy(tv, e->ptr, sizeof(*tv));
2209 /* remove first entry from list */
2210 Curl_llist_remove(list, e, NULL);
2212 /* insert this node again into the splay */
2213 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2214 &d->state.timenode);
2219 static CURLMcode multi_socket(struct Curl_multi *multi,
2223 int *running_handles)
2225 CURLMcode result = CURLM_OK;
2226 struct SessionHandle *data = NULL;
2227 struct Curl_tree *t;
2228 struct timeval now = Curl_tvnow();
2231 /* *perform() deals with running_handles on its own */
2232 result = curl_multi_perform(multi, running_handles);
2234 /* walk through each easy handle and do the socket state change magic
2236 if(result != CURLM_BAD_HANDLE) {
2239 singlesocket(multi, data);
2244 /* or should we fall-through and do the timer-based stuff? */
2247 else if(s != CURL_SOCKET_TIMEOUT) {
2249 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
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. */
2259 SIGPIPE_VARIABLE(pipe_st);
2263 if(data->magic != CURLEASY_MAGIC_NUMBER)
2264 /* bad bad bad bad bad bad bad */
2265 return CURLM_INTERNAL_ERROR;
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;
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;
2286 sigpipe_ignore(data, &pipe_st);
2287 result = multi_runsingle(multi, now, data);
2288 sigpipe_restore(&pipe_st);
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;
2295 if(CURLM_OK >= result)
2296 /* get the socket(s) and check if the state has been changed since
2298 singlesocket(multi, data);
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. */
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 */
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));
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.
2324 /* the first loop lap 'data' can be NULL */
2326 SIGPIPE_VARIABLE(pipe_st);
2328 sigpipe_ignore(data, &pipe_st);
2329 result = multi_runsingle(multi, now, data);
2330 sigpipe_restore(&pipe_st);
2332 if(CURLM_OK >= result)
2333 /* get the socket(s) and check if the state has been changed since
2335 singlesocket(multi, data);
2338 /* Check if there's one (more) expired timer to deal with! This function
2339 extracts a matching node if there is one */
2341 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2343 data = t->payload; /* assign this for next loop */
2344 (void)add_next_timeout(now, multi, t->payload);
2349 *running_handles = multi->num_alive;
2353 #undef curl_multi_setopt
2354 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2355 CURLMoption option, ...)
2357 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2358 CURLMcode res = CURLM_OK;
2361 if(!GOOD_MULTI_HANDLE(multi))
2362 return CURLM_BAD_HANDLE;
2364 va_start(param, option);
2367 case CURLMOPT_SOCKETFUNCTION:
2368 multi->socket_cb = va_arg(param, curl_socket_callback);
2370 case CURLMOPT_SOCKETDATA:
2371 multi->socket_userp = va_arg(param, void *);
2373 case CURLMOPT_PUSHFUNCTION:
2374 multi->push_cb = va_arg(param, curl_push_callback);
2376 case CURLMOPT_PUSHDATA:
2377 multi->push_userp = va_arg(param, void *);
2379 case CURLMOPT_PIPELINING:
2380 multi->pipelining = va_arg(param, long);
2382 case CURLMOPT_TIMERFUNCTION:
2383 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2385 case CURLMOPT_TIMERDATA:
2386 multi->timer_userp = va_arg(param, void *);
2388 case CURLMOPT_MAXCONNECTS:
2389 multi->maxconnects = va_arg(param, long);
2391 case CURLMOPT_MAX_HOST_CONNECTIONS:
2392 multi->max_host_connections = va_arg(param, long);
2394 case CURLMOPT_MAX_PIPELINE_LENGTH:
2395 multi->max_pipeline_length = va_arg(param, long);
2397 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2398 multi->content_length_penalty_size = va_arg(param, long);
2400 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2401 multi->chunk_length_penalty_size = va_arg(param, long);
2403 case CURLMOPT_PIPELINING_SITE_BL:
2404 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2405 &multi->pipelining_site_bl);
2407 case CURLMOPT_PIPELINING_SERVER_BL:
2408 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2409 &multi->pipelining_server_bl);
2411 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2412 multi->max_total_connections = va_arg(param, long);
2415 res = CURLM_UNKNOWN_OPTION;
2422 /* we define curl_multi_socket() in the public multi.h header */
2423 #undef curl_multi_socket
2425 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2426 int *running_handles)
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);
2435 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2436 int ev_bitmask, int *running_handles)
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);
2445 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
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);
2455 static CURLMcode multi_timeout(struct Curl_multi *multi,
2458 static struct timeval tv_zero = {0, 0};
2460 if(multi->timetree) {
2461 /* we have a tree of expire times */
2462 struct timeval now = Curl_tvnow();
2464 /* splay the lowest to the bottom */
2465 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2467 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2468 /* some time left before expiration */
2469 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
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.
2481 /* 0 means immediately */
2490 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2493 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
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;
2499 return multi_timeout(multi, timeout_ms);
2503 * Tell the application it should update its timers, if it subscribes to the
2504 * update timer callback.
2506 static int update_timer(struct Curl_multi *multi)
2510 if(!multi->timer_cb)
2512 if(multi_timeout(multi, &timeout_ms)) {
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
2521 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
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)
2533 multi->timer_lastcall = multi->timetree->key;
2535 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2539 * multi_freetimeout()
2541 * Callback used by the llist system when a single timeout list entry is
2544 static void multi_freetimeout(void *user, void *entryptr)
2548 /* the entry was plain malloc()'ed */
2553 * multi_addtimeout()
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.
2560 multi_addtimeout(struct curl_llist *timeoutlist,
2561 struct timeval *stamp)
2563 struct curl_llist_element *e;
2564 struct timeval *timedup;
2565 struct curl_llist_element *prev = NULL;
2567 timedup = malloc(sizeof(*timedup));
2569 return CURLM_OUT_OF_MEMORY;
2571 /* copy the timestamp */
2572 memcpy(timedup, stamp, sizeof(*timedup));
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);
2586 this is the first timeout on the list */
2588 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2590 return CURLM_OUT_OF_MEMORY;
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()
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.
2605 * Pass zero to clear all timeout values for this handle.
2607 void Curl_expire(struct SessionHandle *data, long milli)
2609 struct Curl_multi *multi = data->multi;
2610 struct timeval *nowp = &data->state.expiretime;
2613 /* this is only interesting while there is still an associated multi struct
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
2623 struct curl_llist *list = data->state.timeoutlist;
2625 rc = Curl_splayremovebyaddr(multi->timetree,
2626 &data->state.timenode,
2629 infof(data, "Internal error clearing splay node = %d\n", rc);
2631 /* flush the timeout list too */
2632 while(list->size > 0)
2633 Curl_llist_remove(list, list->tail, NULL);
2636 infof(data, "Expire cleared\n");
2646 set.tv_sec += milli/1000;
2647 set.tv_usec += (milli%1000)*1000;
2649 if(set.tv_usec >= 1000000) {
2651 set.tv_usec -= 1000000;
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
2658 long diff = curlx_tvdiff(set, *nowp);
2660 /* the new expire time was later so just add it to the queue
2662 multi_addtimeout(data->state.timeoutlist, &set);
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);
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,
2676 infof(data, "Internal error removing splay node = %d\n", rc);
2680 data->state.timenode.payload = data;
2681 multi->timetree = Curl_splayinsert(*nowp,
2683 &data->state.timenode);
2686 Curl_splayprint(multi->timetree, 0, TRUE);
2691 * Curl_expire_latest()
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.
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.
2701 void Curl_expire_latest(struct SessionHandle *data, long milli)
2703 struct timeval *expire = &data->state.expiretime;
2708 set.tv_sec += milli / 1000;
2709 set.tv_usec += (milli % 1000) * 1000;
2711 if(set.tv_usec >= 1000000) {
2713 set.tv_usec -= 1000000;
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
2720 long diff = curlx_tvdiff(set, *expire);
2722 /* the new expire time was later than the top time, so just skip this */
2726 /* Just add the timeout like normal */
2727 Curl_expire(data, milli);
2730 CURLMcode curl_multi_assign(CURLM *multi_handle,
2731 curl_socket_t s, void *hashp)
2733 struct Curl_sh_entry *there = NULL;
2734 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2736 there = sh_getentry(&multi->sockhash, s);
2739 return CURLM_BAD_SOCKET;
2741 there->socketp = hashp;
2746 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2748 return multi ? multi->max_host_connections : 0;
2751 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2753 return multi ? multi->max_total_connections : 0;
2756 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2758 return multi ? multi->content_length_penalty_size : 0;
2761 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2763 return multi ? multi->chunk_length_penalty_size : 0;
2766 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2768 return multi->pipelining_site_bl;
2771 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2773 return multi->pipelining_server_bl;
2776 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2778 struct curl_llist_element *e = multi->pending->head;
2781 struct SessionHandle *data = e->ptr;
2782 struct curl_llist_element *next = e->next;
2784 if(data->mstate == CURLM_STATE_CONNECT_PEND) {
2785 multistate(data, CURLM_STATE_CONNECT);
2787 /* Remove this node from the list */
2788 Curl_llist_remove(multi->pending, e, NULL);
2790 /* Make sure that the handle will be processed soonish. */
2791 Curl_expire_latest(data, 1);
2794 e = next; /* operate on next handle */
2799 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2801 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2802 struct SessionHandle *data;
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",
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);
2816 fprintf(stderr, "%d ", (int)s);
2818 fprintf(stderr, "INTERNAL CONFUSION\n");
2821 fprintf(stderr, "[%s %s] ",
2822 entry->action&CURL_POLL_IN?"RECVING":"",
2823 entry->action&CURL_POLL_OUT?"SENDING":"");
2826 fprintf(stderr, "\n");