1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, 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"
46 #define _MPRINTF_REPLACE /* use our functions only */
47 #include <curl/mprintf.h>
49 #include "curl_memory.h"
50 /* The last #include file should be: */
54 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
55 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
56 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
58 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
59 #define CURL_SOCKET_HASH_TABLE_SIZE 911
62 #define CURL_CONNECTION_HASH_SIZE 97
64 #define CURL_MULTI_HANDLE 0x000bab1e
66 #define GOOD_MULTI_HANDLE(x) \
67 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
68 #define GOOD_EASY_HANDLE(x) \
69 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
71 static void singlesocket(struct Curl_multi *multi,
72 struct SessionHandle *data);
73 static int update_timer(struct Curl_multi *multi);
75 static bool isHandleAtHead(struct SessionHandle *handle,
76 struct curl_llist *pipeline);
77 static CURLMcode add_next_timeout(struct timeval now,
78 struct Curl_multi *multi,
79 struct SessionHandle *d);
80 static CURLMcode multi_timeout(struct Curl_multi *multi,
84 static const char * const statename[]={
106 static void multi_freetimeout(void *a, void *b);
108 /* always use this function to change state, to make debugging easier */
109 static void mstate(struct SessionHandle *data, CURLMstate state
116 long connection_id = -5000;
118 CURLMstate oldstate = data->mstate;
120 if(oldstate == state)
121 /* don't bother when the new state is the same as the old state */
124 data->mstate = state;
127 if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
128 data->mstate < CURLM_STATE_COMPLETED) {
130 connection_id = data->easy_conn->connection_id;
133 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
134 statename[oldstate], statename[data->mstate],
135 (void *)data, lineno, connection_id);
138 if(state == CURLM_STATE_COMPLETED)
139 /* changing to COMPLETED means there's one less easy handle 'alive' */
140 data->multi->num_alive--;
144 #define multistate(x,y) mstate(x,y)
146 #define multistate(x,y) mstate(x,y, __LINE__)
150 * We add one of these structs to the sockhash for a particular socket
153 struct Curl_sh_entry {
154 struct SessionHandle *easy;
156 int action; /* what action READ/WRITE this socket waits for */
157 curl_socket_t socket; /* mainly to ease debugging */
158 void *socketp; /* settable by users with curl_multi_assign() */
160 /* bits for 'action' having no bits means this socket is not expecting any
165 /* make sure this socket is present in the hash for this handle */
166 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
168 struct SessionHandle *data)
170 struct Curl_sh_entry *there =
171 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
172 struct Curl_sh_entry *check;
175 /* it is present, return fine */
178 /* not present, add it */
179 check = calloc(1, sizeof(struct Curl_sh_entry));
181 return NULL; /* major failure */
185 /* make/add new hash entry */
186 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
188 return NULL; /* major failure */
191 return check; /* things are good in sockhash land */
195 /* delete the given socket + handle from the hash */
196 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
198 struct Curl_sh_entry *there =
199 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
202 /* this socket is in the hash */
203 /* We remove the hash entry. (This'll end up in a call to
205 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
210 * free a sockhash entry
212 static void sh_freeentry(void *freethis)
214 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
220 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
222 (void) k1_len; (void) k2_len;
224 return (*((int *) k1)) == (*((int *) k2));
227 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
229 int fd = *((int *) key);
232 return (fd % (int)slots_num);
236 * sh_init() creates a new socket hash and returns the handle for it.
238 * Quote from README.multi_socket:
240 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
241 * is somewhat of a bottle neck. Its current implementation may be a bit too
242 * limiting. It simply has a fixed-size array, and on each entry in the array
243 * it has a linked list with entries. So the hash only checks which list to
244 * scan through. The code I had used so for used a list with merely 7 slots
245 * (as that is what the DNS hash uses) but with 7000 connections that would
246 * make an average of 1000 nodes in each list to run through. I upped that to
247 * 97 slots (I believe a prime is suitable) and noticed a significant speed
248 * increase. I need to reconsider the hash implementation or use a rather
249 * large default value like this. At 9000 connections I was still below 10us
253 static struct curl_hash *sh_init(int hashsize)
255 return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
262 * Called when a transfer is completed. Adds the given msg pointer to
263 * the list kept in the multi handle.
265 static CURLMcode multi_addmsg(struct Curl_multi *multi,
266 struct Curl_message *msg)
268 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
269 return CURLM_OUT_OF_MEMORY;
277 * Callback used by the llist system when a single list entry is destroyed.
279 static void multi_freeamsg(void *a, void *b)
285 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
286 int chashsize) /* connection hash */
288 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
293 multi->type = CURL_MULTI_HANDLE;
295 multi->hostcache = Curl_mk_dnscache();
296 if(!multi->hostcache)
299 multi->sockhash = sh_init(hashsize);
303 multi->conn_cache = Curl_conncache_init(chashsize);
304 if(!multi->conn_cache)
307 multi->msglist = Curl_llist_alloc(multi_freeamsg);
311 /* allocate a new easy handle to use when closing cached connections */
312 multi->closure_handle = curl_easy_init();
313 if(!multi->closure_handle)
316 multi->closure_handle->multi = multi;
317 multi->closure_handle->state.conn_cache = multi->conn_cache;
319 multi->max_pipeline_length = 5;
321 /* -1 means it not set by user, use the default value */
322 multi->maxconnects = -1;
323 return (CURLM *) multi;
327 Curl_hash_destroy(multi->sockhash);
328 multi->sockhash = NULL;
329 Curl_hash_destroy(multi->hostcache);
330 multi->hostcache = NULL;
331 Curl_conncache_destroy(multi->conn_cache);
332 multi->conn_cache = NULL;
333 Curl_close(multi->closure_handle);
334 multi->closure_handle = NULL;
335 Curl_llist_destroy(multi->msglist, NULL);
341 CURLM *curl_multi_init(void)
343 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
344 CURL_CONNECTION_HASH_SIZE);
347 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
350 struct curl_llist *timeoutlist;
351 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
352 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
354 /* First, make some basic checks that the CURLM handle is a good handle */
355 if(!GOOD_MULTI_HANDLE(multi))
356 return CURLM_BAD_HANDLE;
358 /* Verify that we got a somewhat good easy handle too */
359 if(!GOOD_EASY_HANDLE(easy_handle))
360 return CURLM_BAD_EASY_HANDLE;
362 /* Prevent users from adding same easy handle more than once and prevent
363 adding to more than one multi stack */
365 return CURLM_ADDED_ALREADY;
367 /* Allocate and initialize timeout list for easy handle */
368 timeoutlist = Curl_llist_alloc(multi_freetimeout);
370 return CURLM_OUT_OF_MEMORY;
373 * No failure allowed in this function beyond this point. And no
374 * modification of easy nor multi handle allowed before this except for
375 * potential multi's connection cache growing which won't be undone in this
376 * function no matter what.
379 /* Make easy handle use timeout list initialized above */
380 data->state.timeoutlist = timeoutlist;
383 /* set the easy handle */
384 multistate(data, CURLM_STATE_INIT);
386 if((data->set.global_dns_cache) &&
387 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
388 /* global dns cache was requested but still isn't */
389 struct curl_hash *global = Curl_global_host_cache_init();
391 /* only do this if the global cache init works */
392 data->dns.hostcache = global;
393 data->dns.hostcachetype = HCACHE_GLOBAL;
396 /* for multi interface connections, we share DNS cache automatically if the
397 easy handle's one is currently not set. */
398 else if(!data->dns.hostcache ||
399 (data->dns.hostcachetype == HCACHE_NONE)) {
400 data->dns.hostcache = multi->hostcache;
401 data->dns.hostcachetype = HCACHE_MULTI;
404 /* Point to the multi's connection cache */
405 data->state.conn_cache = multi->conn_cache;
407 data->state.infilesize = data->set.filesize;
409 /* This adds the new entry at the 'end' of the doubly-linked circular
410 list of SessionHandle structs to try and maintain a FIFO queue so
411 the pipelined requests are in order. */
413 /* We add this new entry last in the list. */
415 data->next = NULL; /* end of the line */
417 struct SessionHandle *last = multi->easylp;
420 multi->easylp = data; /* the new last node */
423 /* first node, make both prev and next be NULL! */
426 multi->easylp = multi->easyp = data; /* both first and last */
429 /* make the SessionHandle refer back to this multi handle */
430 data->multi = multi_handle;
432 /* Set the timeout for this handle to expire really soon so that it will
433 be taken care of even when this handle is added in the midst of operation
434 when only the curl_multi_socket() API is used. During that flow, only
435 sockets that time-out or have actions will be dealt with. Since this
436 handle has no action yet, we make sure it times out to get things to
438 Curl_expire(data, 1);
440 /* increase the node-counter */
443 /* increase the alive-counter */
446 /* A somewhat crude work-around for a little glitch in update_timer() that
447 happens if the lastcall time is set to the same time when the handle is
448 removed as when the next handle is added, as then the check in
449 update_timer() that prevents calling the application multiple times with
450 the same timer infor will not trigger and then the new handle's timeout
451 will not be notified to the app.
453 The work-around is thus simply to clear the 'lastcall' variable to force
454 update_timer() to always trigger a callback to the app when a new easy
456 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
463 /* Debug-function, used like this:
465 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
467 * Enable the hash print function first by editing hash.c
469 static void debug_print_sock_hash(void *p)
471 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
473 fprintf(stderr, " [easy %p/magic %x/socket %d]",
474 (void *)sh->data, sh->data->magic, (int)sh->socket);
478 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
481 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
482 struct SessionHandle *easy = curl_handle;
483 struct SessionHandle *data = easy;
485 /* First, make some basic checks that the CURLM handle is a good handle */
486 if(!GOOD_MULTI_HANDLE(multi))
487 return CURLM_BAD_HANDLE;
489 /* Verify that we got a somewhat good easy handle too */
490 if(!GOOD_EASY_HANDLE(curl_handle))
491 return CURLM_BAD_EASY_HANDLE;
493 /* Prevent users from trying to remove same easy handle more than once */
495 return CURLM_OK; /* it is already removed so let's say it is fine! */
498 bool premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
499 bool easy_owns_conn = (data->easy_conn &&
500 (data->easy_conn->data == easy)) ?
503 /* If the 'state' is not INIT or COMPLETED, we might need to do something
504 nice to put the easy_handle in a good known state when this returns. */
506 /* this handle is "alive" so we need to count down the total number of
507 alive connections when this is removed */
510 if(data->easy_conn &&
511 (data->easy_conn->send_pipe->size +
512 data->easy_conn->recv_pipe->size > 1) &&
513 data->mstate > CURLM_STATE_WAITDO &&
514 data->mstate < CURLM_STATE_COMPLETED) {
515 /* If the handle is in a pipeline and has started sending off its
516 request but not received its response yet, we need to close
518 connclose(data->easy_conn, "Removed with partial response");
519 /* Set connection owner so that Curl_done() closes it.
520 We can sefely do this here since connection is killed. */
521 data->easy_conn->data = easy;
524 /* The timer must be shut down before data->multi is set to NULL,
525 else the timenode will remain in the splay tree after
526 curl_easy_cleanup is called. */
527 Curl_expire(data, 0);
529 /* destroy the timeout list that is held in the easy handle */
530 if(data->state.timeoutlist) {
531 Curl_llist_destroy(data->state.timeoutlist, NULL);
532 data->state.timeoutlist = NULL;
535 if(data->dns.hostcachetype == HCACHE_MULTI) {
536 /* stop using the multi handle's DNS cache */
537 data->dns.hostcache = NULL;
538 data->dns.hostcachetype = HCACHE_NONE;
541 if(data->easy_conn) {
543 /* we must call Curl_done() here (if we still "own it") so that we don't
544 leave a half-baked one around */
547 /* Curl_done() clears the conn->data field to lose the association
548 between the easy handle and the connection
550 Note that this ignores the return code simply because there's
551 nothing really useful to do with it anyway! */
552 (void)Curl_done(&data->easy_conn, data->result, premature);
555 /* Clear connection pipelines, if Curl_done above was not called */
556 Curl_getoff_all_pipelines(data, data->easy_conn);
559 Curl_wildcard_dtor(&data->wildcard);
561 /* as this was using a shared connection cache we clear the pointer
562 to that since we're not part of that multi handle anymore */
563 data->state.conn_cache = NULL;
565 /* change state without using multistate(), only to make singlesocket() do
567 data->mstate = CURLM_STATE_COMPLETED;
568 singlesocket(multi, easy); /* to let the application know what sockets
569 that vanish with this handle */
571 /* Remove the association between the connection and the handle */
572 if(data->easy_conn) {
573 data->easy_conn->data = NULL;
574 data->easy_conn = NULL;
577 data->multi = NULL; /* clear the association to this multi handle */
580 /* make sure there's no pending message in the queue sent from this easy
582 struct curl_llist_element *e;
584 for(e = multi->msglist->head; e; e = e->next) {
585 struct Curl_message *msg = e->ptr;
587 if(msg->extmsg.easy_handle == easy) {
588 Curl_llist_remove(multi->msglist, e, NULL);
589 /* there can only be one from this specific handle */
595 /* make the previous node point to our next */
597 data->prev->next = data->next;
599 multi->easyp = data->next; /* point to first node */
601 /* make our next point to our previous node */
603 data->next->prev = data->prev;
605 multi->easylp = data->prev; /* point to last node */
608 We do not touch the easy handle here! */
610 multi->num_easy--; /* one less to care about now */
616 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
619 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
621 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
624 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
626 data->easy_conn = NULL;
629 static int waitconnect_getsock(struct connectdata *conn,
638 return GETSOCK_BLANK;
641 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
642 sock[s] = conn->tempsock[i];
643 rc |= GETSOCK_WRITESOCK(s++);
647 /* when we've sent a CONNECT to a proxy, we should rather wait for the
648 socket to become readable to be able to get the response headers */
649 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
650 sock[0] = conn->sock[FIRSTSOCKET];
651 rc = GETSOCK_READSOCK(0);
657 static int domore_getsock(struct connectdata *conn,
658 curl_socket_t *socks,
661 if(conn && conn->handler->domore_getsock)
662 return conn->handler->domore_getsock(conn, socks, numsocks);
663 return GETSOCK_BLANK;
666 /* returns bitmapped flags for this handle and its sockets */
667 static int multi_getsock(struct SessionHandle *data,
668 curl_socket_t *socks, /* points to numsocks number
672 /* If the pipe broke, or if there's no connection left for this easy handle,
673 then we MUST bail out now with no bitmask set. The no connection case can
674 happen when this is called from curl_multi_remove_handle() =>
675 singlesocket() => multi_getsock().
677 if(data->state.pipe_broke || !data->easy_conn)
680 if(data->mstate > CURLM_STATE_CONNECT &&
681 data->mstate < CURLM_STATE_COMPLETED) {
682 /* Set up ownership correctly */
683 data->easy_conn->data = data;
686 switch(data->mstate) {
688 #if 0 /* switch back on these cases to get the compiler to check for all enums
690 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
691 case CURLM_STATE_COMPLETED:
692 case CURLM_STATE_MSGSENT:
693 case CURLM_STATE_INIT:
694 case CURLM_STATE_CONNECT:
695 case CURLM_STATE_WAITDO:
696 case CURLM_STATE_DONE:
697 case CURLM_STATE_LAST:
698 /* this will get called with CURLM_STATE_COMPLETED when a handle is
703 case CURLM_STATE_WAITRESOLVE:
704 return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
706 case CURLM_STATE_PROTOCONNECT:
707 return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
710 case CURLM_STATE_DOING:
711 return Curl_doing_getsock(data->easy_conn, socks, numsocks);
713 case CURLM_STATE_WAITPROXYCONNECT:
714 case CURLM_STATE_WAITCONNECT:
715 return waitconnect_getsock(data->easy_conn, socks, numsocks);
717 case CURLM_STATE_DO_MORE:
718 return domore_getsock(data->easy_conn, socks, numsocks);
720 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
721 to waiting for the same as the *PERFORM
723 case CURLM_STATE_PERFORM:
724 case CURLM_STATE_WAITPERFORM:
725 return Curl_single_getsock(data->easy_conn, socks, numsocks);
730 CURLMcode curl_multi_fdset(CURLM *multi_handle,
731 fd_set *read_fd_set, fd_set *write_fd_set,
732 fd_set *exc_fd_set, int *max_fd)
734 /* Scan through all the easy handles to get the file descriptors set.
735 Some easy handles may not have connected to the remote host yet,
736 and then we must make sure that is done. */
737 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
738 struct SessionHandle *data;
740 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
743 (void)exc_fd_set; /* not used */
745 if(!GOOD_MULTI_HANDLE(multi))
746 return CURLM_BAD_HANDLE;
750 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
752 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
753 curl_socket_t s = CURL_SOCKET_BAD;
755 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
756 FD_SET(sockbunch[i], read_fd_set);
759 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
760 FD_SET(sockbunch[i], write_fd_set);
763 if(s == CURL_SOCKET_BAD)
764 /* this socket is unused, break out of loop */
767 if((int)s > this_max_fd)
768 this_max_fd = (int)s;
772 data = data->next; /* check next handle */
775 *max_fd = this_max_fd;
780 CURLMcode curl_multi_wait(CURLM *multi_handle,
781 struct curl_waitfd extra_fds[],
782 unsigned int extra_nfds,
786 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
787 struct SessionHandle *data;
788 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
791 unsigned int nfds = 0;
792 unsigned int curlfds;
793 struct pollfd *ufds = NULL;
794 long timeout_internal;
796 if(!GOOD_MULTI_HANDLE(multi))
797 return CURLM_BAD_HANDLE;
799 /* If the internally desired timeout is actually shorter than requested from
800 the outside, then use the shorter time! But only if the internal timer
801 is actually larger than -1! */
802 (void)multi_timeout(multi, &timeout_internal);
803 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
804 timeout_ms = (int)timeout_internal;
806 /* Count up how many fds we have from the multi handle */
809 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
811 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
812 curl_socket_t s = CURL_SOCKET_BAD;
814 if(bitmap & GETSOCK_READSOCK(i)) {
818 if(bitmap & GETSOCK_WRITESOCK(i)) {
822 if(s == CURL_SOCKET_BAD) {
827 data = data->next; /* check next handle */
830 curlfds = nfds; /* number of internal file descriptors */
831 nfds += extra_nfds; /* add the externally provided ones */
833 if(nfds || extra_nfds) {
834 ufds = malloc(nfds * sizeof(struct pollfd));
836 return CURLM_OUT_OF_MEMORY;
840 /* only do the second loop if we found descriptors in the first stage run
844 /* Add the curl handles to our pollfds first */
847 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
849 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
850 curl_socket_t s = CURL_SOCKET_BAD;
852 if(bitmap & GETSOCK_READSOCK(i)) {
853 ufds[nfds].fd = sockbunch[i];
854 ufds[nfds].events = POLLIN;
858 if(bitmap & GETSOCK_WRITESOCK(i)) {
859 ufds[nfds].fd = sockbunch[i];
860 ufds[nfds].events = POLLOUT;
864 if(s == CURL_SOCKET_BAD) {
869 data = data->next; /* check next handle */
873 /* Add external file descriptions from poll-like struct curl_waitfd */
874 for(i = 0; i < extra_nfds; i++) {
875 ufds[nfds].fd = extra_fds[i].fd;
876 ufds[nfds].events = 0;
877 if(extra_fds[i].events & CURL_WAIT_POLLIN)
878 ufds[nfds].events |= POLLIN;
879 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
880 ufds[nfds].events |= POLLPRI;
881 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
882 ufds[nfds].events |= POLLOUT;
888 infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
889 i = Curl_poll(ufds, nfds, timeout_ms);
893 /* copy revents results from the poll to the curl_multi_wait poll
894 struct, the bit values of the actual underlying poll() implementation
895 may not be the same as the ones in the public libcurl API! */
896 for(j = 0; j < extra_nfds; j++) {
897 unsigned short mask = 0;
898 unsigned r = ufds[curlfds + j].revents;
901 mask |= CURL_WAIT_POLLIN;
903 mask |= CURL_WAIT_POLLOUT;
905 mask |= CURL_WAIT_POLLPRI;
907 extra_fds[j].revents = mask;
920 static CURLMcode multi_runsingle(struct Curl_multi *multi,
922 struct SessionHandle *data)
924 struct Curl_message *msg = NULL;
927 bool protocol_connect = FALSE;
928 bool dophase_done = FALSE;
930 CURLMcode result = CURLM_OK;
931 struct SingleRequest *k;
935 if(!GOOD_EASY_HANDLE(data))
936 return CURLM_BAD_EASY_HANDLE;
939 /* this is a single-iteration do-while loop just to allow a
940 break to skip to the end of it */
941 bool disconnect_conn = FALSE;
943 /* Handle the case when the pipe breaks, i.e., the connection
944 we're using gets cleaned up and we're left with nothing. */
945 if(data->state.pipe_broke) {
946 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
947 (void *)data, data->state.path);
949 if(data->mstate < CURLM_STATE_COMPLETED) {
950 /* Head back to the CONNECT state */
951 multistate(data, CURLM_STATE_CONNECT);
952 result = CURLM_CALL_MULTI_PERFORM;
953 data->result = CURLE_OK;
956 data->state.pipe_broke = FALSE;
957 data->easy_conn = NULL;
961 if(!data->easy_conn &&
962 data->mstate > CURLM_STATE_CONNECT &&
963 data->mstate < CURLM_STATE_DONE) {
964 /* In all these states, the code will blindly access 'data->easy_conn'
965 so this is precaution that it isn't NULL. And it silences static
967 failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
968 return CURLM_INTERNAL_ERROR;
971 if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
972 data->mstate < CURLM_STATE_COMPLETED)
973 /* Make sure we set the connection's current owner */
974 data->easy_conn->data = data;
976 if(data->easy_conn &&
977 (data->mstate >= CURLM_STATE_CONNECT) &&
978 (data->mstate < CURLM_STATE_COMPLETED)) {
979 /* we need to wait for the connect state as only then is the start time
980 stored, but we must not check already completed handles */
982 timeout_ms = Curl_timeleft(data, &now,
983 (data->mstate <= CURLM_STATE_WAITDO)?
987 /* Handle timed out */
988 if(data->mstate == CURLM_STATE_WAITRESOLVE)
989 failf(data, "Resolving timed out after %ld milliseconds",
990 Curl_tvdiff(now, data->progress.t_startsingle));
991 else if(data->mstate == CURLM_STATE_WAITCONNECT)
992 failf(data, "Connection timed out after %ld milliseconds",
993 Curl_tvdiff(now, data->progress.t_startsingle));
997 failf(data, "Operation timed out after %ld milliseconds with %"
998 CURL_FORMAT_CURL_OFF_T " out of %"
999 CURL_FORMAT_CURL_OFF_T " bytes received",
1000 Curl_tvdiff(k->now, data->progress.t_startsingle),
1001 k->bytecount, k->size);
1004 failf(data, "Operation timed out after %ld milliseconds with %"
1005 CURL_FORMAT_CURL_OFF_T " bytes received",
1006 Curl_tvdiff(now, data->progress.t_startsingle),
1011 /* Force the connection closed because the server could continue to
1012 send us stuff at any time. (The disconnect_conn logic used below
1013 doesn't work at this point). */
1014 connclose(data->easy_conn, "Disconnected with pending data");
1015 data->result = CURLE_OPERATION_TIMEDOUT;
1016 multistate(data, CURLM_STATE_COMPLETED);
1021 switch(data->mstate) {
1022 case CURLM_STATE_INIT:
1023 /* init this transfer. */
1024 data->result=Curl_pretransfer(data);
1026 if(CURLE_OK == data->result) {
1027 /* after init, go CONNECT */
1028 multistate(data, CURLM_STATE_CONNECT);
1029 Curl_pgrsTime(data, TIMER_STARTOP);
1030 result = CURLM_CALL_MULTI_PERFORM;
1034 case CURLM_STATE_CONNECT_PEND:
1035 /* We will stay here until there is a connection available. Then
1036 we try again in the CURLM_STATE_CONNECT state. */
1039 case CURLM_STATE_CONNECT:
1040 /* Connect. We want to get a connection identifier filled in. */
1041 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1042 data->result = Curl_connect(data, &data->easy_conn,
1043 &async, &protocol_connect);
1044 if(CURLE_NO_CONNECTION_AVAILABLE == data->result) {
1045 /* There was no connection available. We will go to the pending
1046 state and wait for an available connection. */
1047 multistate(data, CURLM_STATE_CONNECT_PEND);
1048 data->result = CURLE_OK;
1052 if(CURLE_OK == data->result) {
1053 /* Add this handle to the send or pend pipeline */
1054 data->result = Curl_add_handle_to_pipeline(data, data->easy_conn);
1055 if(CURLE_OK != data->result)
1056 disconnect_conn = TRUE;
1059 /* We're now waiting for an asynchronous name lookup */
1060 multistate(data, CURLM_STATE_WAITRESOLVE);
1062 /* after the connect has been sent off, go WAITCONNECT unless the
1063 protocol connect is already done and we can go directly to
1065 result = CURLM_CALL_MULTI_PERFORM;
1067 if(protocol_connect)
1068 multistate(data, multi->pipelining_enabled?
1069 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1071 #ifndef CURL_DISABLE_HTTP
1072 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1073 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1076 multistate(data, CURLM_STATE_WAITCONNECT);
1083 case CURLM_STATE_WAITRESOLVE:
1084 /* awaiting an asynch name resolve to complete */
1086 struct Curl_dns_entry *dns = NULL;
1088 /* check if we have the name resolved by now */
1089 data->result = Curl_resolver_is_resolved(data->easy_conn, &dns);
1091 /* Update sockets here, because the socket(s) may have been
1092 closed and the application thus needs to be told, even if it
1093 is likely that the same socket(s) will again be used further
1094 down. If the name has not yet been resolved, it is likely
1095 that new sockets have been opened in an attempt to contact
1096 another resolver. */
1097 singlesocket(multi, data);
1100 /* Perform the next step in the connection phase, and then move on
1101 to the WAITCONNECT state */
1102 data->result = Curl_async_resolved(data->easy_conn,
1105 if(CURLE_OK != data->result)
1106 /* if Curl_async_resolved() returns failure, the connection struct
1107 is already freed and gone */
1108 data->easy_conn = NULL; /* no more connection */
1110 /* call again please so that we get the next socket setup */
1111 result = CURLM_CALL_MULTI_PERFORM;
1112 if(protocol_connect)
1113 multistate(data, multi->pipelining_enabled?
1114 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1116 #ifndef CURL_DISABLE_HTTP
1117 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1118 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1121 multistate(data, CURLM_STATE_WAITCONNECT);
1126 if(CURLE_OK != data->result) {
1127 /* failure detected */
1128 disconnect_conn = TRUE;
1134 #ifndef CURL_DISABLE_HTTP
1135 case CURLM_STATE_WAITPROXYCONNECT:
1136 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1137 data->result = Curl_http_connect(data->easy_conn, &protocol_connect);
1139 if(data->easy_conn->bits.proxy_connect_closed) {
1140 /* reset the error buffer */
1141 if(data->set.errorbuffer)
1142 data->set.errorbuffer[0] = '\0';
1143 data->state.errorbuf = FALSE;
1145 data->result = CURLE_OK;
1146 result = CURLM_CALL_MULTI_PERFORM;
1147 multistate(data, CURLM_STATE_CONNECT);
1149 else if(CURLE_OK == data->result) {
1150 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1151 multistate(data, CURLM_STATE_WAITCONNECT);
1156 case CURLM_STATE_WAITCONNECT:
1157 /* awaiting a completion of an asynch connect */
1158 data->result = Curl_is_connected(data->easy_conn,
1164 /* if everything is still fine we do the protocol-specific connect
1166 data->result = Curl_protocol_connect(data->easy_conn,
1170 if(CURLE_OK != data->result) {
1171 /* failure detected */
1172 /* Just break, the cleaning up is handled all in one place */
1173 disconnect_conn = TRUE;
1178 if(!protocol_connect) {
1179 /* We have a TCP connection, but 'protocol_connect' may be false
1180 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1181 connect is TRUE, we move on to STATE_DO.
1182 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1184 #ifndef CURL_DISABLE_HTTP
1185 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1186 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1189 multistate(data, CURLM_STATE_PROTOCONNECT);
1193 /* after the connect has completed, go WAITDO or DO */
1194 multistate(data, multi->pipelining_enabled?
1195 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1197 result = CURLM_CALL_MULTI_PERFORM;
1201 case CURLM_STATE_PROTOCONNECT:
1202 /* protocol-specific connect phase */
1203 data->result = Curl_protocol_connecting(data->easy_conn,
1205 if((data->result == CURLE_OK) && protocol_connect) {
1206 /* after the connect has completed, go WAITDO or DO */
1207 multistate(data, multi->pipelining_enabled?
1208 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1209 result = CURLM_CALL_MULTI_PERFORM;
1211 else if(data->result) {
1212 /* failure detected */
1213 Curl_posttransfer(data);
1214 Curl_done(&data->easy_conn, data->result, TRUE);
1215 disconnect_conn = TRUE;
1219 case CURLM_STATE_WAITDO:
1220 /* Wait for our turn to DO when we're pipelining requests */
1222 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
1223 data->easy_conn->connection_id,
1224 data->easy_conn->send_pipe->size,
1225 data->easy_conn->writechannel_inuse?"TRUE":"FALSE",
1226 isHandleAtHead(data,
1227 data->easy_conn->send_pipe)?"TRUE":"FALSE");
1229 if(!data->easy_conn->writechannel_inuse &&
1230 isHandleAtHead(data,
1231 data->easy_conn->send_pipe)) {
1232 /* Grab the channel */
1233 data->easy_conn->writechannel_inuse = TRUE;
1234 multistate(data, CURLM_STATE_DO);
1235 result = CURLM_CALL_MULTI_PERFORM;
1239 case CURLM_STATE_DO:
1240 if(data->set.connect_only) {
1241 /* keep connection open for application to use the socket */
1242 connkeep(data->easy_conn, "CONNECT_ONLY");
1243 multistate(data, CURLM_STATE_DONE);
1244 data->result = CURLE_OK;
1245 result = CURLM_CALL_MULTI_PERFORM;
1248 /* Perform the protocol's DO action */
1249 data->result = Curl_do(&data->easy_conn, &dophase_done);
1251 /* When Curl_do() returns failure, data->easy_conn might be NULL! */
1253 if(CURLE_OK == data->result) {
1255 /* some steps needed for wildcard matching */
1256 if(data->set.wildcardmatch) {
1257 struct WildcardData *wc = &data->wildcard;
1258 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1259 /* skip some states if it is important */
1260 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1261 multistate(data, CURLM_STATE_DONE);
1262 result = CURLM_CALL_MULTI_PERFORM;
1266 /* DO was not completed in one function call, we must continue
1268 multistate(data, CURLM_STATE_DOING);
1272 /* after DO, go DO_DONE... or DO_MORE */
1273 else if(data->easy_conn->bits.do_more) {
1274 /* we're supposed to do more, but we need to sit down, relax
1275 and wait a little while first */
1276 multistate(data, CURLM_STATE_DO_MORE);
1280 /* we're done with the DO, now DO_DONE */
1281 multistate(data, CURLM_STATE_DO_DONE);
1282 result = CURLM_CALL_MULTI_PERFORM;
1285 else if((CURLE_SEND_ERROR == data->result) &&
1286 data->easy_conn->bits.reuse) {
1288 * In this situation, a connection that we were trying to use
1289 * may have unexpectedly died. If possible, send the connection
1290 * back to the CONNECT phase so we can try again.
1292 char *newurl = NULL;
1293 followtype follow=FOLLOW_NONE;
1297 drc = Curl_retry_request(data->easy_conn, &newurl);
1299 /* a failure here pretty much implies an out of memory */
1301 disconnect_conn = TRUE;
1304 retry = (newurl)?TRUE:FALSE;
1306 Curl_posttransfer(data);
1307 drc = Curl_done(&data->easy_conn, data->result, FALSE);
1309 /* When set to retry the connection, we must to go back to
1310 * the CONNECT state */
1312 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1313 follow = FOLLOW_RETRY;
1314 drc = Curl_follow(data, newurl, follow);
1315 if(drc == CURLE_OK) {
1316 multistate(data, CURLM_STATE_CONNECT);
1317 result = CURLM_CALL_MULTI_PERFORM;
1318 data->result = CURLE_OK;
1327 /* done didn't return OK or SEND_ERROR */
1333 /* Have error handler disconnect conn if we can't retry */
1334 disconnect_conn = TRUE;
1338 /* failure detected */
1339 Curl_posttransfer(data);
1341 Curl_done(&data->easy_conn, data->result, FALSE);
1342 disconnect_conn = TRUE;
1347 case CURLM_STATE_DOING:
1348 /* we continue DOING until the DO phase is complete */
1349 data->result = Curl_protocol_doing(data->easy_conn,
1351 if(CURLE_OK == data->result) {
1353 /* after DO, go DO_DONE or DO_MORE */
1354 multistate(data, data->easy_conn->bits.do_more?
1355 CURLM_STATE_DO_MORE:
1356 CURLM_STATE_DO_DONE);
1357 result = CURLM_CALL_MULTI_PERFORM;
1358 } /* dophase_done */
1361 /* failure detected */
1362 Curl_posttransfer(data);
1363 Curl_done(&data->easy_conn, data->result, FALSE);
1364 disconnect_conn = TRUE;
1368 case CURLM_STATE_DO_MORE:
1370 * When we are connected, DO MORE and then go DO_DONE
1372 data->result = Curl_do_more(data->easy_conn, &control);
1374 /* No need to remove this handle from the send pipeline here since that
1375 is done in Curl_done() */
1376 if(CURLE_OK == data->result) {
1378 /* if positive, advance to DO_DONE
1379 if negative, go back to DOING */
1380 multistate(data, control==1?
1381 CURLM_STATE_DO_DONE:
1383 result = CURLM_CALL_MULTI_PERFORM;
1386 /* stay in DO_MORE */
1390 /* failure detected */
1391 Curl_posttransfer(data);
1392 Curl_done(&data->easy_conn, data->result, FALSE);
1393 disconnect_conn = TRUE;
1397 case CURLM_STATE_DO_DONE:
1398 /* Move ourselves from the send to recv pipeline */
1399 Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
1400 /* Check if we can move pending requests to send pipe */
1401 Curl_multi_process_pending_handles(multi);
1403 /* Only perform the transfer if there's a good socket to work with.
1404 Having both BAD is a signal to skip immediately to DONE */
1405 if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
1406 (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
1407 multistate(data, CURLM_STATE_WAITPERFORM);
1409 multistate(data, CURLM_STATE_DONE);
1410 result = CURLM_CALL_MULTI_PERFORM;
1413 case CURLM_STATE_WAITPERFORM:
1414 /* Wait for our turn to PERFORM */
1415 if(!data->easy_conn->readchannel_inuse &&
1416 isHandleAtHead(data,
1417 data->easy_conn->recv_pipe)) {
1418 /* Grab the channel */
1419 data->easy_conn->readchannel_inuse = TRUE;
1420 multistate(data, CURLM_STATE_PERFORM);
1421 result = CURLM_CALL_MULTI_PERFORM;
1425 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
1426 data->easy_conn->connection_id,
1427 data->easy_conn->recv_pipe->size,
1428 data->easy_conn->readchannel_inuse?"TRUE":"FALSE",
1429 isHandleAtHead(data,
1430 data->easy_conn->recv_pipe)?"TRUE":"FALSE");
1435 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1436 /* if both rates are within spec, resume transfer */
1437 if(Curl_pgrsUpdate(data->easy_conn))
1438 data->result = CURLE_ABORTED_BY_CALLBACK;
1440 data->result = Curl_speedcheck(data, now);
1442 if(( (data->set.max_send_speed == 0) ||
1443 (data->progress.ulspeed < data->set.max_send_speed )) &&
1444 ( (data->set.max_recv_speed == 0) ||
1445 (data->progress.dlspeed < data->set.max_recv_speed)))
1446 multistate(data, CURLM_STATE_PERFORM);
1449 case CURLM_STATE_PERFORM:
1451 char *newurl = NULL;
1454 /* check if over send speed */
1455 if((data->set.max_send_speed > 0) &&
1456 (data->progress.ulspeed > data->set.max_send_speed)) {
1459 multistate(data, CURLM_STATE_TOOFAST);
1461 /* calculate upload rate-limitation timeout. */
1462 buffersize = (int)(data->set.buffer_size ?
1463 data->set.buffer_size : BUFSIZE);
1464 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1465 data->progress.ulspeed, buffersize);
1466 Curl_expire(data, timeout_ms);
1470 /* check if over recv speed */
1471 if((data->set.max_recv_speed > 0) &&
1472 (data->progress.dlspeed > data->set.max_recv_speed)) {
1475 multistate(data, CURLM_STATE_TOOFAST);
1477 /* Calculate download rate-limitation timeout. */
1478 buffersize = (int)(data->set.buffer_size ?
1479 data->set.buffer_size : BUFSIZE);
1480 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1481 data->progress.dlspeed, buffersize);
1482 Curl_expire(data, timeout_ms);
1486 /* read/write data if it is ready to do so */
1487 data->result = Curl_readwrite(data->easy_conn, &done);
1491 if(!(k->keepon & KEEP_RECV)) {
1492 /* We're done receiving */
1493 data->easy_conn->readchannel_inuse = FALSE;
1496 if(!(k->keepon & KEEP_SEND)) {
1497 /* We're done sending */
1498 data->easy_conn->writechannel_inuse = FALSE;
1501 if(done || (data->result == CURLE_RECV_ERROR)) {
1502 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1503 * condition and the server closed the re-used connection exactly when
1504 * we wanted to use it, so figure out if that is indeed the case.
1506 CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
1508 retry = (newurl)?TRUE:FALSE;
1511 /* if we are to retry, set the result to OK and consider the
1513 data->result = CURLE_OK;
1520 * The transfer phase returned error, we mark the connection to get
1521 * closed to prevent being re-used. This is because we can't possibly
1522 * know if the connection is in a good shape or not now. Unless it is
1523 * a protocol which uses two "channels" like FTP, as then the error
1524 * happened in the data connection.
1527 if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
1528 connclose(data->easy_conn, "Transfer returned error");
1530 Curl_posttransfer(data);
1531 Curl_done(&data->easy_conn, data->result, FALSE);
1534 followtype follow=FOLLOW_NONE;
1536 /* call this even if the readwrite function returned error */
1537 Curl_posttransfer(data);
1539 /* we're no longer receiving */
1540 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1542 /* expire the new receiving pipeline head */
1543 if(data->easy_conn->recv_pipe->head)
1544 Curl_expire(data->easy_conn->recv_pipe->head->ptr, 1);
1546 /* Check if we can move pending requests to send pipe */
1547 Curl_multi_process_pending_handles(multi);
1549 /* When we follow redirects or is set to retry the connection, we must
1550 to go back to the CONNECT state */
1551 if(data->req.newurl || retry) {
1553 /* if the URL is a follow-location and not just a retried request
1554 then figure out the URL here */
1555 newurl = data->req.newurl;
1556 data->req.newurl = NULL;
1557 follow = FOLLOW_REDIR;
1560 follow = FOLLOW_RETRY;
1561 data->result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1562 if(CURLE_OK == data->result) {
1563 data->result = Curl_follow(data, newurl, follow);
1564 if(CURLE_OK == data->result) {
1565 multistate(data, CURLM_STATE_CONNECT);
1566 result = CURLM_CALL_MULTI_PERFORM;
1567 newurl = NULL; /* handed over the memory ownership to
1568 Curl_follow(), make sure we don't free() it
1574 /* after the transfer is done, go DONE */
1576 /* but first check to see if we got a location info even though we're
1577 not following redirects */
1578 if(data->req.location) {
1581 newurl = data->req.location;
1582 data->req.location = NULL;
1583 data->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1584 if(CURLE_OK == data->result)
1585 newurl = NULL; /* allocation was handed over Curl_follow() */
1587 disconnect_conn = TRUE;
1590 multistate(data, CURLM_STATE_DONE);
1591 result = CURLM_CALL_MULTI_PERFORM;
1600 case CURLM_STATE_DONE:
1601 /* this state is highly transient, so run another loop after this */
1602 result = CURLM_CALL_MULTI_PERFORM;
1604 if(data->easy_conn) {
1607 /* Remove ourselves from the receive pipeline, if we are there. */
1608 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1609 /* Check if we can move pending requests to send pipe */
1610 Curl_multi_process_pending_handles(multi);
1612 /* post-transfer command */
1613 res = Curl_done(&data->easy_conn, data->result, FALSE);
1615 /* allow a previously set error code take precedence */
1620 * If there are other handles on the pipeline, Curl_done won't set
1621 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1622 * access free'd data, if the connection is free'd and the handle
1623 * removed before we perform the processing in CURLM_STATE_COMPLETED
1626 data->easy_conn = NULL;
1629 if(data->set.wildcardmatch) {
1630 if(data->wildcard.state != CURLWC_DONE) {
1631 /* if a wildcard is set and we are not ending -> lets start again
1632 with CURLM_STATE_INIT */
1633 multistate(data, CURLM_STATE_INIT);
1638 /* after we have DONE what we're supposed to do, go COMPLETED, and
1639 it doesn't matter what the Curl_done() returned! */
1640 multistate(data, CURLM_STATE_COMPLETED);
1643 case CURLM_STATE_COMPLETED:
1644 /* this is a completed transfer, it is likely to still be connected */
1646 /* This node should be delinked from the list now and we should post
1647 an information message that we are complete. */
1649 /* Important: reset the conn pointer so that we don't point to memory
1650 that could be freed anytime */
1651 data->easy_conn = NULL;
1653 Curl_expire(data, 0); /* stop all timers */
1656 case CURLM_STATE_MSGSENT:
1657 return CURLM_OK; /* do nothing */
1660 return CURLM_INTERNAL_ERROR;
1663 if(data->mstate < CURLM_STATE_COMPLETED) {
1664 if(CURLE_OK != data->result) {
1666 * If an error was returned, and we aren't in completed state now,
1667 * then we go to completed and consider this transfer aborted.
1670 /* NOTE: no attempt to disconnect connections must be made
1671 in the case blocks above - cleanup happens only here */
1673 data->state.pipe_broke = FALSE;
1675 if(data->easy_conn) {
1676 /* if this has a connection, unsubscribe from the pipelines */
1677 data->easy_conn->writechannel_inuse = FALSE;
1678 data->easy_conn->readchannel_inuse = FALSE;
1679 Curl_removeHandleFromPipeline(data,
1680 data->easy_conn->send_pipe);
1681 Curl_removeHandleFromPipeline(data,
1682 data->easy_conn->recv_pipe);
1683 /* Check if we can move pending requests to send pipe */
1684 Curl_multi_process_pending_handles(multi);
1686 if(disconnect_conn) {
1687 /* disconnect properly */
1688 Curl_disconnect(data->easy_conn, /* dead_connection */ FALSE);
1690 /* This is where we make sure that the easy_conn pointer is reset.
1691 We don't have to do this in every case block above where a
1692 failure is detected */
1693 data->easy_conn = NULL;
1696 else if(data->mstate == CURLM_STATE_CONNECT) {
1697 /* Curl_connect() failed */
1698 (void)Curl_posttransfer(data);
1701 multistate(data, CURLM_STATE_COMPLETED);
1703 /* if there's still a connection to use, call the progress function */
1704 else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
1705 /* aborted due to progress callback return code must close the
1707 data->result = CURLE_ABORTED_BY_CALLBACK;
1708 connclose(data->easy_conn, "Aborted by callback");
1710 /* if not yet in DONE state, go there, otherwise COMPLETED */
1711 multistate(data, (data->mstate < CURLM_STATE_DONE)?
1712 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1713 result = CURLM_CALL_MULTI_PERFORM;
1716 } WHILE_FALSE; /* just to break out from! */
1718 if(CURLM_STATE_COMPLETED == data->mstate) {
1719 /* now fill in the Curl_message with this info */
1722 msg->extmsg.msg = CURLMSG_DONE;
1723 msg->extmsg.easy_handle = data;
1724 msg->extmsg.data.result = data->result;
1726 result = multi_addmsg(multi, msg);
1728 multistate(data, CURLM_STATE_MSGSENT);
1735 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1737 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1738 struct SessionHandle *data;
1739 CURLMcode returncode=CURLM_OK;
1740 struct Curl_tree *t;
1741 struct timeval now = Curl_tvnow();
1743 if(!GOOD_MULTI_HANDLE(multi))
1744 return CURLM_BAD_HANDLE;
1749 struct WildcardData *wc = &data->wildcard;
1750 SIGPIPE_VARIABLE(pipe_st);
1752 if(data->set.wildcardmatch) {
1754 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1756 return CURLM_OUT_OF_MEMORY;
1760 sigpipe_ignore(data, &pipe_st);
1762 result = multi_runsingle(multi, now, data);
1763 while(CURLM_CALL_MULTI_PERFORM == result);
1764 sigpipe_restore(&pipe_st);
1766 if(data->set.wildcardmatch) {
1767 /* destruct wildcard structures if it is needed */
1768 if(wc->state == CURLWC_DONE || result)
1769 Curl_wildcard_dtor(wc);
1773 returncode = result;
1775 data = data->next; /* operate on next handle */
1779 * Simply remove all expired timers from the splay since handles are dealt
1780 * with unconditionally by this function and curl_multi_timeout() requires
1781 * that already passed/handled expire times are removed from the splay.
1783 * It is important that the 'now' value is set at the entry of this function
1784 * and not for the current time as it may have ticked a little while since
1785 * then and then we risk this loop to remove timers that actually have not
1789 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1791 /* the removed may have another timeout in queue */
1792 (void)add_next_timeout(now, multi, t->payload);
1796 *running_handles = multi->num_alive;
1798 if(CURLM_OK >= returncode)
1799 update_timer(multi);
1804 static void close_all_connections(struct Curl_multi *multi)
1806 struct connectdata *conn;
1808 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1810 SIGPIPE_VARIABLE(pipe_st);
1811 conn->data = multi->closure_handle;
1813 sigpipe_ignore(conn->data, &pipe_st);
1814 /* This will remove the connection from the cache */
1815 (void)Curl_disconnect(conn, FALSE);
1816 sigpipe_restore(&pipe_st);
1818 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1822 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1824 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1825 struct SessionHandle *data;
1826 struct SessionHandle *nextdata;
1828 if(GOOD_MULTI_HANDLE(multi)) {
1829 bool restore_pipe = FALSE;
1830 SIGPIPE_VARIABLE(pipe_st);
1832 multi->type = 0; /* not good anymore */
1834 /* Close all the connections in the connection cache */
1835 close_all_connections(multi);
1837 if(multi->closure_handle) {
1838 sigpipe_ignore(multi->closure_handle, &pipe_st);
1839 restore_pipe = TRUE;
1841 multi->closure_handle->dns.hostcache = multi->hostcache;
1842 Curl_hostcache_clean(multi->closure_handle,
1843 multi->closure_handle->dns.hostcache);
1845 Curl_close(multi->closure_handle);
1846 multi->closure_handle = NULL;
1849 Curl_hash_destroy(multi->sockhash);
1850 multi->sockhash = NULL;
1852 Curl_conncache_destroy(multi->conn_cache);
1853 multi->conn_cache = NULL;
1855 /* remove the pending list of messages */
1856 Curl_llist_destroy(multi->msglist, NULL);
1857 multi->msglist = NULL;
1859 /* remove all easy handles */
1860 data = multi->easyp;
1862 nextdata=data->next;
1863 if(data->dns.hostcachetype == HCACHE_MULTI) {
1864 /* clear out the usage of the shared DNS cache */
1865 Curl_hostcache_clean(data, data->dns.hostcache);
1866 data->dns.hostcache = NULL;
1867 data->dns.hostcachetype = HCACHE_NONE;
1870 /* Clear the pointer to the connection cache */
1871 data->state.conn_cache = NULL;
1872 data->multi = NULL; /* clear the association */
1877 Curl_hash_destroy(multi->hostcache);
1878 multi->hostcache = NULL;
1880 /* Free the blacklists by setting them to NULL */
1881 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1882 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1886 sigpipe_restore(&pipe_st);
1891 return CURLM_BAD_HANDLE;
1895 * curl_multi_info_read()
1897 * This function is the primary way for a multi/multi_socket application to
1898 * figure out if a transfer has ended. We MUST make this function as fast as
1899 * possible as it will be polled frequently and we MUST NOT scan any lists in
1900 * here to figure out things. We must scale fine to thousands of handles and
1901 * beyond. The current design is fully O(1).
1904 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1906 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1907 struct Curl_message *msg;
1909 *msgs_in_queue = 0; /* default to none */
1911 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1912 /* there is one or more messages in the list */
1913 struct curl_llist_element *e;
1915 /* extract the head of the list to return */
1916 e = multi->msglist->head;
1920 /* remove the extracted entry */
1921 Curl_llist_remove(multi->msglist, e, NULL);
1923 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1925 return &msg->extmsg;
1932 * singlesocket() checks what sockets we deal with and their "action state"
1933 * and if we have a different state in any of those sockets from last time we
1934 * call the callback accordingly.
1936 static void singlesocket(struct Curl_multi *multi,
1937 struct SessionHandle *data)
1939 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1941 struct Curl_sh_entry *entry;
1944 unsigned int curraction;
1945 bool remove_sock_from_hash;
1947 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1948 socks[i] = CURL_SOCKET_BAD;
1950 /* Fill in the 'current' struct with the state as it is now: what sockets to
1951 supervise and for what actions */
1952 curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
1954 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1955 sockets we should have from now on. Detect the differences, remove no
1956 longer supervised ones and add new ones */
1958 /* walk over the sockets we got right now */
1959 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1960 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1962 int action = CURL_POLL_NONE;
1966 /* get it from the hash */
1967 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1969 if(curraction & GETSOCK_READSOCK(i))
1970 action |= CURL_POLL_IN;
1971 if(curraction & GETSOCK_WRITESOCK(i))
1972 action |= CURL_POLL_OUT;
1975 /* yeps, already present so check if it has the same action set */
1976 if(entry->action == action)
1977 /* same, continue */
1981 /* this is a socket we didn't have before, add it! */
1982 entry = sh_addentry(multi->sockhash, s, data);
1988 /* we know (entry != NULL) at this point, see the logic above */
1989 if(multi->socket_cb)
1990 multi->socket_cb(data,
1993 multi->socket_userp,
1996 entry->action = action; /* store the current action state */
1999 num = i; /* number of sockets */
2001 /* when we've walked over all the sockets we should have right now, we must
2002 make sure to detect sockets that are removed */
2003 for(i=0; i< data->numsocks; i++) {
2005 s = data->sockets[i];
2006 for(j=0; j<num; j++) {
2008 /* this is still supervised */
2009 s = CURL_SOCKET_BAD;
2013 if(s != CURL_SOCKET_BAD) {
2015 /* this socket has been removed. Tell the app to remove it */
2016 remove_sock_from_hash = TRUE;
2018 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2020 /* check if the socket to be removed serves a connection which has
2021 other easy-s in a pipeline. In this case the socket should not be
2023 struct connectdata *easy_conn = data->easy_conn;
2025 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2026 /* the handle should not be removed from the pipe yet */
2027 remove_sock_from_hash = FALSE;
2029 /* Update the sockhash entry to instead point to the next in line
2030 for the recv_pipe, or the first (in case this particular easy
2032 if(entry->easy == data) {
2033 if(isHandleAtHead(data, easy_conn->recv_pipe))
2034 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2036 entry->easy = easy_conn->recv_pipe->head->ptr;
2039 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2040 /* the handle should not be removed from the pipe yet */
2041 remove_sock_from_hash = FALSE;
2043 /* Update the sockhash entry to instead point to the next in line
2044 for the send_pipe, or the first (in case this particular easy
2046 if(entry->easy == data) {
2047 if(isHandleAtHead(data, easy_conn->send_pipe))
2048 entry->easy = easy_conn->send_pipe->head->next->ptr;
2050 entry->easy = easy_conn->send_pipe->head->ptr;
2053 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2054 when action will be asked on the socket (see multi_socket()), the
2055 head of the correct pipe will be taken according to the
2060 /* just a precaution, this socket really SHOULD be in the hash already
2061 but in case it isn't, we don't have to tell the app to remove it
2062 either since it never got to know about it */
2063 remove_sock_from_hash = FALSE;
2065 if(remove_sock_from_hash) {
2066 /* in this case 'entry' is always non-NULL */
2067 if(multi->socket_cb)
2068 multi->socket_cb(data,
2071 multi->socket_userp,
2073 sh_delentry(multi->sockhash, s);
2079 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2080 data->numsocks = num;
2084 * Curl_multi_closed()
2086 * Used by the connect code to tell the multi_socket code that one of the
2087 * sockets we were using have just been closed. This function will then
2088 * remove it from the sockethash for this handle to make the multi_socket API
2089 * behave properly, especially for the case when libcurl will create another
2090 * socket again and it gets the same file descriptor number.
2093 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2095 struct Curl_multi *multi = conn->data->multi;
2097 /* this is set if this connection is part of a handle that is added to
2098 a multi handle, and only then this is necessary */
2099 struct Curl_sh_entry *entry =
2100 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2103 if(multi->socket_cb)
2104 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2105 multi->socket_userp,
2108 /* now remove it from the socket hash */
2109 sh_delentry(multi->sockhash, s);
2117 * add_next_timeout()
2119 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2120 * when it has just been removed from the splay tree because the timeout has
2121 * expired. This function is then to advance in the list to pick the next
2122 * timeout to use (skip the already expired ones) and add this node back to
2123 * the splay tree again.
2125 * The splay tree only has each sessionhandle as a single node and the nearest
2126 * timeout is used to sort it on.
2128 static CURLMcode add_next_timeout(struct timeval now,
2129 struct Curl_multi *multi,
2130 struct SessionHandle *d)
2132 struct timeval *tv = &d->state.expiretime;
2133 struct curl_llist *list = d->state.timeoutlist;
2134 struct curl_llist_element *e;
2136 /* move over the timeout list for this specific handle and remove all
2137 timeouts that are now passed tense and store the next pending
2139 for(e = list->head; e; ) {
2140 struct curl_llist_element *n = e->next;
2141 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2143 /* remove outdated entry */
2144 Curl_llist_remove(list, e, NULL);
2146 /* the list is sorted so get out on the first mismatch */
2152 /* clear the expire times within the handles that we remove from the
2158 /* copy the first entry to 'tv' */
2159 memcpy(tv, e->ptr, sizeof(*tv));
2161 /* remove first entry from list */
2162 Curl_llist_remove(list, e, NULL);
2164 /* insert this node again into the splay */
2165 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2166 &d->state.timenode);
2171 static CURLMcode multi_socket(struct Curl_multi *multi,
2175 int *running_handles)
2177 CURLMcode result = CURLM_OK;
2178 struct SessionHandle *data = NULL;
2179 struct Curl_tree *t;
2180 struct timeval now = Curl_tvnow();
2183 /* *perform() deals with running_handles on its own */
2184 result = curl_multi_perform(multi, running_handles);
2186 /* walk through each easy handle and do the socket state change magic
2188 if(result != CURLM_BAD_HANDLE) {
2191 singlesocket(multi, data);
2196 /* or should we fall-through and do the timer-based stuff? */
2199 else if(s != CURL_SOCKET_TIMEOUT) {
2201 struct Curl_sh_entry *entry =
2202 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2205 /* Unmatched socket, we can't act on it but we ignore this fact. In
2206 real-world tests it has been proved that libevent can in fact give
2207 the application actions even though the socket was just previously
2208 asked to get removed, so thus we better survive stray socket actions
2209 and just move on. */
2212 SIGPIPE_VARIABLE(pipe_st);
2216 if(data->magic != CURLEASY_MAGIC_NUMBER)
2217 /* bad bad bad bad bad bad bad */
2218 return CURLM_INTERNAL_ERROR;
2220 /* If the pipeline is enabled, take the handle which is in the head of
2221 the pipeline. If we should write into the socket, take the send_pipe
2222 head. If we should read from the socket, take the recv_pipe head. */
2223 if(data->easy_conn) {
2224 if((ev_bitmask & CURL_POLL_OUT) &&
2225 data->easy_conn->send_pipe &&
2226 data->easy_conn->send_pipe->head)
2227 data = data->easy_conn->send_pipe->head->ptr;
2228 else if((ev_bitmask & CURL_POLL_IN) &&
2229 data->easy_conn->recv_pipe &&
2230 data->easy_conn->recv_pipe->head)
2231 data = data->easy_conn->recv_pipe->head->ptr;
2234 if(data->easy_conn &&
2235 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2236 /* set socket event bitmask if they're not locked */
2237 data->easy_conn->cselect_bits = ev_bitmask;
2239 sigpipe_ignore(data, &pipe_st);
2241 result = multi_runsingle(multi, now, data);
2242 while(CURLM_CALL_MULTI_PERFORM == result);
2243 sigpipe_restore(&pipe_st);
2245 if(data->easy_conn &&
2246 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2247 /* clear the bitmask only if not locked */
2248 data->easy_conn->cselect_bits = 0;
2250 if(CURLM_OK >= result)
2251 /* get the socket(s) and check if the state has been changed since
2253 singlesocket(multi, data);
2255 /* Now we fall-through and do the timer-based stuff, since we don't want
2256 to force the user to have to deal with timeouts as long as at least
2257 one connection in fact has traffic. */
2259 data = NULL; /* set data to NULL again to avoid calling
2260 multi_runsingle() in case there's no need to */
2261 now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
2262 may have taken some time */
2266 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
2267 update_timer() to trigger a callback to the app again even if the same
2268 timeout is still the one to run after this call. That handles the case
2269 when the application asks libcurl to run the timeout prematurely. */
2270 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
2274 * The loop following here will go on as long as there are expire-times left
2275 * to process in the splay and 'data' will be re-assigned for every expired
2276 * handle we deal with.
2279 /* the first loop lap 'data' can be NULL */
2281 SIGPIPE_VARIABLE(pipe_st);
2283 sigpipe_ignore(data, &pipe_st);
2285 result = multi_runsingle(multi, now, data);
2286 while(CURLM_CALL_MULTI_PERFORM == result);
2287 sigpipe_restore(&pipe_st);
2289 if(CURLM_OK >= result)
2290 /* get the socket(s) and check if the state has been changed since
2292 singlesocket(multi, data);
2295 /* Check if there's one (more) expired timer to deal with! This function
2296 extracts a matching node if there is one */
2298 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2300 data = t->payload; /* assign this for next loop */
2301 (void)add_next_timeout(now, multi, t->payload);
2306 *running_handles = multi->num_alive;
2310 #undef curl_multi_setopt
2311 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2312 CURLMoption option, ...)
2314 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2315 CURLMcode res = CURLM_OK;
2318 if(!GOOD_MULTI_HANDLE(multi))
2319 return CURLM_BAD_HANDLE;
2321 va_start(param, option);
2324 case CURLMOPT_SOCKETFUNCTION:
2325 multi->socket_cb = va_arg(param, curl_socket_callback);
2327 case CURLMOPT_SOCKETDATA:
2328 multi->socket_userp = va_arg(param, void *);
2330 case CURLMOPT_PIPELINING:
2331 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2333 case CURLMOPT_TIMERFUNCTION:
2334 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2336 case CURLMOPT_TIMERDATA:
2337 multi->timer_userp = va_arg(param, void *);
2339 case CURLMOPT_MAXCONNECTS:
2340 multi->maxconnects = va_arg(param, long);
2342 case CURLMOPT_MAX_HOST_CONNECTIONS:
2343 multi->max_host_connections = va_arg(param, long);
2345 case CURLMOPT_MAX_PIPELINE_LENGTH:
2346 multi->max_pipeline_length = va_arg(param, long);
2348 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2349 multi->content_length_penalty_size = va_arg(param, long);
2351 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2352 multi->chunk_length_penalty_size = va_arg(param, long);
2354 case CURLMOPT_PIPELINING_SITE_BL:
2355 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2356 &multi->pipelining_site_bl);
2358 case CURLMOPT_PIPELINING_SERVER_BL:
2359 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2360 &multi->pipelining_server_bl);
2362 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2363 multi->max_total_connections = va_arg(param, long);
2366 res = CURLM_UNKNOWN_OPTION;
2373 /* we define curl_multi_socket() in the public multi.h header */
2374 #undef curl_multi_socket
2376 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2377 int *running_handles)
2379 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2380 0, running_handles);
2381 if(CURLM_OK >= result)
2382 update_timer((struct Curl_multi *)multi_handle);
2386 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2387 int ev_bitmask, int *running_handles)
2389 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2390 ev_bitmask, running_handles);
2391 if(CURLM_OK >= result)
2392 update_timer((struct Curl_multi *)multi_handle);
2396 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2399 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2400 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2401 if(CURLM_OK >= result)
2402 update_timer((struct Curl_multi *)multi_handle);
2406 static CURLMcode multi_timeout(struct Curl_multi *multi,
2409 static struct timeval tv_zero = {0,0};
2411 if(multi->timetree) {
2412 /* we have a tree of expire times */
2413 struct timeval now = Curl_tvnow();
2415 /* splay the lowest to the bottom */
2416 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2418 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2419 /* some time left before expiration */
2420 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2423 * Since we only provide millisecond resolution on the returned value
2424 * and the diff might be less than one millisecond here, we don't
2425 * return zero as that may cause short bursts of busyloops on fast
2426 * processors while the diff is still present but less than one
2427 * millisecond! instead we return 1 until the time is ripe.
2432 /* 0 means immediately */
2441 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2444 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2446 /* First, make some basic checks that the CURLM handle is a good handle */
2447 if(!GOOD_MULTI_HANDLE(multi))
2448 return CURLM_BAD_HANDLE;
2450 return multi_timeout(multi, timeout_ms);
2454 * Tell the application it should update its timers, if it subscribes to the
2455 * update timer callback.
2457 static int update_timer(struct Curl_multi *multi)
2461 if(!multi->timer_cb)
2463 if(multi_timeout(multi, &timeout_ms)) {
2466 if(timeout_ms < 0) {
2467 static const struct timeval none={0,0};
2468 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2469 multi->timer_lastcall = none;
2470 /* there's no timeout now but there was one previously, tell the app to
2472 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2477 /* When multi_timeout() is done, multi->timetree points to the node with the
2478 * timeout we got the (relative) time-out time for. We can thus easily check
2479 * if this is the same (fixed) time as we got in a previous call and then
2480 * avoid calling the callback again. */
2481 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2484 multi->timer_lastcall = multi->timetree->key;
2486 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2489 void Curl_multi_set_easy_connection(struct SessionHandle *handle,
2490 struct connectdata *conn)
2492 handle->easy_conn = conn;
2495 static bool isHandleAtHead(struct SessionHandle *handle,
2496 struct curl_llist *pipeline)
2498 struct curl_llist_element *curr = pipeline->head;
2500 return (curr->ptr == handle) ? TRUE : FALSE;
2506 * multi_freetimeout()
2508 * Callback used by the llist system when a single timeout list entry is
2511 static void multi_freetimeout(void *user, void *entryptr)
2515 /* the entry was plain malloc()'ed */
2520 * multi_addtimeout()
2522 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2523 * of list is always the timeout nearest in time.
2527 multi_addtimeout(struct curl_llist *timeoutlist,
2528 struct timeval *stamp)
2530 struct curl_llist_element *e;
2531 struct timeval *timedup;
2532 struct curl_llist_element *prev = NULL;
2534 timedup = malloc(sizeof(*timedup));
2536 return CURLM_OUT_OF_MEMORY;
2538 /* copy the timestamp */
2539 memcpy(timedup, stamp, sizeof(*timedup));
2541 if(Curl_llist_count(timeoutlist)) {
2542 /* find the correct spot in the list */
2543 for(e = timeoutlist->head; e; e = e->next) {
2544 struct timeval *checktime = e->ptr;
2545 long diff = curlx_tvdiff(*checktime, *timedup);
2553 this is the first timeout on the list */
2555 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2557 return CURLM_OUT_OF_MEMORY;
2566 * given a number of milliseconds from now to use to set the 'act before
2567 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2569 * Note that the timeout will be added to a queue of timeouts if it defines a
2570 * moment in time that is later than the current head of queue.
2572 * Pass zero to clear all timeout values for this handle.
2574 void Curl_expire(struct SessionHandle *data, long milli)
2576 struct Curl_multi *multi = data->multi;
2577 struct timeval *nowp = &data->state.expiretime;
2580 /* this is only interesting while there is still an associated multi struct
2586 /* No timeout, clear the time data. */
2587 if(nowp->tv_sec || nowp->tv_usec) {
2588 /* Since this is an cleared time, we must remove the previous entry from
2590 struct curl_llist *list = data->state.timeoutlist;
2592 rc = Curl_splayremovebyaddr(multi->timetree,
2593 &data->state.timenode,
2596 infof(data, "Internal error clearing splay node = %d\n", rc);
2598 /* flush the timeout list too */
2599 while(list->size > 0)
2600 Curl_llist_remove(list, list->tail, NULL);
2603 infof(data, "Expire cleared\n");
2613 set.tv_sec += milli/1000;
2614 set.tv_usec += (milli%1000)*1000;
2616 if(set.tv_usec >= 1000000) {
2618 set.tv_usec -= 1000000;
2621 if(nowp->tv_sec || nowp->tv_usec) {
2622 /* This means that the struct is added as a node in the splay tree.
2623 Compare if the new time is earlier, and only remove-old/add-new if it
2625 long diff = curlx_tvdiff(set, *nowp);
2627 /* the new expire time was later so just add it to the queue
2629 multi_addtimeout(data->state.timeoutlist, &set);
2633 /* the new time is newer than the presently set one, so add the current
2634 to the queue and update the head */
2635 multi_addtimeout(data->state.timeoutlist, nowp);
2637 /* Since this is an updated time, we must remove the previous entry from
2638 the splay tree first and then re-add the new value */
2639 rc = Curl_splayremovebyaddr(multi->timetree,
2640 &data->state.timenode,
2643 infof(data, "Internal error removing splay node = %d\n", rc);
2647 data->state.timenode.payload = data;
2648 multi->timetree = Curl_splayinsert(*nowp,
2650 &data->state.timenode);
2653 Curl_splayprint(multi->timetree, 0, TRUE);
2657 CURLMcode curl_multi_assign(CURLM *multi_handle,
2658 curl_socket_t s, void *hashp)
2660 struct Curl_sh_entry *there = NULL;
2661 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2663 if(s != CURL_SOCKET_BAD)
2664 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2667 return CURLM_BAD_SOCKET;
2669 there->socketp = hashp;
2674 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2676 return multi ? multi->max_host_connections : 0;
2679 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2681 return multi ? multi->max_total_connections : 0;
2684 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2686 return multi ? multi->max_pipeline_length : 0;
2689 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2691 return multi ? multi->content_length_penalty_size : 0;
2694 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2696 return multi ? multi->chunk_length_penalty_size : 0;
2699 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2701 return multi->pipelining_site_bl;
2704 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2706 return multi->pipelining_server_bl;
2709 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2711 struct SessionHandle *data;
2715 if(data->mstate == CURLM_STATE_CONNECT_PEND) {
2716 multistate(data, CURLM_STATE_CONNECT);
2717 /* Make sure that the handle will be processed soonish. */
2718 Curl_expire(data, 1);
2720 data = data->next; /* operate on next handle */
2725 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2727 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2728 struct SessionHandle *data;
2730 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2731 multi->num_easy, multi->num_alive);
2732 for(data=multi->easyp; data; data = data->next) {
2733 if(data->mstate < CURLM_STATE_COMPLETED) {
2734 /* only display handles that are not completed */
2735 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2737 statename[data->mstate], data->numsocks);
2738 for(i=0; i < data->numsocks; i++) {
2739 curl_socket_t s = data->sockets[i];
2740 struct Curl_sh_entry *entry =
2741 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2743 fprintf(stderr, "%d ", (int)s);
2745 fprintf(stderr, "INTERNAL CONFUSION\n");
2748 fprintf(stderr, "[%s %s] ",
2749 entry->action&CURL_POLL_IN?"RECVING":"",
2750 entry->action&CURL_POLL_OUT?"SENDING":"");
2753 fprintf(stderr, "\n");