1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, 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>
39 #include "speedcheck.h"
40 #include "conncache.h"
42 #include "multihandle.h"
45 #define _MPRINTF_REPLACE /* use our functions only */
46 #include <curl/mprintf.h>
48 #include "curl_memory.h"
49 /* The last #include file should be: */
53 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
54 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
55 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
57 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
58 #define CURL_SOCKET_HASH_TABLE_SIZE 911
61 #define CURL_CONNECTION_HASH_SIZE 97
63 #define CURL_MULTI_HANDLE 0x000bab1e
65 #define GOOD_MULTI_HANDLE(x) \
66 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
67 #define GOOD_EASY_HANDLE(x) \
68 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
70 static void singlesocket(struct Curl_multi *multi,
71 struct SessionHandle *easy);
72 static int update_timer(struct Curl_multi *multi);
74 static bool isHandleAtHead(struct SessionHandle *handle,
75 struct curl_llist *pipeline);
76 static CURLMcode add_next_timeout(struct timeval now,
77 struct Curl_multi *multi,
78 struct SessionHandle *d);
79 static CURLMcode multi_timeout(struct Curl_multi *multi,
83 static const char * const statename[]={
105 static void multi_freetimeout(void *a, void *b);
107 /* always use this function to change state, to make debugging easier */
108 static void mstate(struct SessionHandle *easy, CURLMstate state
115 long connection_id = -5000;
117 CURLMstate oldstate = easy->mstate;
119 if(oldstate == state)
120 /* don't bother when the new state is the same as the old state */
123 easy->mstate = state;
126 if(easy->mstate >= CURLM_STATE_CONNECT_PEND &&
127 easy->mstate < CURLM_STATE_COMPLETED) {
129 connection_id = easy->easy_conn->connection_id;
132 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
133 statename[oldstate], statename[easy->mstate],
134 (void *)easy, lineno, connection_id);
137 if(state == CURLM_STATE_COMPLETED)
138 /* changing to COMPLETED means there's one less easy handle 'alive' */
139 easy->multi->num_alive--;
143 #define multistate(x,y) mstate(x,y)
145 #define multistate(x,y) mstate(x,y, __LINE__)
149 * We add one of these structs to the sockhash for a particular socket
152 struct Curl_sh_entry {
153 struct SessionHandle *easy;
155 int action; /* what action READ/WRITE this socket waits for */
156 curl_socket_t socket; /* mainly to ease debugging */
157 void *socketp; /* settable by users with curl_multi_assign() */
159 /* bits for 'action' having no bits means this socket is not expecting any
164 /* make sure this socket is present in the hash for this handle */
165 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
167 struct SessionHandle *data)
169 struct Curl_sh_entry *there =
170 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
171 struct Curl_sh_entry *check;
174 /* it is present, return fine */
177 /* not present, add it */
178 check = calloc(1, sizeof(struct Curl_sh_entry));
180 return NULL; /* major failure */
184 /* make/add new hash entry */
185 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
187 return NULL; /* major failure */
190 return check; /* things are good in sockhash land */
194 /* delete the given socket + handle from the hash */
195 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
197 struct Curl_sh_entry *there =
198 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
201 /* this socket is in the hash */
202 /* We remove the hash entry. (This'll end up in a call to
204 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
209 * free a sockhash entry
211 static void sh_freeentry(void *freethis)
213 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
219 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
221 (void) k1_len; (void) k2_len;
223 return (*((int *) k1)) == (*((int *) k2));
226 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
228 int fd = *((int *) key);
231 return (fd % (int)slots_num);
235 * sh_init() creates a new socket hash and returns the handle for it.
237 * Quote from README.multi_socket:
239 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
240 * is somewhat of a bottle neck. Its current implementation may be a bit too
241 * limiting. It simply has a fixed-size array, and on each entry in the array
242 * it has a linked list with entries. So the hash only checks which list to
243 * scan through. The code I had used so for used a list with merely 7 slots
244 * (as that is what the DNS hash uses) but with 7000 connections that would
245 * make an average of 1000 nodes in each list to run through. I upped that to
246 * 97 slots (I believe a prime is suitable) and noticed a significant speed
247 * increase. I need to reconsider the hash implementation or use a rather
248 * large default value like this. At 9000 connections I was still below 10us
252 static struct curl_hash *sh_init(int hashsize)
254 return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
261 * Called when a transfer is completed. Adds the given msg pointer to
262 * the list kept in the multi handle.
264 static CURLMcode multi_addmsg(struct Curl_multi *multi,
265 struct Curl_message *msg)
267 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
268 return CURLM_OUT_OF_MEMORY;
276 * Callback used by the llist system when a single list entry is destroyed.
278 static void multi_freeamsg(void *a, void *b)
284 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
285 int chashsize) /* connection hash */
287 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
292 multi->type = CURL_MULTI_HANDLE;
294 multi->hostcache = Curl_mk_dnscache();
295 if(!multi->hostcache)
298 multi->sockhash = sh_init(hashsize);
302 multi->conn_cache = Curl_conncache_init(chashsize);
303 if(!multi->conn_cache)
306 multi->msglist = Curl_llist_alloc(multi_freeamsg);
310 multi->max_pipeline_length = 5;
311 return (CURLM *) multi;
315 Curl_hash_destroy(multi->sockhash);
316 multi->sockhash = NULL;
317 Curl_hash_destroy(multi->hostcache);
318 multi->hostcache = NULL;
319 Curl_conncache_destroy(multi->conn_cache);
320 multi->conn_cache = NULL;
326 CURLM *curl_multi_init(void)
328 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
329 CURL_CONNECTION_HASH_SIZE);
333 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
336 struct curl_llist *timeoutlist;
337 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
338 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
339 struct SessionHandle *new_closure = NULL;
340 struct curl_hash *hostcache = NULL;
342 /* First, make some basic checks that the CURLM handle is a good handle */
343 if(!GOOD_MULTI_HANDLE(multi))
344 return CURLM_BAD_HANDLE;
346 /* Verify that we got a somewhat good easy handle too */
347 if(!GOOD_EASY_HANDLE(easy_handle))
348 return CURLM_BAD_EASY_HANDLE;
350 /* Prevent users from adding same easy handle more than once and prevent
351 adding to more than one multi stack */
353 /* possibly we should create a new unique error code for this condition */
354 return CURLM_BAD_EASY_HANDLE;
356 /* Allocate and initialize timeout list for easy handle */
357 timeoutlist = Curl_llist_alloc(multi_freetimeout);
359 return CURLM_OUT_OF_MEMORY;
361 /* In case multi handle has no hostcache yet, allocate one */
362 if(!multi->hostcache) {
363 hostcache = Curl_mk_dnscache();
366 Curl_llist_destroy(timeoutlist, NULL);
367 return CURLM_OUT_OF_MEMORY;
371 /* In case multi handle has no closure_handle yet, allocate
372 a new easy handle to use when closing cached connections */
373 if(!multi->closure_handle) {
374 new_closure = (struct SessionHandle *)curl_easy_init();
376 Curl_hash_destroy(hostcache);
378 Curl_llist_destroy(timeoutlist, NULL);
379 return CURLM_OUT_OF_MEMORY;
384 ** No failure allowed in this function beyond this point. And
385 ** no modification of easy nor multi handle allowed before this
386 ** except for potential multi's connection cache growing which
387 ** won't be undone in this function no matter what.
390 /* In case a new closure handle has been initialized above, it
391 is associated now with the multi handle which lacked one. */
393 multi->closure_handle = new_closure;
394 Curl_easy_addmulti(multi->closure_handle, multi_handle);
395 multi->closure_handle->state.conn_cache = multi->conn_cache;
398 /* In case hostcache has been allocated above,
399 it is associated now with the multi handle. */
401 multi->hostcache = hostcache;
403 /* Make easy handle use timeout list initialized above */
404 data->state.timeoutlist = timeoutlist;
407 /* set the easy handle */
408 multistate(data, CURLM_STATE_INIT);
410 if((data->set.global_dns_cache) &&
411 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
412 /* global dns cache was requested but still isn't */
413 struct curl_hash *global = Curl_global_host_cache_init();
415 /* only do this if the global cache init works */
416 data->dns.hostcache = global;
417 data->dns.hostcachetype = HCACHE_GLOBAL;
420 /* for multi interface connections, we share DNS cache automatically if the
421 easy handle's one is currently not set. */
422 else if(!data->dns.hostcache ||
423 (data->dns.hostcachetype == HCACHE_NONE)) {
424 data->dns.hostcache = multi->hostcache;
425 data->dns.hostcachetype = HCACHE_MULTI;
428 /* Point to the multi's connection cache */
429 data->state.conn_cache = multi->conn_cache;
431 /* This adds the new entry at the 'end' of the doubly-linked circular
432 list of SessionHandle structs to try and maintain a FIFO queue so
433 the pipelined requests are in order. */
435 /* We add this new entry last in the list. */
437 data->next = NULL; /* end of the line */
439 struct SessionHandle *last = multi->easylp;
442 multi->easylp = data; /* the new last node */
445 /* first node, make both prev and next be NULL! */
448 multi->easylp = multi->easyp = data; /* both first and last */
451 /* make the SessionHandle refer back to this multi handle */
452 Curl_easy_addmulti(data, multi_handle);
454 /* Set the timeout for this handle to expire really soon so that it will
455 be taken care of even when this handle is added in the midst of operation
456 when only the curl_multi_socket() API is used. During that flow, only
457 sockets that time-out or have actions will be dealt with. Since this
458 handle has no action yet, we make sure it times out to get things to
460 Curl_expire(data, 1);
462 /* increase the node-counter */
465 /* increase the alive-counter */
468 /* A somewhat crude work-around for a little glitch in update_timer() that
469 happens if the lastcall time is set to the same time when the handle is
470 removed as when the next handle is added, as then the check in
471 update_timer() that prevents calling the application multiple times with
472 the same timer infor will not trigger and then the new handle's timeout
473 will not be notified to the app.
475 The work-around is thus simply to clear the 'lastcall' variable to force
476 update_timer() to always trigger a callback to the app when a new easy
478 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
485 /* Debug-function, used like this:
487 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
489 * Enable the hash print function first by editing hash.c
491 static void debug_print_sock_hash(void *p)
493 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
495 fprintf(stderr, " [easy %p/magic %x/socket %d]",
496 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
500 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
503 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
504 struct SessionHandle *easy = curl_handle;
505 struct SessionHandle *data = easy;
507 /* First, make some basic checks that the CURLM handle is a good handle */
508 if(!GOOD_MULTI_HANDLE(multi))
509 return CURLM_BAD_HANDLE;
511 /* Verify that we got a somewhat good easy handle too */
512 if(!GOOD_EASY_HANDLE(curl_handle))
513 return CURLM_BAD_EASY_HANDLE;
516 bool premature = (easy->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
517 bool easy_owns_conn = (easy->easy_conn &&
518 (easy->easy_conn->data == easy)) ?
521 /* If the 'state' is not INIT or COMPLETED, we might need to do something
522 nice to put the easy_handle in a good known state when this returns. */
524 /* this handle is "alive" so we need to count down the total number of
525 alive connections when this is removed */
528 if(easy->easy_conn &&
529 (easy->easy_conn->send_pipe->size +
530 easy->easy_conn->recv_pipe->size > 1) &&
531 easy->mstate > CURLM_STATE_WAITDO &&
532 easy->mstate < CURLM_STATE_COMPLETED) {
533 /* If the handle is in a pipeline and has started sending off its
534 request but not received its response yet, we need to close
536 easy->easy_conn->bits.close = TRUE;
537 /* Set connection owner so that Curl_done() closes it.
538 We can sefely do this here since connection is killed. */
539 easy->easy_conn->data = easy;
542 /* The timer must be shut down before easy->multi is set to NULL,
543 else the timenode will remain in the splay tree after
544 curl_easy_cleanup is called. */
545 Curl_expire(easy, 0);
547 /* destroy the timeout list that is held in the easy handle */
548 if(data->state.timeoutlist) {
549 Curl_llist_destroy(data->state.timeoutlist, NULL);
550 data->state.timeoutlist = NULL;
553 if(easy->dns.hostcachetype == HCACHE_MULTI) {
554 /* stop using the multi handle's DNS cache */
555 easy->dns.hostcache = NULL;
556 easy->dns.hostcachetype = HCACHE_NONE;
559 if(easy->easy_conn) {
561 /* we must call Curl_done() here (if we still "own it") so that we don't
562 leave a half-baked one around */
565 /* Curl_done() clears the conn->data field to lose the association
566 between the easy handle and the connection
568 Note that this ignores the return code simply because there's
569 nothing really useful to do with it anyway! */
570 (void)Curl_done(&easy->easy_conn, easy->result, premature);
573 /* Clear connection pipelines, if Curl_done above was not called */
574 Curl_getoff_all_pipelines(easy, easy->easy_conn);
577 /* as this was using a shared connection cache we clear the pointer
578 to that since we're not part of that multi handle anymore */
579 easy->state.conn_cache = NULL;
581 /* change state without using multistate(), only to make singlesocket() do
583 easy->mstate = CURLM_STATE_COMPLETED;
584 singlesocket(multi, easy); /* to let the application know what sockets
585 that vanish with this handle */
587 /* Remove the association between the connection and the handle */
588 if(easy->easy_conn) {
589 easy->easy_conn->data = NULL;
590 easy->easy_conn = NULL;
593 Curl_easy_addmulti(easy, NULL); /* clear the association
594 to this multi handle */
597 /* make sure there's no pending message in the queue sent from this easy
599 struct curl_llist_element *e;
601 for(e = multi->msglist->head; e; e = e->next) {
602 struct Curl_message *msg = e->ptr;
604 if(msg->extmsg.easy_handle == easy) {
605 Curl_llist_remove(multi->msglist, e, NULL);
606 /* there can only be one from this specific handle */
612 /* make the previous node point to our next */
614 easy->prev->next = easy->next;
616 multi->easyp = easy->next; /* point to first node */
618 /* make our next point to our previous node */
620 easy->next->prev = easy->prev;
622 multi->easylp = easy->prev; /* point to last node */
625 We do not touch the easy handle here! */
627 multi->num_easy--; /* one less to care about now */
633 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
636 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
638 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
641 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
643 data->easy_conn = NULL;
646 static int waitconnect_getsock(struct connectdata *conn,
651 return GETSOCK_BLANK;
653 sock[0] = conn->sock[FIRSTSOCKET];
655 /* when we've sent a CONNECT to a proxy, we should rather wait for the
656 socket to become readable to be able to get the response headers */
657 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
658 return GETSOCK_READSOCK(0);
660 return GETSOCK_WRITESOCK(0);
663 static int domore_getsock(struct connectdata *conn,
664 curl_socket_t *socks,
667 if(conn && conn->handler->domore_getsock)
668 return conn->handler->domore_getsock(conn, socks, numsocks);
669 return GETSOCK_BLANK;
672 /* returns bitmapped flags for this handle and its sockets */
673 static int multi_getsock(struct SessionHandle *easy,
674 curl_socket_t *socks, /* points to numsocks number
678 /* If the pipe broke, or if there's no connection left for this easy handle,
679 then we MUST bail out now with no bitmask set. The no connection case can
680 happen when this is called from curl_multi_remove_handle() =>
681 singlesocket() => multi_getsock().
683 if(easy->state.pipe_broke || !easy->easy_conn)
686 if(easy->mstate > CURLM_STATE_CONNECT &&
687 easy->mstate < CURLM_STATE_COMPLETED) {
688 /* Set up ownership correctly */
689 easy->easy_conn->data = easy;
692 switch(easy->mstate) {
694 #if 0 /* switch back on these cases to get the compiler to check for all enums
696 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
697 case CURLM_STATE_COMPLETED:
698 case CURLM_STATE_MSGSENT:
699 case CURLM_STATE_INIT:
700 case CURLM_STATE_CONNECT:
701 case CURLM_STATE_WAITDO:
702 case CURLM_STATE_DONE:
703 case CURLM_STATE_LAST:
704 /* this will get called with CURLM_STATE_COMPLETED when a handle is
709 case CURLM_STATE_WAITRESOLVE:
710 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
712 case CURLM_STATE_PROTOCONNECT:
713 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
716 case CURLM_STATE_DOING:
717 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
719 case CURLM_STATE_WAITPROXYCONNECT:
720 case CURLM_STATE_WAITCONNECT:
721 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
723 case CURLM_STATE_DO_MORE:
724 return domore_getsock(easy->easy_conn, socks, numsocks);
726 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
727 to waiting for the same as the *PERFORM
729 case CURLM_STATE_PERFORM:
730 case CURLM_STATE_WAITPERFORM:
731 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
736 CURLMcode curl_multi_fdset(CURLM *multi_handle,
737 fd_set *read_fd_set, fd_set *write_fd_set,
738 fd_set *exc_fd_set, int *max_fd)
740 /* Scan through all the easy handles to get the file descriptors set.
741 Some easy handles may not have connected to the remote host yet,
742 and then we must make sure that is done. */
743 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
744 struct SessionHandle *easy;
746 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
749 (void)exc_fd_set; /* not used */
751 if(!GOOD_MULTI_HANDLE(multi))
752 return CURLM_BAD_HANDLE;
756 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
758 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
759 curl_socket_t s = CURL_SOCKET_BAD;
761 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
762 FD_SET(sockbunch[i], read_fd_set);
765 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
766 FD_SET(sockbunch[i], write_fd_set);
769 if(s == CURL_SOCKET_BAD)
770 /* this socket is unused, break out of loop */
773 if((int)s > this_max_fd)
774 this_max_fd = (int)s;
778 easy = easy->next; /* check next handle */
781 *max_fd = this_max_fd;
786 CURLMcode curl_multi_wait(CURLM *multi_handle,
787 struct curl_waitfd extra_fds[],
788 unsigned int extra_nfds,
792 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
793 struct SessionHandle *easy;
794 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
797 unsigned int nfds = 0;
798 unsigned int curlfds;
799 struct pollfd *ufds = NULL;
800 long timeout_internal;
802 if(!GOOD_MULTI_HANDLE(multi))
803 return CURLM_BAD_HANDLE;
805 /* If the internally desired timeout is actually shorter than requested from
806 the outside, then use the shorter time! But only if the internal timer
807 is actually larger than 0! */
808 (void)multi_timeout(multi, &timeout_internal);
809 if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
810 timeout_ms = (int)timeout_internal;
812 /* Count up how many fds we have from the multi handle */
815 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
817 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
818 curl_socket_t s = CURL_SOCKET_BAD;
820 if(bitmap & GETSOCK_READSOCK(i)) {
824 if(bitmap & GETSOCK_WRITESOCK(i)) {
828 if(s == CURL_SOCKET_BAD) {
833 easy = easy->next; /* check next handle */
836 curlfds = nfds; /* number of internal file descriptors */
837 nfds += extra_nfds; /* add the externally provided ones */
840 ufds = malloc(nfds * sizeof(struct pollfd));
842 return CURLM_OUT_OF_MEMORY;
846 /* only do the second loop if we found descriptors in the first stage run
850 /* Add the curl handles to our pollfds first */
853 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
855 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
856 curl_socket_t s = CURL_SOCKET_BAD;
858 if(bitmap & GETSOCK_READSOCK(i)) {
859 ufds[nfds].fd = sockbunch[i];
860 ufds[nfds].events = POLLIN;
864 if(bitmap & GETSOCK_WRITESOCK(i)) {
865 ufds[nfds].fd = sockbunch[i];
866 ufds[nfds].events = POLLOUT;
870 if(s == CURL_SOCKET_BAD) {
875 easy = easy->next; /* check next handle */
879 /* Add external file descriptions from poll-like struct curl_waitfd */
880 for(i = 0; i < extra_nfds; i++) {
881 ufds[nfds].fd = extra_fds[i].fd;
882 ufds[nfds].events = 0;
883 if(extra_fds[i].events & CURL_WAIT_POLLIN)
884 ufds[nfds].events |= POLLIN;
885 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
886 ufds[nfds].events |= POLLPRI;
887 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
888 ufds[nfds].events |= POLLOUT;
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;
925 static CURLMcode multi_runsingle(struct Curl_multi *multi,
927 struct SessionHandle *easy)
929 struct Curl_message *msg = NULL;
932 bool protocol_connect = FALSE;
933 bool dophase_done = FALSE;
935 CURLMcode result = CURLM_OK;
936 struct SingleRequest *k;
937 struct SessionHandle *data;
941 if(!GOOD_EASY_HANDLE(easy))
942 return CURLM_BAD_EASY_HANDLE;
947 /* this is a single-iteration do-while loop just to allow a
948 break to skip to the end of it */
949 bool disconnect_conn = FALSE;
951 /* Handle the case when the pipe breaks, i.e., the connection
952 we're using gets cleaned up and we're left with nothing. */
953 if(data->state.pipe_broke) {
954 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
955 (void *)easy, data->state.path);
957 if(easy->mstate < CURLM_STATE_COMPLETED) {
958 /* Head back to the CONNECT state */
959 multistate(easy, CURLM_STATE_CONNECT);
960 result = CURLM_CALL_MULTI_PERFORM;
961 easy->result = CURLE_OK;
964 data->state.pipe_broke = FALSE;
965 easy->easy_conn = NULL;
969 if(!easy->easy_conn &&
970 easy->mstate > CURLM_STATE_CONNECT &&
971 easy->mstate < CURLM_STATE_DONE) {
972 /* In all these states, the code will blindly access 'easy->easy_conn'
973 so this is precaution that it isn't NULL. And it silences static
975 failf(data, "In state %d with no easy_conn, bail out!\n", easy->mstate);
976 return CURLM_INTERNAL_ERROR;
979 if(easy->easy_conn && easy->mstate > CURLM_STATE_CONNECT &&
980 easy->mstate < CURLM_STATE_COMPLETED)
981 /* Make sure we set the connection's current owner */
982 easy->easy_conn->data = data;
984 if(easy->easy_conn &&
985 (easy->mstate >= CURLM_STATE_CONNECT) &&
986 (easy->mstate < CURLM_STATE_COMPLETED)) {
987 /* we need to wait for the connect state as only then is the start time
988 stored, but we must not check already completed handles */
990 timeout_ms = Curl_timeleft(data, &now,
991 (easy->mstate <= CURLM_STATE_WAITDO)?
995 /* Handle timed out */
996 if(easy->mstate == CURLM_STATE_WAITRESOLVE)
997 failf(data, "Resolving timed out after %ld milliseconds",
998 Curl_tvdiff(now, data->progress.t_startsingle));
999 else if(easy->mstate == CURLM_STATE_WAITCONNECT)
1000 failf(data, "Connection timed out after %ld milliseconds",
1001 Curl_tvdiff(now, data->progress.t_startsingle));
1004 failf(data, "Operation timed out after %ld milliseconds with %"
1005 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1006 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1010 /* Force the connection closed because the server could continue to
1011 send us stuff at any time. (The disconnect_conn logic used below
1012 doesn't work at this point). */
1013 easy->easy_conn->bits.close = TRUE;
1014 easy->result = CURLE_OPERATION_TIMEDOUT;
1015 multistate(easy, CURLM_STATE_COMPLETED);
1020 switch(easy->mstate) {
1021 case CURLM_STATE_INIT:
1022 /* init this transfer. */
1023 easy->result=Curl_pretransfer(data);
1025 if(CURLE_OK == easy->result) {
1026 /* after init, go CONNECT */
1027 multistate(easy, CURLM_STATE_CONNECT);
1028 result = CURLM_CALL_MULTI_PERFORM;
1032 case CURLM_STATE_CONNECT_PEND:
1033 /* We will stay here until there is a connection available. Then
1034 we try again in the CURLM_STATE_CONNECT state. */
1037 case CURLM_STATE_CONNECT:
1038 /* Connect. We want to get a connection identifier filled in. */
1039 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1040 easy->result = Curl_connect(data, &easy->easy_conn,
1041 &async, &protocol_connect);
1042 if(CURLE_NO_CONNECTION_AVAILABLE == easy->result) {
1043 /* There was no connection available. We will go to the pending
1044 state and wait for an available connection. */
1045 multistate(easy, CURLM_STATE_CONNECT_PEND);
1046 easy->result = CURLE_OK;
1050 if(CURLE_OK == easy->result) {
1051 /* Add this handle to the send or pend pipeline */
1052 easy->result = Curl_add_handle_to_pipeline(data, easy->easy_conn);
1053 if(CURLE_OK != easy->result)
1054 disconnect_conn = TRUE;
1057 /* We're now waiting for an asynchronous name lookup */
1058 multistate(easy, CURLM_STATE_WAITRESOLVE);
1060 /* after the connect has been sent off, go WAITCONNECT unless the
1061 protocol connect is already done and we can go directly to
1063 result = CURLM_CALL_MULTI_PERFORM;
1065 if(protocol_connect)
1066 multistate(easy, multi->pipelining_enabled?
1067 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1069 #ifndef CURL_DISABLE_HTTP
1070 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1071 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1074 multistate(easy, CURLM_STATE_WAITCONNECT);
1081 case CURLM_STATE_WAITRESOLVE:
1082 /* awaiting an asynch name resolve to complete */
1084 struct Curl_dns_entry *dns = NULL;
1086 /* check if we have the name resolved by now */
1087 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1089 /* Update sockets here, because the socket(s) may have been
1090 closed and the application thus needs to be told, even if it
1091 is likely that the same socket(s) will again be used further
1092 down. If the name has not yet been resolved, it is likely
1093 that new sockets have been opened in an attempt to contact
1094 another resolver. */
1095 singlesocket(multi, easy);
1098 /* Perform the next step in the connection phase, and then move on
1099 to the WAITCONNECT state */
1100 easy->result = Curl_async_resolved(easy->easy_conn,
1103 if(CURLE_OK != easy->result)
1104 /* if Curl_async_resolved() returns failure, the connection struct
1105 is already freed and gone */
1106 easy->easy_conn = NULL; /* no more connection */
1108 /* call again please so that we get the next socket setup */
1109 result = CURLM_CALL_MULTI_PERFORM;
1110 if(protocol_connect)
1111 multistate(easy, multi->pipelining_enabled?
1112 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1114 #ifndef CURL_DISABLE_HTTP
1115 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1116 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1119 multistate(easy, CURLM_STATE_WAITCONNECT);
1124 if(CURLE_OK != easy->result) {
1125 /* failure detected */
1126 disconnect_conn = TRUE;
1132 #ifndef CURL_DISABLE_HTTP
1133 case CURLM_STATE_WAITPROXYCONNECT:
1134 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1135 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1137 if(easy->easy_conn->bits.proxy_connect_closed) {
1138 /* reset the error buffer */
1139 if(data->set.errorbuffer)
1140 data->set.errorbuffer[0] = '\0';
1141 data->state.errorbuf = FALSE;
1143 easy->result = CURLE_OK;
1144 result = CURLM_CALL_MULTI_PERFORM;
1145 multistate(easy, CURLM_STATE_CONNECT);
1147 else if(CURLE_OK == easy->result) {
1148 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1149 multistate(easy, CURLM_STATE_WAITCONNECT);
1154 case CURLM_STATE_WAITCONNECT:
1155 /* awaiting a completion of an asynch connect */
1156 easy->result = Curl_is_connected(easy->easy_conn,
1162 /* if everything is still fine we do the protocol-specific connect
1164 easy->result = Curl_protocol_connect(easy->easy_conn,
1168 if(CURLE_OK != easy->result) {
1169 /* failure detected */
1170 /* Just break, the cleaning up is handled all in one place */
1171 disconnect_conn = TRUE;
1176 if(!protocol_connect) {
1177 /* We have a TCP connection, but 'protocol_connect' may be false
1178 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1179 connect is TRUE, we move on to STATE_DO.
1180 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1182 #ifndef CURL_DISABLE_HTTP
1183 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1184 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1187 multistate(easy, CURLM_STATE_PROTOCONNECT);
1191 /* after the connect has completed, go WAITDO or DO */
1192 multistate(easy, multi->pipelining_enabled?
1193 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1195 result = CURLM_CALL_MULTI_PERFORM;
1199 case CURLM_STATE_PROTOCONNECT:
1200 /* protocol-specific connect phase */
1201 easy->result = Curl_protocol_connecting(easy->easy_conn,
1203 if((easy->result == CURLE_OK) && protocol_connect) {
1204 /* after the connect has completed, go WAITDO or DO */
1205 multistate(easy, multi->pipelining_enabled?
1206 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1207 result = CURLM_CALL_MULTI_PERFORM;
1209 else if(easy->result) {
1210 /* failure detected */
1211 Curl_posttransfer(data);
1212 Curl_done(&easy->easy_conn, easy->result, TRUE);
1213 disconnect_conn = TRUE;
1217 case CURLM_STATE_WAITDO:
1218 /* Wait for our turn to DO when we're pipelining requests */
1220 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
1221 easy->easy_conn->connection_id,
1222 easy->easy_conn->send_pipe->size,
1223 easy->easy_conn->writechannel_inuse?"TRUE":"FALSE",
1224 isHandleAtHead(data,
1225 easy->easy_conn->send_pipe)?"TRUE":"FALSE");
1227 if(!easy->easy_conn->writechannel_inuse &&
1228 isHandleAtHead(data,
1229 easy->easy_conn->send_pipe)) {
1230 /* Grab the channel */
1231 easy->easy_conn->writechannel_inuse = TRUE;
1232 multistate(easy, CURLM_STATE_DO);
1233 result = CURLM_CALL_MULTI_PERFORM;
1237 case CURLM_STATE_DO:
1238 if(data->set.connect_only) {
1239 /* keep connection open for application to use the socket */
1240 easy->easy_conn->bits.close = FALSE;
1241 multistate(easy, CURLM_STATE_DONE);
1242 easy->result = CURLE_OK;
1243 result = CURLM_CALL_MULTI_PERFORM;
1246 /* Perform the protocol's DO action */
1247 easy->result = Curl_do(&easy->easy_conn, &dophase_done);
1249 /* When Curl_do() returns failure, easy->easy_conn might be NULL! */
1251 if(CURLE_OK == easy->result) {
1253 /* some steps needed for wildcard matching */
1254 if(data->set.wildcardmatch) {
1255 struct WildcardData *wc = &data->wildcard;
1256 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1257 /* skip some states if it is important */
1258 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1259 multistate(easy, CURLM_STATE_DONE);
1260 result = CURLM_CALL_MULTI_PERFORM;
1264 /* DO was not completed in one function call, we must continue
1266 multistate(easy, CURLM_STATE_DOING);
1270 /* after DO, go DO_DONE... or DO_MORE */
1271 else if(easy->easy_conn->bits.do_more) {
1272 /* we're supposed to do more, but we need to sit down, relax
1273 and wait a little while first */
1274 multistate(easy, CURLM_STATE_DO_MORE);
1278 /* we're done with the DO, now DO_DONE */
1279 multistate(easy, CURLM_STATE_DO_DONE);
1280 result = CURLM_CALL_MULTI_PERFORM;
1283 else if((CURLE_SEND_ERROR == easy->result) &&
1284 easy->easy_conn->bits.reuse) {
1286 * In this situation, a connection that we were trying to use
1287 * may have unexpectedly died. If possible, send the connection
1288 * back to the CONNECT phase so we can try again.
1290 char *newurl = NULL;
1291 followtype follow=FOLLOW_NONE;
1295 drc = Curl_retry_request(easy->easy_conn, &newurl);
1297 /* a failure here pretty much implies an out of memory */
1299 disconnect_conn = TRUE;
1302 retry = (newurl)?TRUE:FALSE;
1304 Curl_posttransfer(data);
1305 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1307 /* When set to retry the connection, we must to go back to
1308 * the CONNECT state */
1310 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1311 follow = FOLLOW_RETRY;
1312 drc = Curl_follow(data, newurl, follow);
1313 if(drc == CURLE_OK) {
1314 multistate(easy, CURLM_STATE_CONNECT);
1315 result = CURLM_CALL_MULTI_PERFORM;
1316 easy->result = CURLE_OK;
1325 /* done didn't return OK or SEND_ERROR */
1331 /* Have error handler disconnect conn if we can't retry */
1332 disconnect_conn = TRUE;
1336 /* failure detected */
1337 Curl_posttransfer(data);
1339 Curl_done(&easy->easy_conn, easy->result, FALSE);
1340 disconnect_conn = TRUE;
1345 case CURLM_STATE_DOING:
1346 /* we continue DOING until the DO phase is complete */
1347 easy->result = Curl_protocol_doing(easy->easy_conn,
1349 if(CURLE_OK == easy->result) {
1351 /* after DO, go DO_DONE or DO_MORE */
1352 multistate(easy, easy->easy_conn->bits.do_more?
1353 CURLM_STATE_DO_MORE:
1354 CURLM_STATE_DO_DONE);
1355 result = CURLM_CALL_MULTI_PERFORM;
1356 } /* dophase_done */
1359 /* failure detected */
1360 Curl_posttransfer(data);
1361 Curl_done(&easy->easy_conn, easy->result, FALSE);
1362 disconnect_conn = TRUE;
1366 case CURLM_STATE_DO_MORE:
1368 * When we are connected, DO MORE and then go DO_DONE
1370 easy->result = Curl_do_more(easy->easy_conn, &control);
1372 /* No need to remove this handle from the send pipeline here since that
1373 is done in Curl_done() */
1374 if(CURLE_OK == easy->result) {
1376 /* if positive, advance to DO_DONE
1377 if negative, go back to DOING */
1378 multistate(easy, control==1?
1379 CURLM_STATE_DO_DONE:
1381 result = CURLM_CALL_MULTI_PERFORM;
1384 /* stay in DO_MORE */
1388 /* failure detected */
1389 Curl_posttransfer(data);
1390 Curl_done(&easy->easy_conn, easy->result, FALSE);
1391 disconnect_conn = TRUE;
1395 case CURLM_STATE_DO_DONE:
1396 /* Move ourselves from the send to recv pipeline */
1397 Curl_move_handle_from_send_to_recv_pipe(data, easy->easy_conn);
1398 /* Check if we can move pending requests to send pipe */
1399 Curl_multi_process_pending_handles(multi);
1400 multistate(easy, CURLM_STATE_WAITPERFORM);
1401 result = CURLM_CALL_MULTI_PERFORM;
1404 case CURLM_STATE_WAITPERFORM:
1405 /* Wait for our turn to PERFORM */
1406 if(!easy->easy_conn->readchannel_inuse &&
1407 isHandleAtHead(data,
1408 easy->easy_conn->recv_pipe)) {
1409 /* Grab the channel */
1410 easy->easy_conn->readchannel_inuse = TRUE;
1411 multistate(easy, CURLM_STATE_PERFORM);
1412 result = CURLM_CALL_MULTI_PERFORM;
1416 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
1417 easy->easy_conn->connection_id,
1418 easy->easy_conn->recv_pipe->size,
1419 easy->easy_conn->readchannel_inuse?"TRUE":"FALSE",
1420 isHandleAtHead(data,
1421 easy->easy_conn->recv_pipe)?"TRUE":"FALSE");
1426 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1427 /* if both rates are within spec, resume transfer */
1428 if(Curl_pgrsUpdate(easy->easy_conn))
1429 easy->result = CURLE_ABORTED_BY_CALLBACK;
1431 easy->result = Curl_speedcheck(data, now);
1433 if(( (data->set.max_send_speed == 0) ||
1434 (data->progress.ulspeed < data->set.max_send_speed )) &&
1435 ( (data->set.max_recv_speed == 0) ||
1436 (data->progress.dlspeed < data->set.max_recv_speed)))
1437 multistate(easy, CURLM_STATE_PERFORM);
1440 case CURLM_STATE_PERFORM:
1442 char *newurl = NULL;
1445 /* check if over send speed */
1446 if((data->set.max_send_speed > 0) &&
1447 (data->progress.ulspeed > data->set.max_send_speed)) {
1450 multistate(easy, CURLM_STATE_TOOFAST);
1452 /* calculate upload rate-limitation timeout. */
1453 buffersize = (int)(data->set.buffer_size ?
1454 data->set.buffer_size : BUFSIZE);
1455 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1456 data->progress.ulspeed, buffersize);
1457 Curl_expire(data, timeout_ms);
1461 /* check if over recv speed */
1462 if((data->set.max_recv_speed > 0) &&
1463 (data->progress.dlspeed > data->set.max_recv_speed)) {
1466 multistate(easy, CURLM_STATE_TOOFAST);
1468 /* Calculate download rate-limitation timeout. */
1469 buffersize = (int)(data->set.buffer_size ?
1470 data->set.buffer_size : BUFSIZE);
1471 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1472 data->progress.dlspeed, buffersize);
1473 Curl_expire(data, timeout_ms);
1477 /* read/write data if it is ready to do so */
1478 easy->result = Curl_readwrite(easy->easy_conn, &done);
1482 if(!(k->keepon & KEEP_RECV)) {
1483 /* We're done receiving */
1484 easy->easy_conn->readchannel_inuse = FALSE;
1487 if(!(k->keepon & KEEP_SEND)) {
1488 /* We're done sending */
1489 easy->easy_conn->writechannel_inuse = FALSE;
1492 if(done || (easy->result == CURLE_RECV_ERROR)) {
1493 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1494 * condition and the server closed the re-used connection exactly when
1495 * we wanted to use it, so figure out if that is indeed the case.
1497 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1499 retry = (newurl)?TRUE:FALSE;
1502 /* if we are to retry, set the result to OK and consider the
1504 easy->result = CURLE_OK;
1511 * The transfer phase returned error, we mark the connection to get
1512 * closed to prevent being re-used. This is because we can't possibly
1513 * know if the connection is in a good shape or not now. Unless it is
1514 * a protocol which uses two "channels" like FTP, as then the error
1515 * happened in the data connection.
1518 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1519 easy->easy_conn->bits.close = TRUE;
1521 Curl_posttransfer(data);
1522 Curl_done(&easy->easy_conn, easy->result, FALSE);
1525 followtype follow=FOLLOW_NONE;
1527 /* call this even if the readwrite function returned error */
1528 Curl_posttransfer(data);
1530 /* we're no longer receiving */
1531 Curl_removeHandleFromPipeline(data, easy->easy_conn->recv_pipe);
1533 /* expire the new receiving pipeline head */
1534 if(easy->easy_conn->recv_pipe->head)
1535 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1537 /* Check if we can move pending requests to send pipe */
1538 Curl_multi_process_pending_handles(multi);
1540 /* When we follow redirects or is set to retry the connection, we must
1541 to go back to the CONNECT state */
1542 if(data->req.newurl || retry) {
1544 /* if the URL is a follow-location and not just a retried request
1545 then figure out the URL here */
1546 newurl = data->req.newurl;
1547 data->req.newurl = NULL;
1548 follow = FOLLOW_REDIR;
1551 follow = FOLLOW_RETRY;
1552 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1553 if(CURLE_OK == easy->result) {
1554 easy->result = Curl_follow(data, newurl, follow);
1555 if(CURLE_OK == easy->result) {
1556 multistate(easy, CURLM_STATE_CONNECT);
1557 result = CURLM_CALL_MULTI_PERFORM;
1558 newurl = NULL; /* handed over the memory ownership to
1559 Curl_follow(), make sure we don't free() it
1565 /* after the transfer is done, go DONE */
1567 /* but first check to see if we got a location info even though we're
1568 not following redirects */
1569 if(data->req.location) {
1572 newurl = data->req.location;
1573 data->req.location = NULL;
1574 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1575 if(CURLE_OK == easy->result)
1576 newurl = NULL; /* allocation was handed over Curl_follow() */
1578 disconnect_conn = TRUE;
1581 multistate(easy, CURLM_STATE_DONE);
1582 result = CURLM_CALL_MULTI_PERFORM;
1591 case CURLM_STATE_DONE:
1593 if(easy->easy_conn) {
1594 /* Remove ourselves from the receive pipeline, if we are there. */
1595 Curl_removeHandleFromPipeline(data,
1596 easy->easy_conn->recv_pipe);
1597 /* Check if we can move pending requests to send pipe */
1598 Curl_multi_process_pending_handles(multi);
1600 if(easy->easy_conn->bits.stream_was_rewound) {
1601 /* This request read past its response boundary so we quickly let
1602 the other requests consume those bytes since there is no
1603 guarantee that the socket will become active again */
1604 result = CURLM_CALL_MULTI_PERFORM;
1607 /* post-transfer command */
1608 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1610 * If there are other handles on the pipeline, Curl_done won't set
1611 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1612 * access free'd data, if the connection is free'd and the handle
1613 * removed before we perform the processing in CURLM_STATE_COMPLETED
1616 easy->easy_conn = NULL;
1619 if(data->set.wildcardmatch) {
1620 if(data->wildcard.state != CURLWC_DONE) {
1621 /* if a wildcard is set and we are not ending -> lets start again
1622 with CURLM_STATE_INIT */
1623 result = CURLM_CALL_MULTI_PERFORM;
1624 multistate(easy, CURLM_STATE_INIT);
1629 /* after we have DONE what we're supposed to do, go COMPLETED, and
1630 it doesn't matter what the Curl_done() returned! */
1631 multistate(easy, CURLM_STATE_COMPLETED);
1635 case CURLM_STATE_COMPLETED:
1636 /* this is a completed transfer, it is likely to still be connected */
1638 /* This node should be delinked from the list now and we should post
1639 an information message that we are complete. */
1641 /* Important: reset the conn pointer so that we don't point to memory
1642 that could be freed anytime */
1643 easy->easy_conn = NULL;
1645 Curl_expire(data, 0); /* stop all timers */
1648 case CURLM_STATE_MSGSENT:
1649 return CURLM_OK; /* do nothing */
1652 return CURLM_INTERNAL_ERROR;
1655 if(easy->mstate < CURLM_STATE_COMPLETED) {
1656 if(CURLE_OK != easy->result) {
1658 * If an error was returned, and we aren't in completed state now,
1659 * then we go to completed and consider this transfer aborted.
1662 /* NOTE: no attempt to disconnect connections must be made
1663 in the case blocks above - cleanup happens only here */
1665 data->state.pipe_broke = FALSE;
1667 if(easy->easy_conn) {
1668 /* if this has a connection, unsubscribe from the pipelines */
1669 easy->easy_conn->writechannel_inuse = FALSE;
1670 easy->easy_conn->readchannel_inuse = FALSE;
1671 Curl_removeHandleFromPipeline(data,
1672 easy->easy_conn->send_pipe);
1673 Curl_removeHandleFromPipeline(data,
1674 easy->easy_conn->recv_pipe);
1675 /* Check if we can move pending requests to send pipe */
1676 Curl_multi_process_pending_handles(multi);
1678 if(disconnect_conn) {
1679 /* disconnect properly */
1680 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1682 /* This is where we make sure that the easy_conn pointer is reset.
1683 We don't have to do this in every case block above where a
1684 failure is detected */
1685 easy->easy_conn = NULL;
1688 else if(easy->mstate == CURLM_STATE_CONNECT) {
1689 /* Curl_connect() failed */
1690 (void)Curl_posttransfer(data);
1693 multistate(easy, CURLM_STATE_COMPLETED);
1695 /* if there's still a connection to use, call the progress function */
1696 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1697 /* aborted due to progress callback return code must close the
1699 easy->easy_conn->bits.close = TRUE;
1701 /* if not yet in DONE state, go there, otherwise COMPLETED */
1702 multistate(easy, (easy->mstate < CURLM_STATE_DONE)?
1703 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1704 result = CURLM_CALL_MULTI_PERFORM;
1707 } WHILE_FALSE; /* just to break out from! */
1709 if(CURLM_STATE_COMPLETED == easy->mstate) {
1710 /* now fill in the Curl_message with this info */
1713 msg->extmsg.msg = CURLMSG_DONE;
1714 msg->extmsg.easy_handle = data;
1715 msg->extmsg.data.result = easy->result;
1717 result = multi_addmsg(multi, msg);
1719 multistate(easy, CURLM_STATE_MSGSENT);
1726 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1728 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1729 struct SessionHandle *easy;
1730 CURLMcode returncode=CURLM_OK;
1731 struct Curl_tree *t;
1732 struct timeval now = Curl_tvnow();
1734 if(!GOOD_MULTI_HANDLE(multi))
1735 return CURLM_BAD_HANDLE;
1740 struct WildcardData *wc = &easy->wildcard;
1742 if(easy->set.wildcardmatch) {
1744 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1746 return CURLM_OUT_OF_MEMORY;
1751 result = multi_runsingle(multi, now, easy);
1752 while(CURLM_CALL_MULTI_PERFORM == result);
1754 if(easy->set.wildcardmatch) {
1755 /* destruct wildcard structures if it is needed */
1756 if(wc->state == CURLWC_DONE || result)
1757 Curl_wildcard_dtor(wc);
1761 returncode = result;
1763 easy = easy->next; /* operate on next handle */
1767 * Simply remove all expired timers from the splay since handles are dealt
1768 * with unconditionally by this function and curl_multi_timeout() requires
1769 * that already passed/handled expire times are removed from the splay.
1771 * It is important that the 'now' value is set at the entry of this function
1772 * and not for the current time as it may have ticked a little while since
1773 * then and then we risk this loop to remove timers that actually have not
1777 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1779 /* the removed may have another timeout in queue */
1780 (void)add_next_timeout(now, multi, t->payload);
1784 *running_handles = multi->num_alive;
1786 if(CURLM_OK >= returncode)
1787 update_timer(multi);
1792 static void close_all_connections(struct Curl_multi *multi)
1794 struct connectdata *conn;
1796 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1798 conn->data = multi->closure_handle;
1800 /* This will remove the connection from the cache */
1801 (void)Curl_disconnect(conn, FALSE);
1803 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1807 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1809 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1810 struct SessionHandle *easy;
1811 struct SessionHandle *nexteasy;
1813 if(GOOD_MULTI_HANDLE(multi)) {
1814 multi->type = 0; /* not good anymore */
1816 /* Close all the connections in the connection cache */
1817 close_all_connections(multi);
1819 if(multi->closure_handle) {
1820 multi->closure_handle->dns.hostcache = multi->hostcache;
1821 Curl_hostcache_clean(multi->closure_handle,
1822 multi->closure_handle->dns.hostcache);
1824 Curl_close(multi->closure_handle);
1825 multi->closure_handle = NULL;
1828 Curl_hash_destroy(multi->sockhash);
1829 multi->sockhash = NULL;
1831 Curl_conncache_destroy(multi->conn_cache);
1832 multi->conn_cache = NULL;
1834 /* remove the pending list of messages */
1835 Curl_llist_destroy(multi->msglist, NULL);
1836 multi->msglist = NULL;
1838 /* remove all easy handles */
1839 easy = multi->easyp;
1841 nexteasy=easy->next;
1842 if(easy->dns.hostcachetype == HCACHE_MULTI) {
1843 /* clear out the usage of the shared DNS cache */
1844 Curl_hostcache_clean(easy, easy->dns.hostcache);
1845 easy->dns.hostcache = NULL;
1846 easy->dns.hostcachetype = HCACHE_NONE;
1849 /* Clear the pointer to the connection cache */
1850 easy->state.conn_cache = NULL;
1852 Curl_easy_addmulti(easy, NULL); /* clear the association */
1857 Curl_hash_destroy(multi->hostcache);
1858 multi->hostcache = NULL;
1860 /* Free the blacklists by setting them to NULL */
1861 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1862 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1869 return CURLM_BAD_HANDLE;
1873 * curl_multi_info_read()
1875 * This function is the primary way for a multi/multi_socket application to
1876 * figure out if a transfer has ended. We MUST make this function as fast as
1877 * possible as it will be polled frequently and we MUST NOT scan any lists in
1878 * here to figure out things. We must scale fine to thousands of handles and
1879 * beyond. The current design is fully O(1).
1882 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1884 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1885 struct Curl_message *msg;
1887 *msgs_in_queue = 0; /* default to none */
1889 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1890 /* there is one or more messages in the list */
1891 struct curl_llist_element *e;
1893 /* extract the head of the list to return */
1894 e = multi->msglist->head;
1898 /* remove the extracted entry */
1899 Curl_llist_remove(multi->msglist, e, NULL);
1901 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1903 return &msg->extmsg;
1910 * singlesocket() checks what sockets we deal with and their "action state"
1911 * and if we have a different state in any of those sockets from last time we
1912 * call the callback accordingly.
1914 static void singlesocket(struct Curl_multi *multi,
1915 struct SessionHandle *easy)
1917 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1919 struct Curl_sh_entry *entry;
1922 unsigned int curraction;
1923 bool remove_sock_from_hash;
1925 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1926 socks[i] = CURL_SOCKET_BAD;
1928 /* Fill in the 'current' struct with the state as it is now: what sockets to
1929 supervise and for what actions */
1930 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1932 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1933 sockets we should have from now on. Detect the differences, remove no
1934 longer supervised ones and add new ones */
1936 /* walk over the sockets we got right now */
1937 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1938 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1940 int action = CURL_POLL_NONE;
1944 /* get it from the hash */
1945 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1947 if(curraction & GETSOCK_READSOCK(i))
1948 action |= CURL_POLL_IN;
1949 if(curraction & GETSOCK_WRITESOCK(i))
1950 action |= CURL_POLL_OUT;
1953 /* yeps, already present so check if it has the same action set */
1954 if(entry->action == action)
1955 /* same, continue */
1959 /* this is a socket we didn't have before, add it! */
1960 entry = sh_addentry(multi->sockhash, s, easy);
1966 /* we know (entry != NULL) at this point, see the logic above */
1967 if(multi->socket_cb)
1968 multi->socket_cb(easy,
1971 multi->socket_userp,
1974 entry->action = action; /* store the current action state */
1977 num = i; /* number of sockets */
1979 /* when we've walked over all the sockets we should have right now, we must
1980 make sure to detect sockets that are removed */
1981 for(i=0; i< easy->numsocks; i++) {
1983 s = easy->sockets[i];
1984 for(j=0; j<num; j++) {
1986 /* this is still supervised */
1987 s = CURL_SOCKET_BAD;
1991 if(s != CURL_SOCKET_BAD) {
1993 /* this socket has been removed. Tell the app to remove it */
1994 remove_sock_from_hash = TRUE;
1996 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1998 /* check if the socket to be removed serves a connection which has
1999 other easy-s in a pipeline. In this case the socket should not be
2001 struct connectdata *easy_conn = easy->easy_conn;
2003 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2004 /* the handle should not be removed from the pipe yet */
2005 remove_sock_from_hash = FALSE;
2007 /* Update the sockhash entry to instead point to the next in line
2008 for the recv_pipe, or the first (in case this particular easy
2010 if(entry->easy == easy) {
2011 if(isHandleAtHead(easy, easy_conn->recv_pipe))
2012 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2014 entry->easy = easy_conn->recv_pipe->head->ptr;
2017 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2018 /* the handle should not be removed from the pipe yet */
2019 remove_sock_from_hash = FALSE;
2021 /* Update the sockhash entry to instead point to the next in line
2022 for the send_pipe, or the first (in case this particular easy
2024 if(entry->easy == easy) {
2025 if(isHandleAtHead(easy, easy_conn->send_pipe))
2026 entry->easy = easy_conn->send_pipe->head->next->ptr;
2028 entry->easy = easy_conn->send_pipe->head->ptr;
2031 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2032 when action will be asked on the socket (see multi_socket()), the
2033 head of the correct pipe will be taken according to the
2038 /* just a precaution, this socket really SHOULD be in the hash already
2039 but in case it isn't, we don't have to tell the app to remove it
2040 either since it never got to know about it */
2041 remove_sock_from_hash = FALSE;
2043 if(remove_sock_from_hash) {
2044 /* in this case 'entry' is always non-NULL */
2045 if(multi->socket_cb)
2046 multi->socket_cb(easy,
2049 multi->socket_userp,
2051 sh_delentry(multi->sockhash, s);
2057 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2058 easy->numsocks = num;
2062 * Curl_multi_closed()
2064 * Used by the connect code to tell the multi_socket code that one of the
2065 * sockets we were using have just been closed. This function will then
2066 * remove it from the sockethash for this handle to make the multi_socket API
2067 * behave properly, especially for the case when libcurl will create another
2068 * socket again and it gets the same file descriptor number.
2071 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2073 struct Curl_multi *multi = conn->data->multi;
2075 /* this is set if this connection is part of a handle that is added to
2076 a multi handle, and only then this is necessary */
2077 struct Curl_sh_entry *entry =
2078 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2081 if(multi->socket_cb)
2082 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2083 multi->socket_userp,
2086 /* now remove it from the socket hash */
2087 sh_delentry(multi->sockhash, s);
2095 * add_next_timeout()
2097 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2098 * when it has just been removed from the splay tree because the timeout has
2099 * expired. This function is then to advance in the list to pick the next
2100 * timeout to use (skip the already expired ones) and add this node back to
2101 * the splay tree again.
2103 * The splay tree only has each sessionhandle as a single node and the nearest
2104 * timeout is used to sort it on.
2106 static CURLMcode add_next_timeout(struct timeval now,
2107 struct Curl_multi *multi,
2108 struct SessionHandle *d)
2110 struct timeval *tv = &d->state.expiretime;
2111 struct curl_llist *list = d->state.timeoutlist;
2112 struct curl_llist_element *e;
2114 /* move over the timeout list for this specific handle and remove all
2115 timeouts that are now passed tense and store the next pending
2117 for(e = list->head; e; ) {
2118 struct curl_llist_element *n = e->next;
2119 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2121 /* remove outdated entry */
2122 Curl_llist_remove(list, e, NULL);
2124 /* the list is sorted so get out on the first mismatch */
2130 /* clear the expire times within the handles that we remove from the
2136 /* copy the first entry to 'tv' */
2137 memcpy(tv, e->ptr, sizeof(*tv));
2139 /* remove first entry from list */
2140 Curl_llist_remove(list, e, NULL);
2142 /* insert this node again into the splay */
2143 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2144 &d->state.timenode);
2150 #define TIMEOUT_INACCURACY 40000
2152 #define TIMEOUT_INACCURACY 3000
2155 static CURLMcode multi_socket(struct Curl_multi *multi,
2159 int *running_handles)
2161 CURLMcode result = CURLM_OK;
2162 struct SessionHandle *data = NULL;
2163 struct Curl_tree *t;
2164 struct timeval now = Curl_tvnow();
2167 struct SessionHandle *easy;
2168 /* *perform() deals with running_handles on its own */
2169 result = curl_multi_perform(multi, running_handles);
2171 /* walk through each easy handle and do the socket state change magic
2175 singlesocket(multi, easy);
2179 /* or should we fall-through and do the timer-based stuff? */
2182 else if(s != CURL_SOCKET_TIMEOUT) {
2184 struct Curl_sh_entry *entry =
2185 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2188 /* Unmatched socket, we can't act on it but we ignore this fact. In
2189 real-world tests it has been proved that libevent can in fact give
2190 the application actions even though the socket was just previously
2191 asked to get removed, so thus we better survive stray socket actions
2192 and just move on. */
2197 if(data->magic != CURLEASY_MAGIC_NUMBER)
2198 /* bad bad bad bad bad bad bad */
2199 return CURLM_INTERNAL_ERROR;
2201 /* If the pipeline is enabled, take the handle which is in the head of
2202 the pipeline. If we should write into the socket, take the send_pipe
2203 head. If we should read from the socket, take the recv_pipe head. */
2204 if(data->easy_conn) {
2205 if((ev_bitmask & CURL_POLL_OUT) &&
2206 data->easy_conn->send_pipe &&
2207 data->easy_conn->send_pipe->head)
2208 data = data->easy_conn->send_pipe->head->ptr;
2209 else if((ev_bitmask & CURL_POLL_IN) &&
2210 data->easy_conn->recv_pipe &&
2211 data->easy_conn->recv_pipe->head)
2212 data = data->easy_conn->recv_pipe->head->ptr;
2215 if(data->easy_conn &&
2216 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2217 /* set socket event bitmask if they're not locked */
2218 data->easy_conn->cselect_bits = ev_bitmask;
2221 result = multi_runsingle(multi, now, data);
2222 while(CURLM_CALL_MULTI_PERFORM == result);
2224 if(data->easy_conn &&
2225 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2226 /* clear the bitmask only if not locked */
2227 data->easy_conn->cselect_bits = 0;
2229 if(CURLM_OK >= result)
2230 /* get the socket(s) and check if the state has been changed since
2232 singlesocket(multi, data);
2234 /* Now we fall-through and do the timer-based stuff, since we don't want
2235 to force the user to have to deal with timeouts as long as at least
2236 one connection in fact has traffic. */
2238 data = NULL; /* set data to NULL again to avoid calling
2239 multi_runsingle() in case there's no need to */
2243 /* Compensate for bad precision timers that might've triggered too early.
2245 This precaution was added in commit 2c72732ebf3da5e as a result of bad
2246 resolution in the windows function use(d).
2248 The problematic case here is when using the multi_socket API and libcurl
2249 has told the application about a timeout, and that timeout is what fires
2250 off a bit early. As we don't have any IDs associated with the timeout we
2251 can't tell which timeout that fired off but we only have the times to use
2252 to check what to do. If it fires off too early, we don't run the correct
2253 actions and we don't tell the application again about the same timeout as
2254 was already first in the queue...
2256 Originally we made the timeouts run 40 milliseconds early on all systems,
2257 but now we have an #ifdef setup to provide a decent precaution inaccuracy
2261 now.tv_usec += TIMEOUT_INACCURACY;
2262 if(now.tv_usec >= 1000000) {
2264 now.tv_usec -= 1000000;
2268 * The loop following here will go on as long as there are expire-times left
2269 * to process in the splay and 'data' will be re-assigned for every expired
2270 * handle we deal with.
2273 /* the first loop lap 'data' can be NULL */
2276 result = multi_runsingle(multi, now, data);
2277 while(CURLM_CALL_MULTI_PERFORM == result);
2279 if(CURLM_OK >= result)
2280 /* get the socket(s) and check if the state has been changed since
2282 singlesocket(multi, data);
2285 /* Check if there's one (more) expired timer to deal with! This function
2286 extracts a matching node if there is one */
2288 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2290 data = t->payload; /* assign this for next loop */
2291 (void)add_next_timeout(now, multi, t->payload);
2296 *running_handles = multi->num_alive;
2300 #undef curl_multi_setopt
2301 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2302 CURLMoption option, ...)
2304 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2305 CURLMcode res = CURLM_OK;
2308 if(!GOOD_MULTI_HANDLE(multi))
2309 return CURLM_BAD_HANDLE;
2311 va_start(param, option);
2314 case CURLMOPT_SOCKETFUNCTION:
2315 multi->socket_cb = va_arg(param, curl_socket_callback);
2317 case CURLMOPT_SOCKETDATA:
2318 multi->socket_userp = va_arg(param, void *);
2320 case CURLMOPT_PIPELINING:
2321 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2323 case CURLMOPT_TIMERFUNCTION:
2324 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2326 case CURLMOPT_TIMERDATA:
2327 multi->timer_userp = va_arg(param, void *);
2329 case CURLMOPT_MAXCONNECTS:
2330 multi->maxconnects = va_arg(param, long);
2332 case CURLMOPT_MAX_HOST_CONNECTIONS:
2333 multi->max_host_connections = va_arg(param, long);
2335 case CURLMOPT_MAX_PIPELINE_LENGTH:
2336 multi->max_pipeline_length = va_arg(param, long);
2338 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2339 multi->content_length_penalty_size = va_arg(param, long);
2341 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2342 multi->chunk_length_penalty_size = va_arg(param, long);
2344 case CURLMOPT_PIPELINING_SITE_BL:
2345 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2346 &multi->pipelining_site_bl);
2348 case CURLMOPT_PIPELINING_SERVER_BL:
2349 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2350 &multi->pipelining_server_bl);
2352 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2353 multi->max_total_connections = va_arg(param, long);
2356 res = CURLM_UNKNOWN_OPTION;
2363 /* we define curl_multi_socket() in the public multi.h header */
2364 #undef curl_multi_socket
2366 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2367 int *running_handles)
2369 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2370 0, running_handles);
2371 if(CURLM_OK >= result)
2372 update_timer((struct Curl_multi *)multi_handle);
2376 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2377 int ev_bitmask, int *running_handles)
2379 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2380 ev_bitmask, running_handles);
2381 if(CURLM_OK >= result)
2382 update_timer((struct Curl_multi *)multi_handle);
2386 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2389 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2390 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2391 if(CURLM_OK >= result)
2392 update_timer((struct Curl_multi *)multi_handle);
2396 static CURLMcode multi_timeout(struct Curl_multi *multi,
2399 static struct timeval tv_zero = {0,0};
2401 if(multi->timetree) {
2402 /* we have a tree of expire times */
2403 struct timeval now = Curl_tvnow();
2405 /* splay the lowest to the bottom */
2406 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2408 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2409 /* some time left before expiration */
2410 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2413 * Since we only provide millisecond resolution on the returned value
2414 * and the diff might be less than one millisecond here, we don't
2415 * return zero as that may cause short bursts of busyloops on fast
2416 * processors while the diff is still present but less than one
2417 * millisecond! instead we return 1 until the time is ripe.
2422 /* 0 means immediately */
2431 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2434 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2436 /* First, make some basic checks that the CURLM handle is a good handle */
2437 if(!GOOD_MULTI_HANDLE(multi))
2438 return CURLM_BAD_HANDLE;
2440 return multi_timeout(multi, timeout_ms);
2444 * Tell the application it should update its timers, if it subscribes to the
2445 * update timer callback.
2447 static int update_timer(struct Curl_multi *multi)
2451 if(!multi->timer_cb)
2453 if(multi_timeout(multi, &timeout_ms)) {
2456 if(timeout_ms < 0) {
2457 static const struct timeval none={0,0};
2458 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2459 multi->timer_lastcall = none;
2460 /* there's no timeout now but there was one previously, tell the app to
2462 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2467 /* When multi_timeout() is done, multi->timetree points to the node with the
2468 * timeout we got the (relative) time-out time for. We can thus easily check
2469 * if this is the same (fixed) time as we got in a previous call and then
2470 * avoid calling the callback again. */
2471 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2474 multi->timer_lastcall = multi->timetree->key;
2476 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2479 void Curl_multi_set_easy_connection(struct SessionHandle *handle,
2480 struct connectdata *conn)
2482 handle->easy_conn = conn;
2485 static bool isHandleAtHead(struct SessionHandle *handle,
2486 struct curl_llist *pipeline)
2488 struct curl_llist_element *curr = pipeline->head;
2490 return (curr->ptr == handle) ? TRUE : FALSE;
2496 * multi_freetimeout()
2498 * Callback used by the llist system when a single timeout list entry is
2501 static void multi_freetimeout(void *user, void *entryptr)
2505 /* the entry was plain malloc()'ed */
2510 * multi_addtimeout()
2512 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2513 * of list is always the timeout nearest in time.
2517 multi_addtimeout(struct curl_llist *timeoutlist,
2518 struct timeval *stamp)
2520 struct curl_llist_element *e;
2521 struct timeval *timedup;
2522 struct curl_llist_element *prev = NULL;
2524 timedup = malloc(sizeof(*timedup));
2526 return CURLM_OUT_OF_MEMORY;
2528 /* copy the timestamp */
2529 memcpy(timedup, stamp, sizeof(*timedup));
2531 if(Curl_llist_count(timeoutlist)) {
2532 /* find the correct spot in the list */
2533 for(e = timeoutlist->head; e; e = e->next) {
2534 struct timeval *checktime = e->ptr;
2535 long diff = curlx_tvdiff(*checktime, *timedup);
2543 this is the first timeout on the list */
2545 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2547 return CURLM_OUT_OF_MEMORY;
2556 * given a number of milliseconds from now to use to set the 'act before
2557 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2559 * Note that the timeout will be added to a queue of timeouts if it defines a
2560 * moment in time that is later than the current head of queue.
2562 * Pass zero to clear all timeout values for this handle.
2564 void Curl_expire(struct SessionHandle *data, long milli)
2566 struct Curl_multi *multi = data->multi;
2567 struct timeval *nowp = &data->state.expiretime;
2570 /* this is only interesting while there is still an associated multi struct
2576 /* No timeout, clear the time data. */
2577 if(nowp->tv_sec || nowp->tv_usec) {
2578 /* Since this is an cleared time, we must remove the previous entry from
2580 struct curl_llist *list = data->state.timeoutlist;
2582 rc = Curl_splayremovebyaddr(multi->timetree,
2583 &data->state.timenode,
2586 infof(data, "Internal error clearing splay node = %d\n", rc);
2588 /* flush the timeout list too */
2589 while(list->size > 0)
2590 Curl_llist_remove(list, list->tail, NULL);
2593 infof(data, "Expire cleared\n");
2603 set.tv_sec += milli/1000;
2604 set.tv_usec += (milli%1000)*1000;
2606 if(set.tv_usec >= 1000000) {
2608 set.tv_usec -= 1000000;
2611 if(nowp->tv_sec || nowp->tv_usec) {
2612 /* This means that the struct is added as a node in the splay tree.
2613 Compare if the new time is earlier, and only remove-old/add-new if it
2615 long diff = curlx_tvdiff(set, *nowp);
2617 /* the new expire time was later so just add it to the queue
2619 multi_addtimeout(data->state.timeoutlist, &set);
2623 /* the new time is newer than the presently set one, so add the current
2624 to the queue and update the head */
2625 multi_addtimeout(data->state.timeoutlist, nowp);
2627 /* Since this is an updated time, we must remove the previous entry from
2628 the splay tree first and then re-add the new value */
2629 rc = Curl_splayremovebyaddr(multi->timetree,
2630 &data->state.timenode,
2633 infof(data, "Internal error removing splay node = %d\n", rc);
2637 data->state.timenode.payload = data;
2638 multi->timetree = Curl_splayinsert(*nowp,
2640 &data->state.timenode);
2643 Curl_splayprint(multi->timetree, 0, TRUE);
2647 CURLMcode curl_multi_assign(CURLM *multi_handle,
2648 curl_socket_t s, void *hashp)
2650 struct Curl_sh_entry *there = NULL;
2651 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2653 if(s != CURL_SOCKET_BAD)
2654 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2657 return CURLM_BAD_SOCKET;
2659 there->socketp = hashp;
2664 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2666 return multi ? multi->max_host_connections : 0;
2669 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2671 return multi ? multi->max_total_connections : 0;
2674 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2676 return multi ? multi->max_pipeline_length : 0;
2679 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2681 return multi ? multi->content_length_penalty_size : 0;
2684 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2686 return multi ? multi->chunk_length_penalty_size : 0;
2689 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2691 return multi->pipelining_site_bl;
2694 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2696 return multi->pipelining_server_bl;
2699 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2701 struct SessionHandle *easy;
2705 if(easy->mstate == CURLM_STATE_CONNECT_PEND) {
2706 multistate(easy, CURLM_STATE_CONNECT);
2707 /* Make sure that the handle will be processed soonish. */
2708 Curl_expire(easy, 1);
2710 easy = easy->next; /* operate on next handle */
2715 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2717 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2718 struct SessionHandle *easy;
2720 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2721 multi->num_easy, multi->num_alive);
2722 for(easy=multi->easyp; easy; easy = easy->next) {
2723 if(easy->mstate < CURLM_STATE_COMPLETED) {
2724 /* only display handles that are not completed */
2725 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2727 statename[easy->mstate], easy->numsocks);
2728 for(i=0; i < easy->numsocks; i++) {
2729 curl_socket_t s = easy->sockets[i];
2730 struct Curl_sh_entry *entry =
2731 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2733 fprintf(stderr, "%d ", (int)s);
2735 fprintf(stderr, "INTERNAL CONFUSION\n");
2738 fprintf(stderr, "[%s %s] ",
2739 entry->action&CURL_POLL_IN?"RECVING":"",
2740 entry->action&CURL_POLL_OUT?"SENDING":"");
2743 fprintf(stderr, "\n");