1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2015, 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 http://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 /* always use this function to change state, to make debugging easier */
103 static void mstate(struct SessionHandle *data, CURLMstate state
109 CURLMstate oldstate = data->mstate;
111 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
115 if(oldstate == state)
116 /* don't bother when the new state is the same as the old state */
119 data->mstate = state;
121 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
122 if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
123 data->mstate < CURLM_STATE_COMPLETED) {
124 long connection_id = -5000;
127 connection_id = data->easy_conn->connection_id;
130 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
131 statename[oldstate], statename[data->mstate],
132 (void *)data, lineno, connection_id);
136 if(state == CURLM_STATE_COMPLETED)
137 /* changing to COMPLETED means there's one less easy handle 'alive' */
138 data->multi->num_alive--;
142 #define multistate(x,y) mstate(x,y)
144 #define multistate(x,y) mstate(x,y, __LINE__)
148 * We add one of these structs to the sockhash for a particular socket
151 struct Curl_sh_entry {
152 struct SessionHandle *easy;
153 int action; /* what action READ/WRITE this socket waits for */
154 curl_socket_t socket; /* mainly to ease debugging */
155 void *socketp; /* settable by users with curl_multi_assign() */
157 /* bits for 'action' having no bits means this socket is not expecting any
162 /* make sure this socket is present in the hash for this handle */
163 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
165 struct SessionHandle *data)
167 struct Curl_sh_entry *there =
168 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
169 struct Curl_sh_entry *check;
172 /* it is present, return fine */
175 /* not present, add it */
176 check = calloc(1, sizeof(struct Curl_sh_entry));
178 return NULL; /* major failure */
183 /* make/add new hash entry */
184 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
186 return NULL; /* major failure */
189 return check; /* things are good in sockhash land */
193 /* delete the given socket + handle from the hash */
194 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
196 struct Curl_sh_entry *there =
197 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
200 /* this socket is in the hash */
201 /* We remove the hash entry. (This'll end up in a call to
203 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
208 * free a sockhash entry
210 static void sh_freeentry(void *freethis)
212 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
217 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
219 (void) k1_len; (void) k2_len;
221 return (*((int *) k1)) == (*((int *) k2));
224 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
226 int fd = *((int *) key);
229 return (fd % (int)slots_num);
233 * sh_init() creates a new socket hash and returns the handle for it.
235 * Quote from README.multi_socket:
237 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
238 * is somewhat of a bottle neck. Its current implementation may be a bit too
239 * limiting. It simply has a fixed-size array, and on each entry in the array
240 * it has a linked list with entries. So the hash only checks which list to
241 * scan through. The code I had used so for used a list with merely 7 slots
242 * (as that is what the DNS hash uses) but with 7000 connections that would
243 * make an average of 1000 nodes in each list to run through. I upped that to
244 * 97 slots (I believe a prime is suitable) and noticed a significant speed
245 * increase. I need to reconsider the hash implementation or use a rather
246 * large default value like this. At 9000 connections I was still below 10us
250 static int sh_init(struct curl_hash *hash, int hashsize)
252 return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
259 * Called when a transfer is completed. Adds the given msg pointer to
260 * the list kept in the multi handle.
262 static CURLMcode multi_addmsg(struct Curl_multi *multi,
263 struct Curl_message *msg)
265 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
266 return CURLM_OUT_OF_MEMORY;
274 * Callback used by the llist system when a single list entry is destroyed.
276 static void multi_freeamsg(void *a, void *b)
282 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
283 int chashsize) /* connection hash */
285 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
290 multi->type = CURL_MULTI_HANDLE;
292 if(Curl_mk_dnscache(&multi->hostcache))
295 if(sh_init(&multi->sockhash, hashsize))
298 if(Curl_conncache_init(&multi->conn_cache, chashsize))
301 multi->msglist = Curl_llist_alloc(multi_freeamsg);
305 multi->pending = Curl_llist_alloc(multi_freeamsg);
309 /* allocate a new easy handle to use when closing cached connections */
310 multi->closure_handle = curl_easy_init();
311 if(!multi->closure_handle)
314 multi->closure_handle->multi = multi;
315 multi->closure_handle->state.conn_cache = &multi->conn_cache;
317 multi->max_pipeline_length = 5;
319 /* -1 means it not set by user, use the default value */
320 multi->maxconnects = -1;
321 return (CURLM *) multi;
325 Curl_hash_destroy(&multi->sockhash);
326 Curl_hash_destroy(&multi->hostcache);
327 Curl_conncache_destroy(&multi->conn_cache);
328 Curl_close(multi->closure_handle);
329 multi->closure_handle = NULL;
330 Curl_llist_destroy(multi->msglist, NULL);
331 Curl_llist_destroy(multi->pending, NULL);
337 CURLM *curl_multi_init(void)
339 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
340 CURL_CONNECTION_HASH_SIZE);
343 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
346 struct curl_llist *timeoutlist;
347 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
348 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
350 /* First, make some basic checks that the CURLM handle is a good handle */
351 if(!GOOD_MULTI_HANDLE(multi))
352 return CURLM_BAD_HANDLE;
354 /* Verify that we got a somewhat good easy handle too */
355 if(!GOOD_EASY_HANDLE(easy_handle))
356 return CURLM_BAD_EASY_HANDLE;
358 /* Prevent users from adding same easy handle more than once and prevent
359 adding to more than one multi stack */
361 return CURLM_ADDED_ALREADY;
363 /* Allocate and initialize timeout list for easy handle */
364 timeoutlist = Curl_llist_alloc(multi_freetimeout);
366 return CURLM_OUT_OF_MEMORY;
369 * No failure allowed in this function beyond this point. And no
370 * modification of easy nor multi handle allowed before this except for
371 * potential multi's connection cache growing which won't be undone in this
372 * function no matter what.
375 /* Make easy handle use timeout list initialized above */
376 data->state.timeoutlist = timeoutlist;
379 /* set the easy handle */
380 multistate(data, CURLM_STATE_INIT);
382 if((data->set.global_dns_cache) &&
383 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
384 /* global dns cache was requested but still isn't */
385 struct curl_hash *global = Curl_global_host_cache_init();
387 /* only do this if the global cache init works */
388 data->dns.hostcache = global;
389 data->dns.hostcachetype = HCACHE_GLOBAL;
392 /* for multi interface connections, we share DNS cache automatically if the
393 easy handle's one is currently not set. */
394 else if(!data->dns.hostcache ||
395 (data->dns.hostcachetype == HCACHE_NONE)) {
396 data->dns.hostcache = &multi->hostcache;
397 data->dns.hostcachetype = HCACHE_MULTI;
400 /* Point to the multi's connection cache */
401 data->state.conn_cache = &multi->conn_cache;
403 /* This adds the new entry at the 'end' of the doubly-linked circular
404 list of SessionHandle structs to try and maintain a FIFO queue so
405 the pipelined requests are in order. */
407 /* We add this new entry last in the list. */
409 data->next = NULL; /* end of the line */
411 struct SessionHandle *last = multi->easylp;
414 multi->easylp = data; /* the new last node */
417 /* first node, make prev NULL! */
419 multi->easylp = multi->easyp = data; /* both first and last */
422 /* make the SessionHandle refer back to this multi handle */
423 data->multi = multi_handle;
425 /* Set the timeout for this handle to expire really soon so that it will
426 be taken care of even when this handle is added in the midst of operation
427 when only the curl_multi_socket() API is used. During that flow, only
428 sockets that time-out or have actions will be dealt with. Since this
429 handle has no action yet, we make sure it times out to get things to
431 Curl_expire(data, 1);
433 /* increase the node-counter */
436 /* increase the alive-counter */
439 /* A somewhat crude work-around for a little glitch in update_timer() that
440 happens if the lastcall time is set to the same time when the handle is
441 removed as when the next handle is added, as then the check in
442 update_timer() that prevents calling the application multiple times with
443 the same timer infor will not trigger and then the new handle's timeout
444 will not be notified to the app.
446 The work-around is thus simply to clear the 'lastcall' variable to force
447 update_timer() to always trigger a callback to the app when a new easy
449 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
456 /* Debug-function, used like this:
458 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
460 * Enable the hash print function first by editing hash.c
462 static void debug_print_sock_hash(void *p)
464 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
466 fprintf(stderr, " [easy %p/magic %x/socket %d]",
467 (void *)sh->data, sh->data->magic, (int)sh->socket);
471 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
474 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
475 struct SessionHandle *easy = curl_handle;
476 struct SessionHandle *data = easy;
479 struct curl_llist_element *e;
481 /* First, make some basic checks that the CURLM handle is a good handle */
482 if(!GOOD_MULTI_HANDLE(multi))
483 return CURLM_BAD_HANDLE;
485 /* Verify that we got a somewhat good easy handle too */
486 if(!GOOD_EASY_HANDLE(curl_handle))
487 return CURLM_BAD_EASY_HANDLE;
489 /* Prevent users from trying to remove same easy handle more than once */
491 return CURLM_OK; /* it is already removed so let's say it is fine! */
493 premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
494 easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
497 /* If the 'state' is not INIT or COMPLETED, we might need to do something
498 nice to put the easy_handle in a good known state when this returns. */
500 /* this handle is "alive" so we need to count down the total number of
501 alive connections when this is removed */
504 /* When this handle gets removed, other handles may be able to get the
506 Curl_multi_process_pending_handles(multi);
509 if(data->easy_conn &&
510 data->mstate > CURLM_STATE_DO &&
511 data->mstate < CURLM_STATE_COMPLETED) {
512 /* If the handle is in a pipeline and has started sending off its
513 request but not received its response yet, we need to close
515 connclose(data->easy_conn, "Removed with partial response");
516 /* Set connection owner so that Curl_done() closes it.
517 We can safely do this here since connection is killed. */
518 data->easy_conn->data = easy;
519 easy_owns_conn = TRUE;
522 /* The timer must be shut down before data->multi is set to NULL,
523 else the timenode will remain in the splay tree after
524 curl_easy_cleanup is called. */
525 Curl_expire(data, 0);
527 /* destroy the timeout list that is held in the easy handle */
528 if(data->state.timeoutlist) {
529 Curl_llist_destroy(data->state.timeoutlist, NULL);
530 data->state.timeoutlist = NULL;
533 if(data->dns.hostcachetype == HCACHE_MULTI) {
534 /* stop using the multi handle's DNS cache */
535 data->dns.hostcache = NULL;
536 data->dns.hostcachetype = HCACHE_NONE;
539 if(data->easy_conn) {
541 /* we must call Curl_done() here (if we still "own it") so that we don't
542 leave a half-baked one around */
545 /* Curl_done() clears the conn->data field to lose the association
546 between the easy handle and the connection
548 Note that this ignores the return code simply because there's
549 nothing really useful to do with it anyway! */
550 (void)Curl_done(&data->easy_conn, data->result, premature);
553 /* Clear connection pipelines, if Curl_done above was not called */
554 Curl_getoff_all_pipelines(data, data->easy_conn);
557 Curl_wildcard_dtor(&data->wildcard);
559 /* as this was using a shared connection cache we clear the pointer to that
560 since we're not part of that multi handle anymore */
561 data->state.conn_cache = NULL;
563 /* change state without using multistate(), only to make singlesocket() do
565 data->mstate = CURLM_STATE_COMPLETED;
566 singlesocket(multi, easy); /* to let the application know what sockets that
567 vanish with this handle */
569 /* Remove the association between the connection and the handle */
570 if(data->easy_conn) {
571 data->easy_conn->data = NULL;
572 data->easy_conn = NULL;
575 data->multi = NULL; /* clear the association to this multi handle */
577 /* make sure there's no pending message in the queue sent from this easy
580 for(e = multi->msglist->head; e; e = e->next) {
581 struct Curl_message *msg = e->ptr;
583 if(msg->extmsg.easy_handle == easy) {
584 Curl_llist_remove(multi->msglist, e, NULL);
585 /* there can only be one from this specific handle */
590 /* make the previous node point to our next */
592 data->prev->next = data->next;
594 multi->easyp = data->next; /* point to first node */
596 /* make our next point to our previous node */
598 data->next->prev = data->prev;
600 multi->easylp = data->prev; /* point to last node */
603 We do not touch the easy handle here! */
604 multi->num_easy--; /* one less to care about now */
610 /* Return TRUE if the application asked for a certain set of pipelining */
611 bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
613 return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
616 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
618 data->easy_conn = NULL;
621 static int waitconnect_getsock(struct connectdata *conn,
630 return GETSOCK_BLANK;
633 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
634 sock[s] = conn->tempsock[i];
635 rc |= GETSOCK_WRITESOCK(s++);
642 static int waitproxyconnect_getsock(struct connectdata *conn,
647 return GETSOCK_BLANK;
649 sock[0] = conn->sock[FIRSTSOCKET];
651 /* when we've sent a CONNECT to a proxy, we should rather wait for the
652 socket to become readable to be able to get the response headers */
653 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
654 return GETSOCK_READSOCK(0);
656 return GETSOCK_WRITESOCK(0);
659 static int domore_getsock(struct connectdata *conn,
660 curl_socket_t *socks,
663 if(conn && conn->handler->domore_getsock)
664 return conn->handler->domore_getsock(conn, socks, numsocks);
665 return GETSOCK_BLANK;
668 /* returns bitmapped flags for this handle and its sockets */
669 static int multi_getsock(struct SessionHandle *data,
670 curl_socket_t *socks, /* points to numsocks number
674 /* If the pipe broke, or if there's no connection left for this easy handle,
675 then we MUST bail out now with no bitmask set. The no connection case can
676 happen when this is called from curl_multi_remove_handle() =>
677 singlesocket() => multi_getsock().
679 if(data->state.pipe_broke || !data->easy_conn)
682 if(data->mstate > CURLM_STATE_CONNECT &&
683 data->mstate < CURLM_STATE_COMPLETED) {
684 /* Set up ownership correctly */
685 data->easy_conn->data = data;
688 switch(data->mstate) {
690 #if 0 /* switch back on these cases to get the compiler to check for all enums
692 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
693 case CURLM_STATE_COMPLETED:
694 case CURLM_STATE_MSGSENT:
695 case CURLM_STATE_INIT:
696 case CURLM_STATE_CONNECT:
697 case CURLM_STATE_WAITDO:
698 case CURLM_STATE_DONE:
699 case CURLM_STATE_LAST:
700 /* this will get called with CURLM_STATE_COMPLETED when a handle is
705 case CURLM_STATE_WAITRESOLVE:
706 return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
708 case CURLM_STATE_PROTOCONNECT:
709 case CURLM_STATE_SENDPROTOCONNECT:
710 return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
713 case CURLM_STATE_DOING:
714 return Curl_doing_getsock(data->easy_conn, socks, numsocks);
716 case CURLM_STATE_WAITPROXYCONNECT:
717 return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
719 case CURLM_STATE_WAITCONNECT:
720 return waitconnect_getsock(data->easy_conn, socks, numsocks);
722 case CURLM_STATE_DO_MORE:
723 return domore_getsock(data->easy_conn, socks, numsocks);
725 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
726 to waiting for the same as the *PERFORM
728 case CURLM_STATE_PERFORM:
729 case CURLM_STATE_WAITPERFORM:
730 return Curl_single_getsock(data->easy_conn, socks, numsocks);
735 CURLMcode curl_multi_fdset(CURLM *multi_handle,
736 fd_set *read_fd_set, fd_set *write_fd_set,
737 fd_set *exc_fd_set, int *max_fd)
739 /* Scan through all the easy handles to get the file descriptors set.
740 Some easy handles may not have connected to the remote host yet,
741 and then we must make sure that is done. */
742 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
743 struct SessionHandle *data;
745 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
748 (void)exc_fd_set; /* not used */
750 if(!GOOD_MULTI_HANDLE(multi))
751 return CURLM_BAD_HANDLE;
755 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
757 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
758 curl_socket_t s = CURL_SOCKET_BAD;
760 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
761 FD_SET(sockbunch[i], read_fd_set);
764 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
765 FD_SET(sockbunch[i], write_fd_set);
768 if(s == CURL_SOCKET_BAD)
769 /* this socket is unused, break out of loop */
772 if((int)s > this_max_fd)
773 this_max_fd = (int)s;
777 data = data->next; /* check next handle */
780 *max_fd = this_max_fd;
785 CURLMcode curl_multi_wait(CURLM *multi_handle,
786 struct curl_waitfd extra_fds[],
787 unsigned int extra_nfds,
791 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
792 struct SessionHandle *data;
793 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
796 unsigned int nfds = 0;
797 unsigned int curlfds;
798 struct pollfd *ufds = NULL;
799 long timeout_internal;
801 if(!GOOD_MULTI_HANDLE(multi))
802 return CURLM_BAD_HANDLE;
804 /* If the internally desired timeout is actually shorter than requested from
805 the outside, then use the shorter time! But only if the internal timer
806 is actually larger than -1! */
807 (void)multi_timeout(multi, &timeout_internal);
808 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
809 timeout_ms = (int)timeout_internal;
811 /* Count up how many fds we have from the multi handle */
814 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
816 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
817 curl_socket_t s = CURL_SOCKET_BAD;
819 if(bitmap & GETSOCK_READSOCK(i)) {
823 if(bitmap & GETSOCK_WRITESOCK(i)) {
827 if(s == CURL_SOCKET_BAD) {
832 data = data->next; /* check next handle */
835 curlfds = nfds; /* number of internal file descriptors */
836 nfds += extra_nfds; /* add the externally provided ones */
838 if(nfds || extra_nfds) {
839 ufds = malloc(nfds * sizeof(struct pollfd));
841 return CURLM_OUT_OF_MEMORY;
845 /* only do the second loop if we found descriptors in the first stage run
849 /* Add the curl handles to our pollfds first */
852 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
854 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
855 curl_socket_t s = CURL_SOCKET_BAD;
857 if(bitmap & GETSOCK_READSOCK(i)) {
858 ufds[nfds].fd = sockbunch[i];
859 ufds[nfds].events = POLLIN;
863 if(bitmap & GETSOCK_WRITESOCK(i)) {
864 ufds[nfds].fd = sockbunch[i];
865 ufds[nfds].events = POLLOUT;
869 if(s == CURL_SOCKET_BAD) {
874 data = data->next; /* check next handle */
878 /* Add external file descriptions from poll-like struct curl_waitfd */
879 for(i = 0; i < extra_nfds; i++) {
880 ufds[nfds].fd = extra_fds[i].fd;
881 ufds[nfds].events = 0;
882 if(extra_fds[i].events & CURL_WAIT_POLLIN)
883 ufds[nfds].events |= POLLIN;
884 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
885 ufds[nfds].events |= POLLPRI;
886 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
887 ufds[nfds].events |= POLLOUT;
893 infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
894 i = Curl_poll(ufds, nfds, timeout_ms);
898 /* copy revents results from the poll to the curl_multi_wait poll
899 struct, the bit values of the actual underlying poll() implementation
900 may not be the same as the ones in the public libcurl API! */
901 for(j = 0; j < extra_nfds; j++) {
902 unsigned short mask = 0;
903 unsigned r = ufds[curlfds + j].revents;
906 mask |= CURL_WAIT_POLLIN;
908 mask |= CURL_WAIT_POLLOUT;
910 mask |= CURL_WAIT_POLLPRI;
912 extra_fds[j].revents = mask;
926 * Curl_multi_connchanged() is called to tell that there is a connection in
927 * this multi handle that has changed state (pipelining become possible, the
928 * number of allowed streams changed or similar), and a subsequent use of this
929 * multi handle should move CONNECT_PEND handles back to CONNECT to have them
932 void Curl_multi_connchanged(struct Curl_multi *multi)
934 multi->recheckstate = TRUE;
938 * multi_ischanged() is called
940 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
943 * Set 'clear' to TRUE to have it also clear the state variable.
945 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
947 bool retval = multi->recheckstate;
949 multi->recheckstate = FALSE;
953 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
954 struct SessionHandle *data,
955 struct connectdata *conn)
959 rc = curl_multi_add_handle(multi, data);
961 struct SingleRequest *k = &data->req;
963 /* pass in NULL for 'conn' here since we don't want to init the
964 connection, only this transfer */
965 Curl_init_do(data, NULL);
967 /* take this handle to the perform state right away */
968 multistate(data, CURLM_STATE_PERFORM);
969 data->easy_conn = conn;
970 k->keepon |= KEEP_RECV; /* setup to receive! */
975 static CURLMcode multi_runsingle(struct Curl_multi *multi,
977 struct SessionHandle *data)
979 struct Curl_message *msg = NULL;
982 bool protocol_connect = FALSE;
983 bool dophase_done = FALSE;
986 CURLcode result = CURLE_OK;
987 struct SingleRequest *k;
991 if(!GOOD_EASY_HANDLE(data))
992 return CURLM_BAD_EASY_HANDLE;
995 bool disconnect_conn = FALSE;
998 /* Handle the case when the pipe breaks, i.e., the connection
999 we're using gets cleaned up and we're left with nothing. */
1000 if(data->state.pipe_broke) {
1001 infof(data, "Pipe broke: handle %p, url = %s\n",
1002 (void *)data, data->state.path);
1004 if(data->mstate < CURLM_STATE_COMPLETED) {
1005 /* Head back to the CONNECT state */
1006 multistate(data, CURLM_STATE_CONNECT);
1007 rc = CURLM_CALL_MULTI_PERFORM;
1011 data->state.pipe_broke = FALSE;
1012 data->easy_conn = NULL;
1016 if(!data->easy_conn &&
1017 data->mstate > CURLM_STATE_CONNECT &&
1018 data->mstate < CURLM_STATE_DONE) {
1019 /* In all these states, the code will blindly access 'data->easy_conn'
1020 so this is precaution that it isn't NULL. And it silences static
1022 failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
1023 return CURLM_INTERNAL_ERROR;
1026 if(multi_ischanged(multi, TRUE)) {
1027 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
1028 Curl_multi_process_pending_handles(multi);
1031 if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
1032 data->mstate < CURLM_STATE_COMPLETED)
1033 /* Make sure we set the connection's current owner */
1034 data->easy_conn->data = data;
1036 if(data->easy_conn &&
1037 (data->mstate >= CURLM_STATE_CONNECT) &&
1038 (data->mstate < CURLM_STATE_COMPLETED)) {
1039 /* we need to wait for the connect state as only then is the start time
1040 stored, but we must not check already completed handles */
1042 timeout_ms = Curl_timeleft(data, &now,
1043 (data->mstate <= CURLM_STATE_WAITDO)?
1046 if(timeout_ms < 0) {
1047 /* Handle timed out */
1048 if(data->mstate == CURLM_STATE_WAITRESOLVE)
1049 failf(data, "Resolving timed out after %ld milliseconds",
1050 Curl_tvdiff(now, data->progress.t_startsingle));
1051 else if(data->mstate == CURLM_STATE_WAITCONNECT)
1052 failf(data, "Connection timed out after %ld milliseconds",
1053 Curl_tvdiff(now, data->progress.t_startsingle));
1057 failf(data, "Operation timed out after %ld milliseconds with %"
1058 CURL_FORMAT_CURL_OFF_T " out of %"
1059 CURL_FORMAT_CURL_OFF_T " bytes received",
1060 Curl_tvdiff(k->now, data->progress.t_startsingle),
1061 k->bytecount, k->size);
1064 failf(data, "Operation timed out after %ld milliseconds with %"
1065 CURL_FORMAT_CURL_OFF_T " bytes received",
1066 Curl_tvdiff(now, data->progress.t_startsingle),
1071 /* Force connection closed if the connection has indeed been used */
1072 if(data->mstate > CURLM_STATE_DO) {
1073 connclose(data->easy_conn, "Disconnected with pending data");
1074 disconnect_conn = TRUE;
1076 result = CURLE_OPERATION_TIMEDOUT;
1077 (void)Curl_done(&data->easy_conn, result, TRUE);
1078 /* Skip the statemachine and go directly to error handling section. */
1079 goto statemachine_end;
1083 switch(data->mstate) {
1084 case CURLM_STATE_INIT:
1085 /* init this transfer. */
1086 result=Curl_pretransfer(data);
1089 /* after init, go CONNECT */
1090 multistate(data, CURLM_STATE_CONNECT);
1091 Curl_pgrsTime(data, TIMER_STARTOP);
1092 rc = CURLM_CALL_MULTI_PERFORM;
1096 case CURLM_STATE_CONNECT_PEND:
1097 /* We will stay here until there is a connection available. Then
1098 we try again in the CURLM_STATE_CONNECT state. */
1101 case CURLM_STATE_CONNECT:
1102 /* Connect. We want to get a connection identifier filled in. */
1103 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1104 result = Curl_connect(data, &data->easy_conn,
1105 &async, &protocol_connect);
1106 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1107 /* There was no connection available. We will go to the pending
1108 state and wait for an available connection. */
1109 multistate(data, CURLM_STATE_CONNECT_PEND);
1111 /* add this handle to the list of connect-pending handles */
1112 if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
1113 result = CURLE_OUT_OF_MEMORY;
1120 /* Add this handle to the send or pend pipeline */
1121 result = Curl_add_handle_to_pipeline(data, data->easy_conn);
1123 disconnect_conn = TRUE;
1126 /* We're now waiting for an asynchronous name lookup */
1127 multistate(data, CURLM_STATE_WAITRESOLVE);
1129 /* after the connect has been sent off, go WAITCONNECT unless the
1130 protocol connect is already done and we can go directly to
1132 rc = CURLM_CALL_MULTI_PERFORM;
1134 if(protocol_connect)
1135 multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
1136 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1138 #ifndef CURL_DISABLE_HTTP
1139 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1140 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1143 multistate(data, CURLM_STATE_WAITCONNECT);
1150 case CURLM_STATE_WAITRESOLVE:
1151 /* awaiting an asynch name resolve to complete */
1153 struct Curl_dns_entry *dns = NULL;
1154 struct connectdata *conn = data->easy_conn;
1156 /* check if we have the name resolved by now */
1157 dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
1160 #ifdef CURLRES_ASYNCH
1161 conn->async.dns = dns;
1162 conn->async.done = TRUE;
1165 infof(data, "Hostname was found in DNS cache\n");
1169 result = Curl_resolver_is_resolved(data->easy_conn, &dns);
1171 /* Update sockets here, because the socket(s) may have been
1172 closed and the application thus needs to be told, even if it
1173 is likely that the same socket(s) will again be used further
1174 down. If the name has not yet been resolved, it is likely
1175 that new sockets have been opened in an attempt to contact
1176 another resolver. */
1177 singlesocket(multi, data);
1180 /* Perform the next step in the connection phase, and then move on
1181 to the WAITCONNECT state */
1182 result = Curl_async_resolved(data->easy_conn, &protocol_connect);
1185 /* if Curl_async_resolved() returns failure, the connection struct
1186 is already freed and gone */
1187 data->easy_conn = NULL; /* no more connection */
1189 /* call again please so that we get the next socket setup */
1190 rc = CURLM_CALL_MULTI_PERFORM;
1191 if(protocol_connect)
1192 multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
1193 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1195 #ifndef CURL_DISABLE_HTTP
1196 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1197 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1200 multistate(data, CURLM_STATE_WAITCONNECT);
1206 /* failure detected */
1207 disconnect_conn = TRUE;
1213 #ifndef CURL_DISABLE_HTTP
1214 case CURLM_STATE_WAITPROXYCONNECT:
1215 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1216 result = Curl_http_connect(data->easy_conn, &protocol_connect);
1218 rc = CURLM_CALL_MULTI_PERFORM;
1219 if(data->easy_conn->bits.proxy_connect_closed) {
1220 /* connect back to proxy again */
1222 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1223 multistate(data, CURLM_STATE_CONNECT);
1226 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1227 /* initiate protocol connect phase */
1228 multistate(data, CURLM_STATE_SENDPROTOCONNECT);
1233 case CURLM_STATE_WAITCONNECT:
1234 /* awaiting a completion of an asynch TCP connect */
1235 result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
1236 if(connected && !result) {
1237 rc = CURLM_CALL_MULTI_PERFORM;
1238 multistate(data, data->easy_conn->bits.tunnel_proxy?
1239 CURLM_STATE_WAITPROXYCONNECT:
1240 CURLM_STATE_SENDPROTOCONNECT);
1243 /* failure detected */
1244 /* Just break, the cleaning up is handled all in one place */
1245 disconnect_conn = TRUE;
1250 case CURLM_STATE_SENDPROTOCONNECT:
1251 result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
1252 if(!protocol_connect)
1253 /* switch to waiting state */
1254 multistate(data, CURLM_STATE_PROTOCONNECT);
1256 /* protocol connect has completed, go WAITDO or DO */
1257 multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
1258 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1259 rc = CURLM_CALL_MULTI_PERFORM;
1262 /* failure detected */
1263 Curl_posttransfer(data);
1264 Curl_done(&data->easy_conn, result, TRUE);
1265 disconnect_conn = TRUE;
1269 case CURLM_STATE_PROTOCONNECT:
1270 /* protocol-specific connect phase */
1271 result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
1272 if(!result && protocol_connect) {
1273 /* after the connect has completed, go WAITDO or DO */
1274 multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
1275 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1276 rc = CURLM_CALL_MULTI_PERFORM;
1279 /* failure detected */
1280 Curl_posttransfer(data);
1281 Curl_done(&data->easy_conn, result, TRUE);
1282 disconnect_conn = TRUE;
1286 case CURLM_STATE_WAITDO:
1287 /* Wait for our turn to DO when we're pipelining requests */
1288 if(Curl_pipeline_checkget_write(data, data->easy_conn)) {
1289 /* Grabbed the channel */
1290 multistate(data, CURLM_STATE_DO);
1291 rc = CURLM_CALL_MULTI_PERFORM;
1295 case CURLM_STATE_DO:
1296 if(data->set.connect_only) {
1297 /* keep connection open for application to use the socket */
1298 connkeep(data->easy_conn, "CONNECT_ONLY");
1299 multistate(data, CURLM_STATE_DONE);
1301 rc = CURLM_CALL_MULTI_PERFORM;
1304 /* Perform the protocol's DO action */
1305 result = Curl_do(&data->easy_conn, &dophase_done);
1307 /* When Curl_do() returns failure, data->easy_conn might be NULL! */
1311 /* some steps needed for wildcard matching */
1312 if(data->set.wildcardmatch) {
1313 struct WildcardData *wc = &data->wildcard;
1314 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1315 /* skip some states if it is important */
1316 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1317 multistate(data, CURLM_STATE_DONE);
1318 rc = CURLM_CALL_MULTI_PERFORM;
1322 /* DO was not completed in one function call, we must continue
1324 multistate(data, CURLM_STATE_DOING);
1328 /* after DO, go DO_DONE... or DO_MORE */
1329 else if(data->easy_conn->bits.do_more) {
1330 /* we're supposed to do more, but we need to sit down, relax
1331 and wait a little while first */
1332 multistate(data, CURLM_STATE_DO_MORE);
1336 /* we're done with the DO, now DO_DONE */
1337 multistate(data, CURLM_STATE_DO_DONE);
1338 rc = CURLM_CALL_MULTI_PERFORM;
1341 else if((CURLE_SEND_ERROR == result) &&
1342 data->easy_conn->bits.reuse) {
1344 * In this situation, a connection that we were trying to use
1345 * may have unexpectedly died. If possible, send the connection
1346 * back to the CONNECT phase so we can try again.
1348 char *newurl = NULL;
1349 followtype follow=FOLLOW_NONE;
1353 drc = Curl_retry_request(data->easy_conn, &newurl);
1355 /* a failure here pretty much implies an out of memory */
1357 disconnect_conn = TRUE;
1360 retry = (newurl)?TRUE:FALSE;
1362 Curl_posttransfer(data);
1363 drc = Curl_done(&data->easy_conn, result, FALSE);
1365 /* When set to retry the connection, we must to go back to
1366 * the CONNECT state */
1368 if(!drc || (drc == CURLE_SEND_ERROR)) {
1369 follow = FOLLOW_RETRY;
1370 drc = Curl_follow(data, newurl, follow);
1372 multistate(data, CURLM_STATE_CONNECT);
1373 rc = CURLM_CALL_MULTI_PERFORM;
1383 /* done didn't return OK or SEND_ERROR */
1389 /* Have error handler disconnect conn if we can't retry */
1390 disconnect_conn = TRUE;
1395 /* failure detected */
1396 Curl_posttransfer(data);
1398 Curl_done(&data->easy_conn, result, FALSE);
1399 disconnect_conn = TRUE;
1404 case CURLM_STATE_DOING:
1405 /* we continue DOING until the DO phase is complete */
1406 result = Curl_protocol_doing(data->easy_conn,
1410 /* after DO, go DO_DONE or DO_MORE */
1411 multistate(data, data->easy_conn->bits.do_more?
1412 CURLM_STATE_DO_MORE:
1413 CURLM_STATE_DO_DONE);
1414 rc = CURLM_CALL_MULTI_PERFORM;
1415 } /* dophase_done */
1418 /* failure detected */
1419 Curl_posttransfer(data);
1420 Curl_done(&data->easy_conn, result, FALSE);
1421 disconnect_conn = TRUE;
1425 case CURLM_STATE_DO_MORE:
1427 * When we are connected, DO MORE and then go DO_DONE
1429 result = Curl_do_more(data->easy_conn, &control);
1431 /* No need to remove this handle from the send pipeline here since that
1432 is done in Curl_done() */
1435 /* if positive, advance to DO_DONE
1436 if negative, go back to DOING */
1437 multistate(data, control==1?
1438 CURLM_STATE_DO_DONE:
1440 rc = CURLM_CALL_MULTI_PERFORM;
1443 /* stay in DO_MORE */
1447 /* failure detected */
1448 Curl_posttransfer(data);
1449 Curl_done(&data->easy_conn, result, FALSE);
1450 disconnect_conn = TRUE;
1454 case CURLM_STATE_DO_DONE:
1455 /* Move ourselves from the send to recv pipeline */
1456 Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
1457 /* Check if we can move pending requests to send pipe */
1458 Curl_multi_process_pending_handles(multi);
1460 /* Only perform the transfer if there's a good socket to work with.
1461 Having both BAD is a signal to skip immediately to DONE */
1462 if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
1463 (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
1464 multistate(data, CURLM_STATE_WAITPERFORM);
1466 multistate(data, CURLM_STATE_DONE);
1467 rc = CURLM_CALL_MULTI_PERFORM;
1470 case CURLM_STATE_WAITPERFORM:
1471 /* Wait for our turn to PERFORM */
1472 if(Curl_pipeline_checkget_read(data, data->easy_conn)) {
1473 /* Grabbed the channel */
1474 multistate(data, CURLM_STATE_PERFORM);
1475 rc = CURLM_CALL_MULTI_PERFORM;
1479 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1480 /* if both rates are within spec, resume transfer */
1481 if(Curl_pgrsUpdate(data->easy_conn))
1482 result = CURLE_ABORTED_BY_CALLBACK;
1484 result = Curl_speedcheck(data, now);
1486 if(( (data->set.max_send_speed == 0) ||
1487 (data->progress.ulspeed < data->set.max_send_speed )) &&
1488 ( (data->set.max_recv_speed == 0) ||
1489 (data->progress.dlspeed < data->set.max_recv_speed)))
1490 multistate(data, CURLM_STATE_PERFORM);
1493 case CURLM_STATE_PERFORM:
1495 char *newurl = NULL;
1498 /* check if over send speed */
1499 if((data->set.max_send_speed > 0) &&
1500 (data->progress.ulspeed > data->set.max_send_speed)) {
1503 multistate(data, CURLM_STATE_TOOFAST);
1505 /* calculate upload rate-limitation timeout. */
1506 buffersize = (int)(data->set.buffer_size ?
1507 data->set.buffer_size : BUFSIZE);
1508 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1509 data->progress.ulspeed, buffersize);
1510 Curl_expire_latest(data, timeout_ms);
1514 /* check if over recv speed */
1515 if((data->set.max_recv_speed > 0) &&
1516 (data->progress.dlspeed > data->set.max_recv_speed)) {
1519 multistate(data, CURLM_STATE_TOOFAST);
1521 /* Calculate download rate-limitation timeout. */
1522 buffersize = (int)(data->set.buffer_size ?
1523 data->set.buffer_size : BUFSIZE);
1524 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1525 data->progress.dlspeed, buffersize);
1526 Curl_expire_latest(data, timeout_ms);
1530 /* read/write data if it is ready to do so */
1531 result = Curl_readwrite(data->easy_conn, data, &done);
1535 if(!(k->keepon & KEEP_RECV))
1536 /* We're done receiving */
1537 Curl_pipeline_leave_read(data->easy_conn);
1539 if(!(k->keepon & KEEP_SEND))
1540 /* We're done sending */
1541 Curl_pipeline_leave_write(data->easy_conn);
1543 if(done || (result == CURLE_RECV_ERROR)) {
1544 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1545 * condition and the server closed the re-used connection exactly when
1546 * we wanted to use it, so figure out if that is indeed the case.
1548 CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
1550 retry = (newurl)?TRUE:FALSE;
1553 /* if we are to retry, set the result to OK and consider the
1562 * The transfer phase returned error, we mark the connection to get
1563 * closed to prevent being re-used. This is because we can't possibly
1564 * know if the connection is in a good shape or not now. Unless it is
1565 * a protocol which uses two "channels" like FTP, as then the error
1566 * happened in the data connection.
1569 if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
1570 connclose(data->easy_conn, "Transfer returned error");
1572 Curl_posttransfer(data);
1573 Curl_done(&data->easy_conn, result, FALSE);
1576 followtype follow=FOLLOW_NONE;
1578 /* call this even if the readwrite function returned error */
1579 Curl_posttransfer(data);
1581 /* we're no longer receiving */
1582 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1584 /* expire the new receiving pipeline head */
1585 if(data->easy_conn->recv_pipe->head)
1586 Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
1588 /* Check if we can move pending requests to send pipe */
1589 Curl_multi_process_pending_handles(multi);
1591 /* When we follow redirects or is set to retry the connection, we must
1592 to go back to the CONNECT state */
1593 if(data->req.newurl || retry) {
1595 /* if the URL is a follow-location and not just a retried request
1596 then figure out the URL here */
1598 newurl = data->req.newurl;
1599 data->req.newurl = NULL;
1600 follow = FOLLOW_REDIR;
1603 follow = FOLLOW_RETRY;
1604 result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1606 result = Curl_follow(data, newurl, follow);
1608 multistate(data, CURLM_STATE_CONNECT);
1609 rc = CURLM_CALL_MULTI_PERFORM;
1610 newurl = NULL; /* handed over the memory ownership to
1611 Curl_follow(), make sure we don't free() it
1617 /* after the transfer is done, go DONE */
1619 /* but first check to see if we got a location info even though we're
1620 not following redirects */
1621 if(data->req.location) {
1623 newurl = data->req.location;
1624 data->req.location = NULL;
1625 result = Curl_follow(data, newurl, FOLLOW_FAKE);
1627 newurl = NULL; /* allocation was handed over Curl_follow() */
1629 disconnect_conn = TRUE;
1632 multistate(data, CURLM_STATE_DONE);
1633 rc = CURLM_CALL_MULTI_PERFORM;
1641 case CURLM_STATE_DONE:
1642 /* this state is highly transient, so run another loop after this */
1643 rc = CURLM_CALL_MULTI_PERFORM;
1645 if(data->easy_conn) {
1648 /* Remove ourselves from the receive pipeline, if we are there. */
1649 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1650 /* Check if we can move pending requests to send pipe */
1651 Curl_multi_process_pending_handles(multi);
1653 /* post-transfer command */
1654 res = Curl_done(&data->easy_conn, result, FALSE);
1656 /* allow a previously set error code take precedence */
1661 * If there are other handles on the pipeline, Curl_done won't set
1662 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1663 * access free'd data, if the connection is free'd and the handle
1664 * removed before we perform the processing in CURLM_STATE_COMPLETED
1667 data->easy_conn = NULL;
1670 if(data->set.wildcardmatch) {
1671 if(data->wildcard.state != CURLWC_DONE) {
1672 /* if a wildcard is set and we are not ending -> lets start again
1673 with CURLM_STATE_INIT */
1674 multistate(data, CURLM_STATE_INIT);
1679 /* after we have DONE what we're supposed to do, go COMPLETED, and
1680 it doesn't matter what the Curl_done() returned! */
1681 multistate(data, CURLM_STATE_COMPLETED);
1684 case CURLM_STATE_COMPLETED:
1685 /* this is a completed transfer, it is likely to still be connected */
1687 /* This node should be delinked from the list now and we should post
1688 an information message that we are complete. */
1690 /* Important: reset the conn pointer so that we don't point to memory
1691 that could be freed anytime */
1692 data->easy_conn = NULL;
1694 Curl_expire(data, 0); /* stop all timers */
1697 case CURLM_STATE_MSGSENT:
1698 data->result = result;
1699 return CURLM_OK; /* do nothing */
1702 return CURLM_INTERNAL_ERROR;
1706 if(data->mstate < CURLM_STATE_COMPLETED) {
1709 * If an error was returned, and we aren't in completed state now,
1710 * then we go to completed and consider this transfer aborted.
1713 /* NOTE: no attempt to disconnect connections must be made
1714 in the case blocks above - cleanup happens only here */
1716 data->state.pipe_broke = FALSE;
1718 /* Check if we can move pending requests to send pipe */
1719 Curl_multi_process_pending_handles(multi);
1721 if(data->easy_conn) {
1722 /* if this has a connection, unsubscribe from the pipelines */
1723 Curl_pipeline_leave_write(data->easy_conn);
1724 Curl_pipeline_leave_read(data->easy_conn);
1725 Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
1726 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1728 if(disconnect_conn) {
1729 /* Don't attempt to send data over a connection that timed out */
1730 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
1731 /* disconnect properly */
1732 Curl_disconnect(data->easy_conn, dead_connection);
1734 /* This is where we make sure that the easy_conn pointer is reset.
1735 We don't have to do this in every case block above where a
1736 failure is detected */
1737 data->easy_conn = NULL;
1740 else if(data->mstate == CURLM_STATE_CONNECT) {
1741 /* Curl_connect() failed */
1742 (void)Curl_posttransfer(data);
1745 multistate(data, CURLM_STATE_COMPLETED);
1747 /* if there's still a connection to use, call the progress function */
1748 else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
1749 /* aborted due to progress callback return code must close the
1751 result = CURLE_ABORTED_BY_CALLBACK;
1752 connclose(data->easy_conn, "Aborted by callback");
1754 /* if not yet in DONE state, go there, otherwise COMPLETED */
1755 multistate(data, (data->mstate < CURLM_STATE_DONE)?
1756 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1757 rc = CURLM_CALL_MULTI_PERFORM;
1761 if(CURLM_STATE_COMPLETED == data->mstate) {
1762 /* now fill in the Curl_message with this info */
1765 msg->extmsg.msg = CURLMSG_DONE;
1766 msg->extmsg.easy_handle = data;
1767 msg->extmsg.data.result = result;
1769 rc = multi_addmsg(multi, msg);
1771 multistate(data, CURLM_STATE_MSGSENT);
1773 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
1775 data->result = result;
1782 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1784 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1785 struct SessionHandle *data;
1786 CURLMcode returncode=CURLM_OK;
1787 struct Curl_tree *t;
1788 struct timeval now = Curl_tvnow();
1790 if(!GOOD_MULTI_HANDLE(multi))
1791 return CURLM_BAD_HANDLE;
1796 struct WildcardData *wc = &data->wildcard;
1797 SIGPIPE_VARIABLE(pipe_st);
1799 if(data->set.wildcardmatch) {
1801 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1803 return CURLM_OUT_OF_MEMORY;
1807 sigpipe_ignore(data, &pipe_st);
1808 result = multi_runsingle(multi, now, data);
1809 sigpipe_restore(&pipe_st);
1811 if(data->set.wildcardmatch) {
1812 /* destruct wildcard structures if it is needed */
1813 if(wc->state == CURLWC_DONE || result)
1814 Curl_wildcard_dtor(wc);
1818 returncode = result;
1820 data = data->next; /* operate on next handle */
1824 * Simply remove all expired timers from the splay since handles are dealt
1825 * with unconditionally by this function and curl_multi_timeout() requires
1826 * that already passed/handled expire times are removed from the splay.
1828 * It is important that the 'now' value is set at the entry of this function
1829 * and not for the current time as it may have ticked a little while since
1830 * then and then we risk this loop to remove timers that actually have not
1834 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1836 /* the removed may have another timeout in queue */
1837 (void)add_next_timeout(now, multi, t->payload);
1841 *running_handles = multi->num_alive;
1843 if(CURLM_OK >= returncode)
1844 update_timer(multi);
1849 static void close_all_connections(struct Curl_multi *multi)
1851 struct connectdata *conn;
1853 conn = Curl_conncache_find_first_connection(&multi->conn_cache);
1855 SIGPIPE_VARIABLE(pipe_st);
1856 conn->data = multi->closure_handle;
1858 sigpipe_ignore(conn->data, &pipe_st);
1859 /* This will remove the connection from the cache */
1860 (void)Curl_disconnect(conn, FALSE);
1861 sigpipe_restore(&pipe_st);
1863 conn = Curl_conncache_find_first_connection(&multi->conn_cache);
1867 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1869 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1870 struct SessionHandle *data;
1871 struct SessionHandle *nextdata;
1873 if(GOOD_MULTI_HANDLE(multi)) {
1874 bool restore_pipe = FALSE;
1875 SIGPIPE_VARIABLE(pipe_st);
1877 multi->type = 0; /* not good anymore */
1879 /* Close all the connections in the connection cache */
1880 close_all_connections(multi);
1882 if(multi->closure_handle) {
1883 sigpipe_ignore(multi->closure_handle, &pipe_st);
1884 restore_pipe = TRUE;
1886 multi->closure_handle->dns.hostcache = &multi->hostcache;
1887 Curl_hostcache_clean(multi->closure_handle,
1888 multi->closure_handle->dns.hostcache);
1890 Curl_close(multi->closure_handle);
1893 Curl_hash_destroy(&multi->sockhash);
1894 Curl_conncache_destroy(&multi->conn_cache);
1895 Curl_llist_destroy(multi->msglist, NULL);
1896 Curl_llist_destroy(multi->pending, NULL);
1898 /* remove all easy handles */
1899 data = multi->easyp;
1901 nextdata=data->next;
1902 if(data->dns.hostcachetype == HCACHE_MULTI) {
1903 /* clear out the usage of the shared DNS cache */
1904 Curl_hostcache_clean(data, data->dns.hostcache);
1905 data->dns.hostcache = NULL;
1906 data->dns.hostcachetype = HCACHE_NONE;
1909 /* Clear the pointer to the connection cache */
1910 data->state.conn_cache = NULL;
1911 data->multi = NULL; /* clear the association */
1916 Curl_hash_destroy(&multi->hostcache);
1918 /* Free the blacklists by setting them to NULL */
1919 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1920 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1924 sigpipe_restore(&pipe_st);
1929 return CURLM_BAD_HANDLE;
1933 * curl_multi_info_read()
1935 * This function is the primary way for a multi/multi_socket application to
1936 * figure out if a transfer has ended. We MUST make this function as fast as
1937 * possible as it will be polled frequently and we MUST NOT scan any lists in
1938 * here to figure out things. We must scale fine to thousands of handles and
1939 * beyond. The current design is fully O(1).
1942 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1944 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1945 struct Curl_message *msg;
1947 *msgs_in_queue = 0; /* default to none */
1949 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1950 /* there is one or more messages in the list */
1951 struct curl_llist_element *e;
1953 /* extract the head of the list to return */
1954 e = multi->msglist->head;
1958 /* remove the extracted entry */
1959 Curl_llist_remove(multi->msglist, e, NULL);
1961 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1963 return &msg->extmsg;
1970 * singlesocket() checks what sockets we deal with and their "action state"
1971 * and if we have a different state in any of those sockets from last time we
1972 * call the callback accordingly.
1974 static void singlesocket(struct Curl_multi *multi,
1975 struct SessionHandle *data)
1977 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1979 struct Curl_sh_entry *entry;
1982 unsigned int curraction;
1983 bool remove_sock_from_hash;
1985 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1986 socks[i] = CURL_SOCKET_BAD;
1988 /* Fill in the 'current' struct with the state as it is now: what sockets to
1989 supervise and for what actions */
1990 curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
1992 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1993 sockets we should have from now on. Detect the differences, remove no
1994 longer supervised ones and add new ones */
1996 /* walk over the sockets we got right now */
1997 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1998 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2000 int action = CURL_POLL_NONE;
2004 /* get it from the hash */
2005 entry = Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s));
2007 if(curraction & GETSOCK_READSOCK(i))
2008 action |= CURL_POLL_IN;
2009 if(curraction & GETSOCK_WRITESOCK(i))
2010 action |= CURL_POLL_OUT;
2013 /* yeps, already present so check if it has the same action set */
2014 if(entry->action == action)
2015 /* same, continue */
2019 /* this is a socket we didn't have before, add it! */
2020 entry = sh_addentry(&multi->sockhash, s, data);
2026 /* we know (entry != NULL) at this point, see the logic above */
2027 if(multi->socket_cb)
2028 multi->socket_cb(data,
2031 multi->socket_userp,
2034 entry->action = action; /* store the current action state */
2037 num = i; /* number of sockets */
2039 /* when we've walked over all the sockets we should have right now, we must
2040 make sure to detect sockets that are removed */
2041 for(i=0; i< data->numsocks; i++) {
2043 s = data->sockets[i];
2044 for(j=0; j<num; j++) {
2046 /* this is still supervised */
2047 s = CURL_SOCKET_BAD;
2051 if(s != CURL_SOCKET_BAD) {
2053 /* this socket has been removed. Tell the app to remove it */
2054 remove_sock_from_hash = TRUE;
2056 entry = Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s));
2058 /* check if the socket to be removed serves a connection which has
2059 other easy-s in a pipeline. In this case the socket should not be
2061 struct connectdata *easy_conn = data->easy_conn;
2063 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2064 /* the handle should not be removed from the pipe yet */
2065 remove_sock_from_hash = FALSE;
2067 /* Update the sockhash entry to instead point to the next in line
2068 for the recv_pipe, or the first (in case this particular easy
2070 if(entry->easy == data) {
2071 if(Curl_recvpipe_head(data, easy_conn))
2072 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2074 entry->easy = easy_conn->recv_pipe->head->ptr;
2077 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2078 /* the handle should not be removed from the pipe yet */
2079 remove_sock_from_hash = FALSE;
2081 /* Update the sockhash entry to instead point to the next in line
2082 for the send_pipe, or the first (in case this particular easy
2084 if(entry->easy == data) {
2085 if(Curl_sendpipe_head(data, easy_conn))
2086 entry->easy = easy_conn->send_pipe->head->next->ptr;
2088 entry->easy = easy_conn->send_pipe->head->ptr;
2091 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2092 when action will be asked on the socket (see multi_socket()), the
2093 head of the correct pipe will be taken according to the
2098 /* just a precaution, this socket really SHOULD be in the hash already
2099 but in case it isn't, we don't have to tell the app to remove it
2100 either since it never got to know about it */
2101 remove_sock_from_hash = FALSE;
2103 if(remove_sock_from_hash) {
2104 /* in this case 'entry' is always non-NULL */
2105 if(multi->socket_cb)
2106 multi->socket_cb(data,
2109 multi->socket_userp,
2111 sh_delentry(&multi->sockhash, s);
2117 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2118 data->numsocks = num;
2122 * Curl_multi_closed()
2124 * Used by the connect code to tell the multi_socket code that one of the
2125 * sockets we were using is about to be closed. This function will then
2126 * remove it from the sockethash for this handle to make the multi_socket API
2127 * behave properly, especially for the case when libcurl will create another
2128 * socket again and it gets the same file descriptor number.
2131 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2133 struct Curl_multi *multi = conn->data->multi;
2135 /* this is set if this connection is part of a handle that is added to
2136 a multi handle, and only then this is necessary */
2137 struct Curl_sh_entry *entry =
2138 Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s));
2141 if(multi->socket_cb)
2142 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2143 multi->socket_userp,
2146 /* now remove it from the socket hash */
2147 sh_delentry(&multi->sockhash, s);
2155 * add_next_timeout()
2157 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2158 * when it has just been removed from the splay tree because the timeout has
2159 * expired. This function is then to advance in the list to pick the next
2160 * timeout to use (skip the already expired ones) and add this node back to
2161 * the splay tree again.
2163 * The splay tree only has each sessionhandle as a single node and the nearest
2164 * timeout is used to sort it on.
2166 static CURLMcode add_next_timeout(struct timeval now,
2167 struct Curl_multi *multi,
2168 struct SessionHandle *d)
2170 struct timeval *tv = &d->state.expiretime;
2171 struct curl_llist *list = d->state.timeoutlist;
2172 struct curl_llist_element *e;
2174 /* move over the timeout list for this specific handle and remove all
2175 timeouts that are now passed tense and store the next pending
2177 for(e = list->head; e; ) {
2178 struct curl_llist_element *n = e->next;
2179 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2181 /* remove outdated entry */
2182 Curl_llist_remove(list, e, NULL);
2184 /* the list is sorted so get out on the first mismatch */
2190 /* clear the expire times within the handles that we remove from the
2196 /* copy the first entry to 'tv' */
2197 memcpy(tv, e->ptr, sizeof(*tv));
2199 /* remove first entry from list */
2200 Curl_llist_remove(list, e, NULL);
2202 /* insert this node again into the splay */
2203 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2204 &d->state.timenode);
2209 static CURLMcode multi_socket(struct Curl_multi *multi,
2213 int *running_handles)
2215 CURLMcode result = CURLM_OK;
2216 struct SessionHandle *data = NULL;
2217 struct Curl_tree *t;
2218 struct timeval now = Curl_tvnow();
2221 /* *perform() deals with running_handles on its own */
2222 result = curl_multi_perform(multi, running_handles);
2224 /* walk through each easy handle and do the socket state change magic
2226 if(result != CURLM_BAD_HANDLE) {
2229 singlesocket(multi, data);
2234 /* or should we fall-through and do the timer-based stuff? */
2237 else if(s != CURL_SOCKET_TIMEOUT) {
2239 struct Curl_sh_entry *entry =
2240 Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s));
2243 /* Unmatched socket, we can't act on it but we ignore this fact. In
2244 real-world tests it has been proved that libevent can in fact give
2245 the application actions even though the socket was just previously
2246 asked to get removed, so thus we better survive stray socket actions
2247 and just move on. */
2250 SIGPIPE_VARIABLE(pipe_st);
2254 if(data->magic != CURLEASY_MAGIC_NUMBER)
2255 /* bad bad bad bad bad bad bad */
2256 return CURLM_INTERNAL_ERROR;
2258 /* If the pipeline is enabled, take the handle which is in the head of
2259 the pipeline. If we should write into the socket, take the send_pipe
2260 head. If we should read from the socket, take the recv_pipe head. */
2261 if(data->easy_conn) {
2262 if((ev_bitmask & CURL_POLL_OUT) &&
2263 data->easy_conn->send_pipe &&
2264 data->easy_conn->send_pipe->head)
2265 data = data->easy_conn->send_pipe->head->ptr;
2266 else if((ev_bitmask & CURL_POLL_IN) &&
2267 data->easy_conn->recv_pipe &&
2268 data->easy_conn->recv_pipe->head)
2269 data = data->easy_conn->recv_pipe->head->ptr;
2272 if(data->easy_conn &&
2273 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2274 /* set socket event bitmask if they're not locked */
2275 data->easy_conn->cselect_bits = ev_bitmask;
2277 sigpipe_ignore(data, &pipe_st);
2278 result = multi_runsingle(multi, now, data);
2279 sigpipe_restore(&pipe_st);
2281 if(data->easy_conn &&
2282 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2283 /* clear the bitmask only if not locked */
2284 data->easy_conn->cselect_bits = 0;
2286 if(CURLM_OK >= result)
2287 /* get the socket(s) and check if the state has been changed since
2289 singlesocket(multi, data);
2291 /* Now we fall-through and do the timer-based stuff, since we don't want
2292 to force the user to have to deal with timeouts as long as at least
2293 one connection in fact has traffic. */
2295 data = NULL; /* set data to NULL again to avoid calling
2296 multi_runsingle() in case there's no need to */
2297 now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
2298 may have taken some time */
2302 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
2303 update_timer() to trigger a callback to the app again even if the same
2304 timeout is still the one to run after this call. That handles the case
2305 when the application asks libcurl to run the timeout prematurely. */
2306 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
2310 * The loop following here will go on as long as there are expire-times left
2311 * to process in the splay and 'data' will be re-assigned for every expired
2312 * handle we deal with.
2315 /* the first loop lap 'data' can be NULL */
2317 SIGPIPE_VARIABLE(pipe_st);
2319 sigpipe_ignore(data, &pipe_st);
2320 result = multi_runsingle(multi, now, data);
2321 sigpipe_restore(&pipe_st);
2323 if(CURLM_OK >= result)
2324 /* get the socket(s) and check if the state has been changed since
2326 singlesocket(multi, data);
2329 /* Check if there's one (more) expired timer to deal with! This function
2330 extracts a matching node if there is one */
2332 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2334 data = t->payload; /* assign this for next loop */
2335 (void)add_next_timeout(now, multi, t->payload);
2340 *running_handles = multi->num_alive;
2344 #undef curl_multi_setopt
2345 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2346 CURLMoption option, ...)
2348 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2349 CURLMcode res = CURLM_OK;
2352 if(!GOOD_MULTI_HANDLE(multi))
2353 return CURLM_BAD_HANDLE;
2355 va_start(param, option);
2358 case CURLMOPT_SOCKETFUNCTION:
2359 multi->socket_cb = va_arg(param, curl_socket_callback);
2361 case CURLMOPT_SOCKETDATA:
2362 multi->socket_userp = va_arg(param, void *);
2364 case CURLMOPT_PUSHFUNCTION:
2365 multi->push_cb = va_arg(param, curl_push_callback);
2367 case CURLMOPT_PUSHDATA:
2368 multi->push_userp = va_arg(param, void *);
2370 case CURLMOPT_PIPELINING:
2371 multi->pipelining = va_arg(param, long);
2373 case CURLMOPT_TIMERFUNCTION:
2374 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2376 case CURLMOPT_TIMERDATA:
2377 multi->timer_userp = va_arg(param, void *);
2379 case CURLMOPT_MAXCONNECTS:
2380 multi->maxconnects = va_arg(param, long);
2382 case CURLMOPT_MAX_HOST_CONNECTIONS:
2383 multi->max_host_connections = va_arg(param, long);
2385 case CURLMOPT_MAX_PIPELINE_LENGTH:
2386 multi->max_pipeline_length = va_arg(param, long);
2388 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2389 multi->content_length_penalty_size = va_arg(param, long);
2391 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2392 multi->chunk_length_penalty_size = va_arg(param, long);
2394 case CURLMOPT_PIPELINING_SITE_BL:
2395 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2396 &multi->pipelining_site_bl);
2398 case CURLMOPT_PIPELINING_SERVER_BL:
2399 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2400 &multi->pipelining_server_bl);
2402 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2403 multi->max_total_connections = va_arg(param, long);
2406 res = CURLM_UNKNOWN_OPTION;
2413 /* we define curl_multi_socket() in the public multi.h header */
2414 #undef curl_multi_socket
2416 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2417 int *running_handles)
2419 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2420 0, running_handles);
2421 if(CURLM_OK >= result)
2422 update_timer((struct Curl_multi *)multi_handle);
2426 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2427 int ev_bitmask, int *running_handles)
2429 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2430 ev_bitmask, running_handles);
2431 if(CURLM_OK >= result)
2432 update_timer((struct Curl_multi *)multi_handle);
2436 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2439 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2440 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2441 if(CURLM_OK >= result)
2442 update_timer((struct Curl_multi *)multi_handle);
2446 static CURLMcode multi_timeout(struct Curl_multi *multi,
2449 static struct timeval tv_zero = {0, 0};
2451 if(multi->timetree) {
2452 /* we have a tree of expire times */
2453 struct timeval now = Curl_tvnow();
2455 /* splay the lowest to the bottom */
2456 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2458 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2459 /* some time left before expiration */
2460 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2463 * Since we only provide millisecond resolution on the returned value
2464 * and the diff might be less than one millisecond here, we don't
2465 * return zero as that may cause short bursts of busyloops on fast
2466 * processors while the diff is still present but less than one
2467 * millisecond! instead we return 1 until the time is ripe.
2472 /* 0 means immediately */
2481 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2484 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2486 /* First, make some basic checks that the CURLM handle is a good handle */
2487 if(!GOOD_MULTI_HANDLE(multi))
2488 return CURLM_BAD_HANDLE;
2490 return multi_timeout(multi, timeout_ms);
2494 * Tell the application it should update its timers, if it subscribes to the
2495 * update timer callback.
2497 static int update_timer(struct Curl_multi *multi)
2501 if(!multi->timer_cb)
2503 if(multi_timeout(multi, &timeout_ms)) {
2506 if(timeout_ms < 0) {
2507 static const struct timeval none={0, 0};
2508 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2509 multi->timer_lastcall = none;
2510 /* there's no timeout now but there was one previously, tell the app to
2512 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2517 /* When multi_timeout() is done, multi->timetree points to the node with the
2518 * timeout we got the (relative) time-out time for. We can thus easily check
2519 * if this is the same (fixed) time as we got in a previous call and then
2520 * avoid calling the callback again. */
2521 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2524 multi->timer_lastcall = multi->timetree->key;
2526 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2530 * multi_freetimeout()
2532 * Callback used by the llist system when a single timeout list entry is
2535 static void multi_freetimeout(void *user, void *entryptr)
2539 /* the entry was plain malloc()'ed */
2544 * multi_addtimeout()
2546 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2547 * of list is always the timeout nearest in time.
2551 multi_addtimeout(struct curl_llist *timeoutlist,
2552 struct timeval *stamp)
2554 struct curl_llist_element *e;
2555 struct timeval *timedup;
2556 struct curl_llist_element *prev = NULL;
2558 timedup = malloc(sizeof(*timedup));
2560 return CURLM_OUT_OF_MEMORY;
2562 /* copy the timestamp */
2563 memcpy(timedup, stamp, sizeof(*timedup));
2565 if(Curl_llist_count(timeoutlist)) {
2566 /* find the correct spot in the list */
2567 for(e = timeoutlist->head; e; e = e->next) {
2568 struct timeval *checktime = e->ptr;
2569 long diff = curlx_tvdiff(*checktime, *timedup);
2577 this is the first timeout on the list */
2579 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2581 return CURLM_OUT_OF_MEMORY;
2590 * given a number of milliseconds from now to use to set the 'act before
2591 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2593 * Note that the timeout will be added to a queue of timeouts if it defines a
2594 * moment in time that is later than the current head of queue.
2596 * Pass zero to clear all timeout values for this handle.
2598 void Curl_expire(struct SessionHandle *data, long milli)
2600 struct Curl_multi *multi = data->multi;
2601 struct timeval *nowp = &data->state.expiretime;
2604 /* this is only interesting while there is still an associated multi struct
2610 /* No timeout, clear the time data. */
2611 if(nowp->tv_sec || nowp->tv_usec) {
2612 /* Since this is an cleared time, we must remove the previous entry from
2614 struct curl_llist *list = data->state.timeoutlist;
2616 rc = Curl_splayremovebyaddr(multi->timetree,
2617 &data->state.timenode,
2620 infof(data, "Internal error clearing splay node = %d\n", rc);
2622 /* flush the timeout list too */
2623 while(list->size > 0)
2624 Curl_llist_remove(list, list->tail, NULL);
2627 infof(data, "Expire cleared\n");
2637 set.tv_sec += milli/1000;
2638 set.tv_usec += (milli%1000)*1000;
2640 if(set.tv_usec >= 1000000) {
2642 set.tv_usec -= 1000000;
2645 if(nowp->tv_sec || nowp->tv_usec) {
2646 /* This means that the struct is added as a node in the splay tree.
2647 Compare if the new time is earlier, and only remove-old/add-new if it
2649 long diff = curlx_tvdiff(set, *nowp);
2651 /* the new expire time was later so just add it to the queue
2653 multi_addtimeout(data->state.timeoutlist, &set);
2657 /* the new time is newer than the presently set one, so add the current
2658 to the queue and update the head */
2659 multi_addtimeout(data->state.timeoutlist, nowp);
2661 /* Since this is an updated time, we must remove the previous entry from
2662 the splay tree first and then re-add the new value */
2663 rc = Curl_splayremovebyaddr(multi->timetree,
2664 &data->state.timenode,
2667 infof(data, "Internal error removing splay node = %d\n", rc);
2671 data->state.timenode.payload = data;
2672 multi->timetree = Curl_splayinsert(*nowp,
2674 &data->state.timenode);
2677 Curl_splayprint(multi->timetree, 0, TRUE);
2682 * Curl_expire_latest()
2684 * This is like Curl_expire() but will only add a timeout node to the list of
2685 * timers if there is no timeout that will expire before the given time.
2687 * Use this function if the code logic risks calling this function many times
2688 * or if there's no particular conditional wait in the code for this specific
2689 * time-out period to expire.
2692 void Curl_expire_latest(struct SessionHandle *data, long milli)
2694 struct timeval *expire = &data->state.expiretime;
2699 set.tv_sec += milli / 1000;
2700 set.tv_usec += (milli % 1000) * 1000;
2702 if(set.tv_usec >= 1000000) {
2704 set.tv_usec -= 1000000;
2707 if(expire->tv_sec || expire->tv_usec) {
2708 /* This means that the struct is added as a node in the splay tree.
2709 Compare if the new time is earlier, and only remove-old/add-new if it
2711 long diff = curlx_tvdiff(set, *expire);
2713 /* the new expire time was later than the top time, so just skip this */
2717 /* Just add the timeout like normal */
2718 Curl_expire(data, milli);
2721 CURLMcode curl_multi_assign(CURLM *multi_handle,
2722 curl_socket_t s, void *hashp)
2724 struct Curl_sh_entry *there = NULL;
2725 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2727 if(s != CURL_SOCKET_BAD)
2728 there = Curl_hash_pick(&multi->sockhash, (char *)&s,
2729 sizeof(curl_socket_t));
2732 return CURLM_BAD_SOCKET;
2734 there->socketp = hashp;
2739 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2741 return multi ? multi->max_host_connections : 0;
2744 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2746 return multi ? multi->max_total_connections : 0;
2749 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2751 return multi ? multi->content_length_penalty_size : 0;
2754 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2756 return multi ? multi->chunk_length_penalty_size : 0;
2759 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2761 return multi->pipelining_site_bl;
2764 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2766 return multi->pipelining_server_bl;
2769 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2771 struct curl_llist_element *e = multi->pending->head;
2774 struct SessionHandle *data = e->ptr;
2775 struct curl_llist_element *next = e->next;
2777 if(data->mstate == CURLM_STATE_CONNECT_PEND) {
2778 multistate(data, CURLM_STATE_CONNECT);
2780 /* Remove this node from the list */
2781 Curl_llist_remove(multi->pending, e, NULL);
2783 /* Make sure that the handle will be processed soonish. */
2784 Curl_expire_latest(data, 1);
2787 e = next; /* operate on next handle */
2792 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2794 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2795 struct SessionHandle *data;
2797 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2798 multi->num_easy, multi->num_alive);
2799 for(data=multi->easyp; data; data = data->next) {
2800 if(data->mstate < CURLM_STATE_COMPLETED) {
2801 /* only display handles that are not completed */
2802 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2804 statename[data->mstate], data->numsocks);
2805 for(i=0; i < data->numsocks; i++) {
2806 curl_socket_t s = data->sockets[i];
2807 struct Curl_sh_entry *entry =
2808 Curl_hash_pick(&multi->sockhash, (char *)&s, sizeof(s));
2810 fprintf(stderr, "%d ", (int)s);
2812 fprintf(stderr, "INTERNAL CONFUSION\n");
2815 fprintf(stderr, "[%s %s] ",
2816 entry->action&CURL_POLL_IN?"RECVING":"",
2817 entry->action&CURL_POLL_OUT?"SENDING":"");
2820 fprintf(stderr, "\n");