1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #include <curl/curl.h>
40 #include "speedcheck.h"
41 #include "conncache.h"
43 #include "multihandle.h"
47 #define _MPRINTF_REPLACE /* use our functions only */
48 #include <curl/mprintf.h>
50 #include "curl_memory.h"
51 /* The last #include file should be: */
55 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
56 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
57 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
59 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
60 #define CURL_SOCKET_HASH_TABLE_SIZE 911
63 #define CURL_CONNECTION_HASH_SIZE 97
65 #define CURL_MULTI_HANDLE 0x000bab1e
67 #define GOOD_MULTI_HANDLE(x) \
68 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
69 #define GOOD_EASY_HANDLE(x) \
70 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
72 static void singlesocket(struct Curl_multi *multi,
73 struct SessionHandle *data);
74 static int update_timer(struct Curl_multi *multi);
76 static bool isHandleAtHead(struct SessionHandle *handle,
77 struct curl_llist *pipeline);
78 static CURLMcode add_next_timeout(struct timeval now,
79 struct Curl_multi *multi,
80 struct SessionHandle *d);
81 static CURLMcode multi_timeout(struct Curl_multi *multi,
85 static const char * const statename[]={
107 static void multi_freetimeout(void *a, void *b);
109 /* always use this function to change state, to make debugging easier */
110 static void mstate(struct SessionHandle *data, CURLMstate state
116 CURLMstate oldstate = data->mstate;
118 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
122 if(oldstate == state)
123 /* don't bother when the new state is the same as the old state */
126 data->mstate = state;
128 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
129 if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
130 data->mstate < CURLM_STATE_COMPLETED) {
131 long connection_id = -5000;
134 connection_id = data->easy_conn->connection_id;
137 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
138 statename[oldstate], statename[data->mstate],
139 (void *)data, lineno, connection_id);
143 if(state == CURLM_STATE_COMPLETED)
144 /* changing to COMPLETED means there's one less easy handle 'alive' */
145 data->multi->num_alive--;
149 #define multistate(x,y) mstate(x,y)
151 #define multistate(x,y) mstate(x,y, __LINE__)
155 * We add one of these structs to the sockhash for a particular socket
158 struct Curl_sh_entry {
159 struct SessionHandle *easy;
161 int action; /* what action READ/WRITE this socket waits for */
162 curl_socket_t socket; /* mainly to ease debugging */
163 void *socketp; /* settable by users with curl_multi_assign() */
165 /* bits for 'action' having no bits means this socket is not expecting any
170 /* make sure this socket is present in the hash for this handle */
171 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
173 struct SessionHandle *data)
175 struct Curl_sh_entry *there =
176 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
177 struct Curl_sh_entry *check;
180 /* it is present, return fine */
183 /* not present, add it */
184 check = calloc(1, sizeof(struct Curl_sh_entry));
186 return NULL; /* major failure */
191 /* make/add new hash entry */
192 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
194 return NULL; /* major failure */
197 return check; /* things are good in sockhash land */
201 /* delete the given socket + handle from the hash */
202 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
204 struct Curl_sh_entry *there =
205 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
208 /* this socket is in the hash */
209 /* We remove the hash entry. (This'll end up in a call to
211 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
216 * free a sockhash entry
218 static void sh_freeentry(void *freethis)
220 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
226 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
228 (void) k1_len; (void) k2_len;
230 return (*((int *) k1)) == (*((int *) k2));
233 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
235 int fd = *((int *) key);
238 return (fd % (int)slots_num);
242 * sh_init() creates a new socket hash and returns the handle for it.
244 * Quote from README.multi_socket:
246 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
247 * is somewhat of a bottle neck. Its current implementation may be a bit too
248 * limiting. It simply has a fixed-size array, and on each entry in the array
249 * it has a linked list with entries. So the hash only checks which list to
250 * scan through. The code I had used so for used a list with merely 7 slots
251 * (as that is what the DNS hash uses) but with 7000 connections that would
252 * make an average of 1000 nodes in each list to run through. I upped that to
253 * 97 slots (I believe a prime is suitable) and noticed a significant speed
254 * increase. I need to reconsider the hash implementation or use a rather
255 * large default value like this. At 9000 connections I was still below 10us
259 static struct curl_hash *sh_init(int hashsize)
261 return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
268 * Called when a transfer is completed. Adds the given msg pointer to
269 * the list kept in the multi handle.
271 static CURLMcode multi_addmsg(struct Curl_multi *multi,
272 struct Curl_message *msg)
274 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
275 return CURLM_OUT_OF_MEMORY;
283 * Callback used by the llist system when a single list entry is destroyed.
285 static void multi_freeamsg(void *a, void *b)
291 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
292 int chashsize) /* connection hash */
294 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
299 multi->type = CURL_MULTI_HANDLE;
301 multi->hostcache = Curl_mk_dnscache();
302 if(!multi->hostcache)
305 multi->sockhash = sh_init(hashsize);
309 multi->conn_cache = Curl_conncache_init(chashsize);
310 if(!multi->conn_cache)
313 multi->msglist = Curl_llist_alloc(multi_freeamsg);
317 multi->pending = Curl_llist_alloc(multi_freeamsg);
321 /* allocate a new easy handle to use when closing cached connections */
322 multi->closure_handle = curl_easy_init();
323 if(!multi->closure_handle)
326 multi->closure_handle->multi = multi;
327 multi->closure_handle->state.conn_cache = multi->conn_cache;
329 multi->max_pipeline_length = 5;
331 /* -1 means it not set by user, use the default value */
332 multi->maxconnects = -1;
333 return (CURLM *) multi;
337 Curl_hash_destroy(multi->sockhash);
338 multi->sockhash = NULL;
339 Curl_hash_destroy(multi->hostcache);
340 multi->hostcache = NULL;
341 Curl_conncache_destroy(multi->conn_cache);
342 multi->conn_cache = NULL;
343 Curl_close(multi->closure_handle);
344 multi->closure_handle = NULL;
345 Curl_llist_destroy(multi->msglist, NULL);
346 Curl_llist_destroy(multi->pending, NULL);
352 CURLM *curl_multi_init(void)
354 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
355 CURL_CONNECTION_HASH_SIZE);
358 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
361 struct curl_llist *timeoutlist;
362 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
363 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
365 /* First, make some basic checks that the CURLM handle is a good handle */
366 if(!GOOD_MULTI_HANDLE(multi))
367 return CURLM_BAD_HANDLE;
369 /* Verify that we got a somewhat good easy handle too */
370 if(!GOOD_EASY_HANDLE(easy_handle))
371 return CURLM_BAD_EASY_HANDLE;
373 /* Prevent users from adding same easy handle more than once and prevent
374 adding to more than one multi stack */
376 return CURLM_ADDED_ALREADY;
378 /* Allocate and initialize timeout list for easy handle */
379 timeoutlist = Curl_llist_alloc(multi_freetimeout);
381 return CURLM_OUT_OF_MEMORY;
384 * No failure allowed in this function beyond this point. And no
385 * modification of easy nor multi handle allowed before this except for
386 * potential multi's connection cache growing which won't be undone in this
387 * function no matter what.
390 /* Make easy handle use timeout list initialized above */
391 data->state.timeoutlist = timeoutlist;
394 /* set the easy handle */
395 multistate(data, CURLM_STATE_INIT);
397 if((data->set.global_dns_cache) &&
398 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
399 /* global dns cache was requested but still isn't */
400 struct curl_hash *global = Curl_global_host_cache_init();
402 /* only do this if the global cache init works */
403 data->dns.hostcache = global;
404 data->dns.hostcachetype = HCACHE_GLOBAL;
407 /* for multi interface connections, we share DNS cache automatically if the
408 easy handle's one is currently not set. */
409 else if(!data->dns.hostcache ||
410 (data->dns.hostcachetype == HCACHE_NONE)) {
411 data->dns.hostcache = multi->hostcache;
412 data->dns.hostcachetype = HCACHE_MULTI;
415 /* Point to the multi's connection cache */
416 data->state.conn_cache = multi->conn_cache;
418 data->state.infilesize = data->set.filesize;
420 /* This adds the new entry at the 'end' of the doubly-linked circular
421 list of SessionHandle structs to try and maintain a FIFO queue so
422 the pipelined requests are in order. */
424 /* We add this new entry last in the list. */
426 data->next = NULL; /* end of the line */
428 struct SessionHandle *last = multi->easylp;
431 multi->easylp = data; /* the new last node */
434 /* first node, make both prev and next be NULL! */
437 multi->easylp = multi->easyp = data; /* both first and last */
440 /* make the SessionHandle refer back to this multi handle */
441 data->multi = multi_handle;
443 /* Set the timeout for this handle to expire really soon so that it will
444 be taken care of even when this handle is added in the midst of operation
445 when only the curl_multi_socket() API is used. During that flow, only
446 sockets that time-out or have actions will be dealt with. Since this
447 handle has no action yet, we make sure it times out to get things to
449 Curl_expire(data, 1);
451 /* increase the node-counter */
454 /* increase the alive-counter */
457 /* A somewhat crude work-around for a little glitch in update_timer() that
458 happens if the lastcall time is set to the same time when the handle is
459 removed as when the next handle is added, as then the check in
460 update_timer() that prevents calling the application multiple times with
461 the same timer infor will not trigger and then the new handle's timeout
462 will not be notified to the app.
464 The work-around is thus simply to clear the 'lastcall' variable to force
465 update_timer() to always trigger a callback to the app when a new easy
467 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
474 /* Debug-function, used like this:
476 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
478 * Enable the hash print function first by editing hash.c
480 static void debug_print_sock_hash(void *p)
482 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
484 fprintf(stderr, " [easy %p/magic %x/socket %d]",
485 (void *)sh->data, sh->data->magic, (int)sh->socket);
489 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
492 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
493 struct SessionHandle *easy = curl_handle;
494 struct SessionHandle *data = easy;
497 struct curl_llist_element *e;
499 /* First, make some basic checks that the CURLM handle is a good handle */
500 if(!GOOD_MULTI_HANDLE(multi))
501 return CURLM_BAD_HANDLE;
503 /* Verify that we got a somewhat good easy handle too */
504 if(!GOOD_EASY_HANDLE(curl_handle))
505 return CURLM_BAD_EASY_HANDLE;
507 /* Prevent users from trying to remove same easy handle more than once */
509 return CURLM_OK; /* it is already removed so let's say it is fine! */
512 premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
513 easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
516 /* If the 'state' is not INIT or COMPLETED, we might need to do something
517 nice to put the easy_handle in a good known state when this returns. */
519 /* this handle is "alive" so we need to count down the total number of
520 alive connections when this is removed */
523 if(data->easy_conn &&
524 data->mstate > CURLM_STATE_DO &&
525 data->mstate < CURLM_STATE_COMPLETED) {
526 /* If the handle is in a pipeline and has started sending off its
527 request but not received its response yet, we need to close
529 connclose(data->easy_conn, "Removed with partial response");
530 /* Set connection owner so that Curl_done() closes it.
531 We can safely do this here since connection is killed. */
532 data->easy_conn->data = easy;
533 easy_owns_conn = TRUE;
536 /* The timer must be shut down before data->multi is set to NULL,
537 else the timenode will remain in the splay tree after
538 curl_easy_cleanup is called. */
539 Curl_expire(data, 0);
541 /* destroy the timeout list that is held in the easy handle */
542 if(data->state.timeoutlist) {
543 Curl_llist_destroy(data->state.timeoutlist, NULL);
544 data->state.timeoutlist = NULL;
547 if(data->dns.hostcachetype == HCACHE_MULTI) {
548 /* stop using the multi handle's DNS cache */
549 data->dns.hostcache = NULL;
550 data->dns.hostcachetype = HCACHE_NONE;
553 if(data->easy_conn) {
555 /* we must call Curl_done() here (if we still "own it") so that we don't
556 leave a half-baked one around */
559 /* Curl_done() clears the conn->data field to lose the association
560 between the easy handle and the connection
562 Note that this ignores the return code simply because there's
563 nothing really useful to do with it anyway! */
564 (void)Curl_done(&data->easy_conn, data->result, premature);
567 /* Clear connection pipelines, if Curl_done above was not called */
568 Curl_getoff_all_pipelines(data, data->easy_conn);
571 Curl_wildcard_dtor(&data->wildcard);
573 /* as this was using a shared connection cache we clear the pointer to that
574 since we're not part of that multi handle anymore */
575 data->state.conn_cache = NULL;
577 /* change state without using multistate(), only to make singlesocket() do
579 data->mstate = CURLM_STATE_COMPLETED;
580 singlesocket(multi, easy); /* to let the application know what sockets that
581 vanish with this handle */
583 /* Remove the association between the connection and the handle */
584 if(data->easy_conn) {
585 data->easy_conn->data = NULL;
586 data->easy_conn = NULL;
589 data->multi = NULL; /* clear the association to this multi handle */
591 /* make sure there's no pending message in the queue sent from this easy
594 for(e = multi->msglist->head; e; e = e->next) {
595 struct Curl_message *msg = e->ptr;
597 if(msg->extmsg.easy_handle == easy) {
598 Curl_llist_remove(multi->msglist, e, NULL);
599 /* there can only be one from this specific handle */
604 /* make the previous node point to our next */
606 data->prev->next = data->next;
608 multi->easyp = data->next; /* point to first node */
610 /* make our next point to our previous node */
612 data->next->prev = data->prev;
614 multi->easylp = data->prev; /* point to last node */
617 We do not touch the easy handle here! */
618 multi->num_easy--; /* one less to care about now */
624 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
626 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
629 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
631 data->easy_conn = NULL;
634 static int waitconnect_getsock(struct connectdata *conn,
643 return GETSOCK_BLANK;
646 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
647 sock[s] = conn->tempsock[i];
648 rc |= GETSOCK_WRITESOCK(s++);
652 /* when we've sent a CONNECT to a proxy, we should rather wait for the
653 socket to become readable to be able to get the response headers */
654 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
655 sock[0] = conn->sock[FIRSTSOCKET];
656 rc = GETSOCK_READSOCK(0);
662 static int domore_getsock(struct connectdata *conn,
663 curl_socket_t *socks,
666 if(conn && conn->handler->domore_getsock)
667 return conn->handler->domore_getsock(conn, socks, numsocks);
668 return GETSOCK_BLANK;
671 /* returns bitmapped flags for this handle and its sockets */
672 static int multi_getsock(struct SessionHandle *data,
673 curl_socket_t *socks, /* points to numsocks number
677 /* If the pipe broke, or if there's no connection left for this easy handle,
678 then we MUST bail out now with no bitmask set. The no connection case can
679 happen when this is called from curl_multi_remove_handle() =>
680 singlesocket() => multi_getsock().
682 if(data->state.pipe_broke || !data->easy_conn)
685 if(data->mstate > CURLM_STATE_CONNECT &&
686 data->mstate < CURLM_STATE_COMPLETED) {
687 /* Set up ownership correctly */
688 data->easy_conn->data = data;
691 switch(data->mstate) {
693 #if 0 /* switch back on these cases to get the compiler to check for all enums
695 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
696 case CURLM_STATE_COMPLETED:
697 case CURLM_STATE_MSGSENT:
698 case CURLM_STATE_INIT:
699 case CURLM_STATE_CONNECT:
700 case CURLM_STATE_WAITDO:
701 case CURLM_STATE_DONE:
702 case CURLM_STATE_LAST:
703 /* this will get called with CURLM_STATE_COMPLETED when a handle is
708 case CURLM_STATE_WAITRESOLVE:
709 return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
711 case CURLM_STATE_PROTOCONNECT:
712 return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
715 case CURLM_STATE_DOING:
716 return Curl_doing_getsock(data->easy_conn, socks, numsocks);
718 case CURLM_STATE_WAITPROXYCONNECT:
719 case CURLM_STATE_WAITCONNECT:
720 return waitconnect_getsock(data->easy_conn, socks, numsocks);
722 case CURLM_STATE_DO_MORE:
723 return domore_getsock(data->easy_conn, socks, numsocks);
725 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
726 to waiting for the same as the *PERFORM
728 case CURLM_STATE_PERFORM:
729 case CURLM_STATE_WAITPERFORM:
730 return Curl_single_getsock(data->easy_conn, socks, numsocks);
735 CURLMcode curl_multi_fdset(CURLM *multi_handle,
736 fd_set *read_fd_set, fd_set *write_fd_set,
737 fd_set *exc_fd_set, int *max_fd)
739 /* Scan through all the easy handles to get the file descriptors set.
740 Some easy handles may not have connected to the remote host yet,
741 and then we must make sure that is done. */
742 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
743 struct SessionHandle *data;
745 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
748 (void)exc_fd_set; /* not used */
750 if(!GOOD_MULTI_HANDLE(multi))
751 return CURLM_BAD_HANDLE;
755 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
757 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
758 curl_socket_t s = CURL_SOCKET_BAD;
760 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
761 FD_SET(sockbunch[i], read_fd_set);
764 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
765 FD_SET(sockbunch[i], write_fd_set);
768 if(s == CURL_SOCKET_BAD)
769 /* this socket is unused, break out of loop */
772 if((int)s > this_max_fd)
773 this_max_fd = (int)s;
777 data = data->next; /* check next handle */
780 *max_fd = this_max_fd;
785 CURLMcode curl_multi_wait(CURLM *multi_handle,
786 struct curl_waitfd extra_fds[],
787 unsigned int extra_nfds,
791 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
792 struct SessionHandle *data;
793 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
796 unsigned int nfds = 0;
797 unsigned int curlfds;
798 struct pollfd *ufds = NULL;
799 long timeout_internal;
801 if(!GOOD_MULTI_HANDLE(multi))
802 return CURLM_BAD_HANDLE;
804 /* If the internally desired timeout is actually shorter than requested from
805 the outside, then use the shorter time! But only if the internal timer
806 is actually larger than -1! */
807 (void)multi_timeout(multi, &timeout_internal);
808 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
809 timeout_ms = (int)timeout_internal;
811 /* Count up how many fds we have from the multi handle */
814 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
816 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
817 curl_socket_t s = CURL_SOCKET_BAD;
819 if(bitmap & GETSOCK_READSOCK(i)) {
823 if(bitmap & GETSOCK_WRITESOCK(i)) {
827 if(s == CURL_SOCKET_BAD) {
832 data = data->next; /* check next handle */
835 curlfds = nfds; /* number of internal file descriptors */
836 nfds += extra_nfds; /* add the externally provided ones */
838 if(nfds || extra_nfds) {
839 ufds = malloc(nfds * sizeof(struct pollfd));
841 return CURLM_OUT_OF_MEMORY;
845 /* only do the second loop if we found descriptors in the first stage run
849 /* Add the curl handles to our pollfds first */
852 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
854 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
855 curl_socket_t s = CURL_SOCKET_BAD;
857 if(bitmap & GETSOCK_READSOCK(i)) {
858 ufds[nfds].fd = sockbunch[i];
859 ufds[nfds].events = POLLIN;
863 if(bitmap & GETSOCK_WRITESOCK(i)) {
864 ufds[nfds].fd = sockbunch[i];
865 ufds[nfds].events = POLLOUT;
869 if(s == CURL_SOCKET_BAD) {
874 data = data->next; /* check next handle */
878 /* Add external file descriptions from poll-like struct curl_waitfd */
879 for(i = 0; i < extra_nfds; i++) {
880 ufds[nfds].fd = extra_fds[i].fd;
881 ufds[nfds].events = 0;
882 if(extra_fds[i].events & CURL_WAIT_POLLIN)
883 ufds[nfds].events |= POLLIN;
884 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
885 ufds[nfds].events |= POLLPRI;
886 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
887 ufds[nfds].events |= POLLOUT;
893 infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
894 i = Curl_poll(ufds, nfds, timeout_ms);
898 /* copy revents results from the poll to the curl_multi_wait poll
899 struct, the bit values of the actual underlying poll() implementation
900 may not be the same as the ones in the public libcurl API! */
901 for(j = 0; j < extra_nfds; j++) {
902 unsigned short mask = 0;
903 unsigned r = ufds[curlfds + j].revents;
906 mask |= CURL_WAIT_POLLIN;
908 mask |= CURL_WAIT_POLLOUT;
910 mask |= CURL_WAIT_POLLPRI;
912 extra_fds[j].revents = mask;
925 static CURLMcode multi_runsingle(struct Curl_multi *multi,
927 struct SessionHandle *data)
929 struct Curl_message *msg = NULL;
932 bool protocol_connect = FALSE;
933 bool dophase_done = FALSE;
936 CURLcode result = CURLE_OK;
937 struct SingleRequest *k;
941 if(!GOOD_EASY_HANDLE(data))
942 return CURLM_BAD_EASY_HANDLE;
945 bool disconnect_conn = FALSE;
948 /* Handle the case when the pipe breaks, i.e., the connection
949 we're using gets cleaned up and we're left with nothing. */
950 if(data->state.pipe_broke) {
951 infof(data, "Pipe broke: handle %p, url = %s\n",
952 (void *)data, data->state.path);
954 if(data->mstate < CURLM_STATE_COMPLETED) {
955 /* Head back to the CONNECT state */
956 multistate(data, CURLM_STATE_CONNECT);
957 rc = CURLM_CALL_MULTI_PERFORM;
961 data->state.pipe_broke = FALSE;
962 data->easy_conn = NULL;
966 if(!data->easy_conn &&
967 data->mstate > CURLM_STATE_CONNECT &&
968 data->mstate < CURLM_STATE_DONE) {
969 /* In all these states, the code will blindly access 'data->easy_conn'
970 so this is precaution that it isn't NULL. And it silences static
972 failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
973 return CURLM_INTERNAL_ERROR;
976 if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
977 data->mstate < CURLM_STATE_COMPLETED)
978 /* Make sure we set the connection's current owner */
979 data->easy_conn->data = data;
981 if(data->easy_conn &&
982 (data->mstate >= CURLM_STATE_CONNECT) &&
983 (data->mstate < CURLM_STATE_COMPLETED)) {
984 /* we need to wait for the connect state as only then is the start time
985 stored, but we must not check already completed handles */
987 timeout_ms = Curl_timeleft(data, &now,
988 (data->mstate <= CURLM_STATE_WAITDO)?
992 /* Handle timed out */
993 if(data->mstate == CURLM_STATE_WAITRESOLVE)
994 failf(data, "Resolving timed out after %ld milliseconds",
995 Curl_tvdiff(now, data->progress.t_startsingle));
996 else if(data->mstate == CURLM_STATE_WAITCONNECT)
997 failf(data, "Connection timed out after %ld milliseconds",
998 Curl_tvdiff(now, data->progress.t_startsingle));
1002 failf(data, "Operation timed out after %ld milliseconds with %"
1003 CURL_FORMAT_CURL_OFF_T " out of %"
1004 CURL_FORMAT_CURL_OFF_T " bytes received",
1005 Curl_tvdiff(k->now, data->progress.t_startsingle),
1006 k->bytecount, k->size);
1009 failf(data, "Operation timed out after %ld milliseconds with %"
1010 CURL_FORMAT_CURL_OFF_T " bytes received",
1011 Curl_tvdiff(now, data->progress.t_startsingle),
1016 /* Force connection closed if the connection has indeed been used */
1017 if(data->mstate > CURLM_STATE_DO) {
1018 connclose(data->easy_conn, "Disconnected with pending data");
1019 disconnect_conn = TRUE;
1021 result = CURLE_OPERATION_TIMEDOUT;
1022 /* Skip the statemachine and go directly to error handling section. */
1023 goto statemachine_end;
1027 switch(data->mstate) {
1028 case CURLM_STATE_INIT:
1029 /* init this transfer. */
1030 result=Curl_pretransfer(data);
1033 /* after init, go CONNECT */
1034 multistate(data, CURLM_STATE_CONNECT);
1035 Curl_pgrsTime(data, TIMER_STARTOP);
1036 rc = CURLM_CALL_MULTI_PERFORM;
1040 case CURLM_STATE_CONNECT_PEND:
1041 /* We will stay here until there is a connection available. Then
1042 we try again in the CURLM_STATE_CONNECT state. */
1045 case CURLM_STATE_CONNECT:
1046 /* Connect. We want to get a connection identifier filled in. */
1047 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1048 result = Curl_connect(data, &data->easy_conn,
1049 &async, &protocol_connect);
1050 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1051 /* There was no connection available. We will go to the pending
1052 state and wait for an available connection. */
1053 multistate(data, CURLM_STATE_CONNECT_PEND);
1055 /* add this handle to the list of connect-pending handles */
1056 if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
1057 result = CURLE_OUT_OF_MEMORY;
1064 /* Add this handle to the send or pend pipeline */
1065 result = Curl_add_handle_to_pipeline(data, data->easy_conn);
1067 disconnect_conn = TRUE;
1070 /* We're now waiting for an asynchronous name lookup */
1071 multistate(data, CURLM_STATE_WAITRESOLVE);
1073 /* after the connect has been sent off, go WAITCONNECT unless the
1074 protocol connect is already done and we can go directly to
1076 rc = CURLM_CALL_MULTI_PERFORM;
1078 if(protocol_connect)
1079 multistate(data, multi->pipelining_enabled?
1080 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1082 #ifndef CURL_DISABLE_HTTP
1083 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1084 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1087 multistate(data, CURLM_STATE_WAITCONNECT);
1094 case CURLM_STATE_WAITRESOLVE:
1095 /* awaiting an asynch name resolve to complete */
1097 struct Curl_dns_entry *dns = NULL;
1098 struct connectdata *conn = data->easy_conn;
1100 /* check if we have the name resolved by now */
1102 Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
1104 dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
1107 dns->inuse++; /* we use it! */
1108 #ifdef CURLRES_ASYNCH
1109 conn->async.dns = dns;
1110 conn->async.done = TRUE;
1113 infof(data, "Hostname was found in DNS cache\n");
1117 Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1120 result = Curl_resolver_is_resolved(data->easy_conn, &dns);
1122 /* Update sockets here, because the socket(s) may have been
1123 closed and the application thus needs to be told, even if it
1124 is likely that the same socket(s) will again be used further
1125 down. If the name has not yet been resolved, it is likely
1126 that new sockets have been opened in an attempt to contact
1127 another resolver. */
1128 singlesocket(multi, data);
1131 /* Perform the next step in the connection phase, and then move on
1132 to the WAITCONNECT state */
1133 result = Curl_async_resolved(data->easy_conn, &protocol_connect);
1136 /* if Curl_async_resolved() returns failure, the connection struct
1137 is already freed and gone */
1138 data->easy_conn = NULL; /* no more connection */
1140 /* call again please so that we get the next socket setup */
1141 rc = CURLM_CALL_MULTI_PERFORM;
1142 if(protocol_connect)
1143 multistate(data, multi->pipelining_enabled?
1144 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1146 #ifndef CURL_DISABLE_HTTP
1147 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1148 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1151 multistate(data, CURLM_STATE_WAITCONNECT);
1157 /* failure detected */
1158 disconnect_conn = TRUE;
1164 #ifndef CURL_DISABLE_HTTP
1165 case CURLM_STATE_WAITPROXYCONNECT:
1166 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1167 result = Curl_http_connect(data->easy_conn, &protocol_connect);
1169 if(data->easy_conn->bits.proxy_connect_closed) {
1170 /* connect back to proxy again */
1172 rc = CURLM_CALL_MULTI_PERFORM;
1173 multistate(data, CURLM_STATE_CONNECT);
1176 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1177 multistate(data, CURLM_STATE_WAITCONNECT);
1182 case CURLM_STATE_WAITCONNECT:
1183 /* awaiting a completion of an asynch connect */
1184 result = Curl_is_connected(data->easy_conn,
1190 /* if everything is still fine we do the protocol-specific connect
1192 result = Curl_protocol_connect(data->easy_conn,
1196 if(data->easy_conn->bits.proxy_connect_closed) {
1197 /* connect back to proxy again since it was closed in a proxy CONNECT
1200 rc = CURLM_CALL_MULTI_PERFORM;
1201 multistate(data, CURLM_STATE_CONNECT);
1205 /* failure detected */
1206 /* Just break, the cleaning up is handled all in one place */
1207 disconnect_conn = TRUE;
1212 if(!protocol_connect) {
1213 /* We have a TCP connection, but 'protocol_connect' may be false
1214 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1215 connect is TRUE, we move on to STATE_DO.
1216 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1218 #ifndef CURL_DISABLE_HTTP
1219 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1220 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1223 multistate(data, CURLM_STATE_PROTOCONNECT);
1227 /* after the connect has completed, go WAITDO or DO */
1228 multistate(data, multi->pipelining_enabled?
1229 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1231 rc = CURLM_CALL_MULTI_PERFORM;
1235 case CURLM_STATE_PROTOCONNECT:
1236 /* protocol-specific connect phase */
1237 result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
1238 if(!result && protocol_connect) {
1239 /* after the connect has completed, go WAITDO or DO */
1240 multistate(data, multi->pipelining_enabled?
1241 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1242 rc = CURLM_CALL_MULTI_PERFORM;
1245 /* failure detected */
1246 Curl_posttransfer(data);
1247 Curl_done(&data->easy_conn, result, TRUE);
1248 disconnect_conn = TRUE;
1252 case CURLM_STATE_WAITDO:
1253 /* Wait for our turn to DO when we're pipelining requests */
1255 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
1256 data->easy_conn->connection_id,
1257 data->easy_conn->send_pipe->size,
1258 data->easy_conn->writechannel_inuse?"TRUE":"FALSE",
1259 isHandleAtHead(data,
1260 data->easy_conn->send_pipe)?"TRUE":"FALSE");
1262 if(!data->easy_conn->writechannel_inuse &&
1263 isHandleAtHead(data,
1264 data->easy_conn->send_pipe)) {
1265 /* Grab the channel */
1266 data->easy_conn->writechannel_inuse = TRUE;
1267 multistate(data, CURLM_STATE_DO);
1268 rc = CURLM_CALL_MULTI_PERFORM;
1272 case CURLM_STATE_DO:
1273 if(data->set.connect_only) {
1274 /* keep connection open for application to use the socket */
1275 connkeep(data->easy_conn, "CONNECT_ONLY");
1276 multistate(data, CURLM_STATE_DONE);
1278 rc = CURLM_CALL_MULTI_PERFORM;
1281 /* Perform the protocol's DO action */
1282 result = Curl_do(&data->easy_conn, &dophase_done);
1284 /* When Curl_do() returns failure, data->easy_conn might be NULL! */
1288 /* some steps needed for wildcard matching */
1289 if(data->set.wildcardmatch) {
1290 struct WildcardData *wc = &data->wildcard;
1291 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1292 /* skip some states if it is important */
1293 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1294 multistate(data, CURLM_STATE_DONE);
1295 rc = CURLM_CALL_MULTI_PERFORM;
1299 /* DO was not completed in one function call, we must continue
1301 multistate(data, CURLM_STATE_DOING);
1305 /* after DO, go DO_DONE... or DO_MORE */
1306 else if(data->easy_conn->bits.do_more) {
1307 /* we're supposed to do more, but we need to sit down, relax
1308 and wait a little while first */
1309 multistate(data, CURLM_STATE_DO_MORE);
1313 /* we're done with the DO, now DO_DONE */
1314 multistate(data, CURLM_STATE_DO_DONE);
1315 rc = CURLM_CALL_MULTI_PERFORM;
1318 else if((CURLE_SEND_ERROR == result) &&
1319 data->easy_conn->bits.reuse) {
1321 * In this situation, a connection that we were trying to use
1322 * may have unexpectedly died. If possible, send the connection
1323 * back to the CONNECT phase so we can try again.
1325 char *newurl = NULL;
1326 followtype follow=FOLLOW_NONE;
1330 drc = Curl_retry_request(data->easy_conn, &newurl);
1332 /* a failure here pretty much implies an out of memory */
1334 disconnect_conn = TRUE;
1337 retry = (newurl)?TRUE:FALSE;
1339 Curl_posttransfer(data);
1340 drc = Curl_done(&data->easy_conn, result, FALSE);
1342 /* When set to retry the connection, we must to go back to
1343 * the CONNECT state */
1345 if(!drc || (drc == CURLE_SEND_ERROR)) {
1346 follow = FOLLOW_RETRY;
1347 drc = Curl_follow(data, newurl, follow);
1349 multistate(data, CURLM_STATE_CONNECT);
1350 rc = CURLM_CALL_MULTI_PERFORM;
1360 /* done didn't return OK or SEND_ERROR */
1366 /* Have error handler disconnect conn if we can't retry */
1367 disconnect_conn = TRUE;
1372 /* failure detected */
1373 Curl_posttransfer(data);
1375 Curl_done(&data->easy_conn, result, FALSE);
1376 disconnect_conn = TRUE;
1381 case CURLM_STATE_DOING:
1382 /* we continue DOING until the DO phase is complete */
1383 result = Curl_protocol_doing(data->easy_conn,
1387 /* after DO, go DO_DONE or DO_MORE */
1388 multistate(data, data->easy_conn->bits.do_more?
1389 CURLM_STATE_DO_MORE:
1390 CURLM_STATE_DO_DONE);
1391 rc = CURLM_CALL_MULTI_PERFORM;
1392 } /* dophase_done */
1395 /* failure detected */
1396 Curl_posttransfer(data);
1397 Curl_done(&data->easy_conn, result, FALSE);
1398 disconnect_conn = TRUE;
1402 case CURLM_STATE_DO_MORE:
1404 * When we are connected, DO MORE and then go DO_DONE
1406 result = Curl_do_more(data->easy_conn, &control);
1408 /* No need to remove this handle from the send pipeline here since that
1409 is done in Curl_done() */
1412 /* if positive, advance to DO_DONE
1413 if negative, go back to DOING */
1414 multistate(data, control==1?
1415 CURLM_STATE_DO_DONE:
1417 rc = CURLM_CALL_MULTI_PERFORM;
1420 /* stay in DO_MORE */
1424 /* failure detected */
1425 Curl_posttransfer(data);
1426 Curl_done(&data->easy_conn, result, FALSE);
1427 disconnect_conn = TRUE;
1431 case CURLM_STATE_DO_DONE:
1432 /* Move ourselves from the send to recv pipeline */
1433 Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
1434 /* Check if we can move pending requests to send pipe */
1435 Curl_multi_process_pending_handles(multi);
1437 /* Only perform the transfer if there's a good socket to work with.
1438 Having both BAD is a signal to skip immediately to DONE */
1439 if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
1440 (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
1441 multistate(data, CURLM_STATE_WAITPERFORM);
1443 multistate(data, CURLM_STATE_DONE);
1444 rc = CURLM_CALL_MULTI_PERFORM;
1447 case CURLM_STATE_WAITPERFORM:
1448 /* Wait for our turn to PERFORM */
1449 if(!data->easy_conn->readchannel_inuse &&
1450 isHandleAtHead(data,
1451 data->easy_conn->recv_pipe)) {
1452 /* Grab the channel */
1453 data->easy_conn->readchannel_inuse = TRUE;
1454 multistate(data, CURLM_STATE_PERFORM);
1455 rc = CURLM_CALL_MULTI_PERFORM;
1459 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
1460 data->easy_conn->connection_id,
1461 data->easy_conn->recv_pipe->size,
1462 data->easy_conn->readchannel_inuse?"TRUE":"FALSE",
1463 isHandleAtHead(data,
1464 data->easy_conn->recv_pipe)?"TRUE":"FALSE");
1469 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1470 /* if both rates are within spec, resume transfer */
1471 if(Curl_pgrsUpdate(data->easy_conn))
1472 result = CURLE_ABORTED_BY_CALLBACK;
1474 result = Curl_speedcheck(data, now);
1476 if(( (data->set.max_send_speed == 0) ||
1477 (data->progress.ulspeed < data->set.max_send_speed )) &&
1478 ( (data->set.max_recv_speed == 0) ||
1479 (data->progress.dlspeed < data->set.max_recv_speed)))
1480 multistate(data, CURLM_STATE_PERFORM);
1483 case CURLM_STATE_PERFORM:
1485 char *newurl = NULL;
1488 /* check if over send speed */
1489 if((data->set.max_send_speed > 0) &&
1490 (data->progress.ulspeed > data->set.max_send_speed)) {
1493 multistate(data, CURLM_STATE_TOOFAST);
1495 /* calculate upload rate-limitation timeout. */
1496 buffersize = (int)(data->set.buffer_size ?
1497 data->set.buffer_size : BUFSIZE);
1498 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1499 data->progress.ulspeed, buffersize);
1500 Curl_expire_latest(data, timeout_ms);
1504 /* check if over recv speed */
1505 if((data->set.max_recv_speed > 0) &&
1506 (data->progress.dlspeed > data->set.max_recv_speed)) {
1509 multistate(data, CURLM_STATE_TOOFAST);
1511 /* Calculate download rate-limitation timeout. */
1512 buffersize = (int)(data->set.buffer_size ?
1513 data->set.buffer_size : BUFSIZE);
1514 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1515 data->progress.dlspeed, buffersize);
1516 Curl_expire_latest(data, timeout_ms);
1520 /* read/write data if it is ready to do so */
1521 result = Curl_readwrite(data->easy_conn, &done);
1525 if(!(k->keepon & KEEP_RECV)) {
1526 /* We're done receiving */
1527 data->easy_conn->readchannel_inuse = FALSE;
1530 if(!(k->keepon & KEEP_SEND)) {
1531 /* We're done sending */
1532 data->easy_conn->writechannel_inuse = FALSE;
1535 if(done || (result == CURLE_RECV_ERROR)) {
1536 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1537 * condition and the server closed the re-used connection exactly when
1538 * we wanted to use it, so figure out if that is indeed the case.
1540 CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
1542 retry = (newurl)?TRUE:FALSE;
1545 /* if we are to retry, set the result to OK and consider the
1554 * The transfer phase returned error, we mark the connection to get
1555 * closed to prevent being re-used. This is because we can't possibly
1556 * know if the connection is in a good shape or not now. Unless it is
1557 * a protocol which uses two "channels" like FTP, as then the error
1558 * happened in the data connection.
1561 if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
1562 connclose(data->easy_conn, "Transfer returned error");
1564 Curl_posttransfer(data);
1565 Curl_done(&data->easy_conn, result, FALSE);
1568 followtype follow=FOLLOW_NONE;
1570 /* call this even if the readwrite function returned error */
1571 Curl_posttransfer(data);
1573 /* we're no longer receiving */
1574 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1576 /* expire the new receiving pipeline head */
1577 if(data->easy_conn->recv_pipe->head)
1578 Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
1580 /* Check if we can move pending requests to send pipe */
1581 Curl_multi_process_pending_handles(multi);
1583 /* When we follow redirects or is set to retry the connection, we must
1584 to go back to the CONNECT state */
1585 if(data->req.newurl || retry) {
1587 /* if the URL is a follow-location and not just a retried request
1588 then figure out the URL here */
1591 newurl = data->req.newurl;
1592 data->req.newurl = NULL;
1593 follow = FOLLOW_REDIR;
1596 follow = FOLLOW_RETRY;
1597 result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1599 result = Curl_follow(data, newurl, follow);
1601 multistate(data, CURLM_STATE_CONNECT);
1602 rc = CURLM_CALL_MULTI_PERFORM;
1603 newurl = NULL; /* handed over the memory ownership to
1604 Curl_follow(), make sure we don't free() it
1610 /* after the transfer is done, go DONE */
1612 /* but first check to see if we got a location info even though we're
1613 not following redirects */
1614 if(data->req.location) {
1617 newurl = data->req.location;
1618 data->req.location = NULL;
1619 result = Curl_follow(data, newurl, FOLLOW_FAKE);
1621 newurl = NULL; /* allocation was handed over Curl_follow() */
1623 disconnect_conn = TRUE;
1626 multistate(data, CURLM_STATE_DONE);
1627 rc = CURLM_CALL_MULTI_PERFORM;
1636 case CURLM_STATE_DONE:
1637 /* this state is highly transient, so run another loop after this */
1638 rc = CURLM_CALL_MULTI_PERFORM;
1640 if(data->easy_conn) {
1643 /* Remove ourselves from the receive pipeline, if we are there. */
1644 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1645 /* Check if we can move pending requests to send pipe */
1646 Curl_multi_process_pending_handles(multi);
1648 /* post-transfer command */
1649 res = Curl_done(&data->easy_conn, result, FALSE);
1651 /* allow a previously set error code take precedence */
1656 * If there are other handles on the pipeline, Curl_done won't set
1657 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1658 * access free'd data, if the connection is free'd and the handle
1659 * removed before we perform the processing in CURLM_STATE_COMPLETED
1662 data->easy_conn = NULL;
1665 if(data->set.wildcardmatch) {
1666 if(data->wildcard.state != CURLWC_DONE) {
1667 /* if a wildcard is set and we are not ending -> lets start again
1668 with CURLM_STATE_INIT */
1669 multistate(data, CURLM_STATE_INIT);
1674 /* after we have DONE what we're supposed to do, go COMPLETED, and
1675 it doesn't matter what the Curl_done() returned! */
1676 multistate(data, CURLM_STATE_COMPLETED);
1679 case CURLM_STATE_COMPLETED:
1680 /* this is a completed transfer, it is likely to still be connected */
1682 /* This node should be delinked from the list now and we should post
1683 an information message that we are complete. */
1685 /* Important: reset the conn pointer so that we don't point to memory
1686 that could be freed anytime */
1687 data->easy_conn = NULL;
1689 Curl_expire(data, 0); /* stop all timers */
1692 case CURLM_STATE_MSGSENT:
1693 data->result = result;
1694 return CURLM_OK; /* do nothing */
1697 return CURLM_INTERNAL_ERROR;
1701 if(data->mstate < CURLM_STATE_COMPLETED) {
1704 * If an error was returned, and we aren't in completed state now,
1705 * then we go to completed and consider this transfer aborted.
1708 /* NOTE: no attempt to disconnect connections must be made
1709 in the case blocks above - cleanup happens only here */
1711 data->state.pipe_broke = FALSE;
1713 if(data->easy_conn) {
1714 /* if this has a connection, unsubscribe from the pipelines */
1715 data->easy_conn->writechannel_inuse = FALSE;
1716 data->easy_conn->readchannel_inuse = FALSE;
1717 Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
1718 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1719 /* Check if we can move pending requests to send pipe */
1720 Curl_multi_process_pending_handles(multi);
1722 if(disconnect_conn) {
1723 /* Don't attempt to send data over a connection that timed out */
1724 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
1725 /* disconnect properly */
1726 Curl_disconnect(data->easy_conn, dead_connection);
1728 /* This is where we make sure that the easy_conn pointer is reset.
1729 We don't have to do this in every case block above where a
1730 failure is detected */
1731 data->easy_conn = NULL;
1734 else if(data->mstate == CURLM_STATE_CONNECT) {
1735 /* Curl_connect() failed */
1736 (void)Curl_posttransfer(data);
1739 multistate(data, CURLM_STATE_COMPLETED);
1741 /* if there's still a connection to use, call the progress function */
1742 else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
1743 /* aborted due to progress callback return code must close the
1745 result = CURLE_ABORTED_BY_CALLBACK;
1746 connclose(data->easy_conn, "Aborted by callback");
1748 /* if not yet in DONE state, go there, otherwise COMPLETED */
1749 multistate(data, (data->mstate < CURLM_STATE_DONE)?
1750 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1751 rc = CURLM_CALL_MULTI_PERFORM;
1755 if(CURLM_STATE_COMPLETED == data->mstate) {
1756 /* now fill in the Curl_message with this info */
1759 msg->extmsg.msg = CURLMSG_DONE;
1760 msg->extmsg.easy_handle = data;
1761 msg->extmsg.data.result = result;
1763 rc = multi_addmsg(multi, msg);
1765 multistate(data, CURLM_STATE_MSGSENT);
1767 } while(rc == CURLM_CALL_MULTI_PERFORM);
1769 data->result = result;
1776 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1778 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1779 struct SessionHandle *data;
1780 CURLMcode returncode=CURLM_OK;
1781 struct Curl_tree *t;
1782 struct timeval now = Curl_tvnow();
1784 if(!GOOD_MULTI_HANDLE(multi))
1785 return CURLM_BAD_HANDLE;
1790 struct WildcardData *wc = &data->wildcard;
1791 SIGPIPE_VARIABLE(pipe_st);
1793 if(data->set.wildcardmatch) {
1795 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1797 return CURLM_OUT_OF_MEMORY;
1801 sigpipe_ignore(data, &pipe_st);
1802 result = multi_runsingle(multi, now, data);
1803 sigpipe_restore(&pipe_st);
1805 if(data->set.wildcardmatch) {
1806 /* destruct wildcard structures if it is needed */
1807 if(wc->state == CURLWC_DONE || result)
1808 Curl_wildcard_dtor(wc);
1812 returncode = result;
1814 data = data->next; /* operate on next handle */
1818 * Simply remove all expired timers from the splay since handles are dealt
1819 * with unconditionally by this function and curl_multi_timeout() requires
1820 * that already passed/handled expire times are removed from the splay.
1822 * It is important that the 'now' value is set at the entry of this function
1823 * and not for the current time as it may have ticked a little while since
1824 * then and then we risk this loop to remove timers that actually have not
1828 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1830 /* the removed may have another timeout in queue */
1831 (void)add_next_timeout(now, multi, t->payload);
1835 *running_handles = multi->num_alive;
1837 if(CURLM_OK >= returncode)
1838 update_timer(multi);
1843 static void close_all_connections(struct Curl_multi *multi)
1845 struct connectdata *conn;
1847 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1849 SIGPIPE_VARIABLE(pipe_st);
1850 conn->data = multi->closure_handle;
1852 sigpipe_ignore(conn->data, &pipe_st);
1853 /* This will remove the connection from the cache */
1854 (void)Curl_disconnect(conn, FALSE);
1855 sigpipe_restore(&pipe_st);
1857 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1861 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1863 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1864 struct SessionHandle *data;
1865 struct SessionHandle *nextdata;
1867 if(GOOD_MULTI_HANDLE(multi)) {
1868 bool restore_pipe = FALSE;
1869 SIGPIPE_VARIABLE(pipe_st);
1871 multi->type = 0; /* not good anymore */
1873 /* Close all the connections in the connection cache */
1874 close_all_connections(multi);
1876 if(multi->closure_handle) {
1877 sigpipe_ignore(multi->closure_handle, &pipe_st);
1878 restore_pipe = TRUE;
1880 multi->closure_handle->dns.hostcache = multi->hostcache;
1881 Curl_hostcache_clean(multi->closure_handle,
1882 multi->closure_handle->dns.hostcache);
1884 Curl_close(multi->closure_handle);
1887 Curl_hash_destroy(multi->sockhash);
1888 Curl_conncache_destroy(multi->conn_cache);
1889 Curl_llist_destroy(multi->msglist, NULL);
1890 Curl_llist_destroy(multi->pending, NULL);
1892 /* remove all easy handles */
1893 data = multi->easyp;
1895 nextdata=data->next;
1896 if(data->dns.hostcachetype == HCACHE_MULTI) {
1897 /* clear out the usage of the shared DNS cache */
1898 Curl_hostcache_clean(data, data->dns.hostcache);
1899 data->dns.hostcache = NULL;
1900 data->dns.hostcachetype = HCACHE_NONE;
1903 /* Clear the pointer to the connection cache */
1904 data->state.conn_cache = NULL;
1905 data->multi = NULL; /* clear the association */
1910 Curl_hash_destroy(multi->hostcache);
1912 /* Free the blacklists by setting them to NULL */
1913 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1914 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1918 sigpipe_restore(&pipe_st);
1923 return CURLM_BAD_HANDLE;
1927 * curl_multi_info_read()
1929 * This function is the primary way for a multi/multi_socket application to
1930 * figure out if a transfer has ended. We MUST make this function as fast as
1931 * possible as it will be polled frequently and we MUST NOT scan any lists in
1932 * here to figure out things. We must scale fine to thousands of handles and
1933 * beyond. The current design is fully O(1).
1936 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1938 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1939 struct Curl_message *msg;
1941 *msgs_in_queue = 0; /* default to none */
1943 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1944 /* there is one or more messages in the list */
1945 struct curl_llist_element *e;
1947 /* extract the head of the list to return */
1948 e = multi->msglist->head;
1952 /* remove the extracted entry */
1953 Curl_llist_remove(multi->msglist, e, NULL);
1955 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1957 return &msg->extmsg;
1964 * singlesocket() checks what sockets we deal with and their "action state"
1965 * and if we have a different state in any of those sockets from last time we
1966 * call the callback accordingly.
1968 static void singlesocket(struct Curl_multi *multi,
1969 struct SessionHandle *data)
1971 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1973 struct Curl_sh_entry *entry;
1976 unsigned int curraction;
1977 bool remove_sock_from_hash;
1979 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1980 socks[i] = CURL_SOCKET_BAD;
1982 /* Fill in the 'current' struct with the state as it is now: what sockets to
1983 supervise and for what actions */
1984 curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
1986 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1987 sockets we should have from now on. Detect the differences, remove no
1988 longer supervised ones and add new ones */
1990 /* walk over the sockets we got right now */
1991 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1992 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1994 int action = CURL_POLL_NONE;
1998 /* get it from the hash */
1999 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2001 if(curraction & GETSOCK_READSOCK(i))
2002 action |= CURL_POLL_IN;
2003 if(curraction & GETSOCK_WRITESOCK(i))
2004 action |= CURL_POLL_OUT;
2007 /* yeps, already present so check if it has the same action set */
2008 if(entry->action == action)
2009 /* same, continue */
2013 /* this is a socket we didn't have before, add it! */
2014 entry = sh_addentry(multi->sockhash, s, data);
2020 /* we know (entry != NULL) at this point, see the logic above */
2021 if(multi->socket_cb)
2022 multi->socket_cb(data,
2025 multi->socket_userp,
2028 entry->action = action; /* store the current action state */
2031 num = i; /* number of sockets */
2033 /* when we've walked over all the sockets we should have right now, we must
2034 make sure to detect sockets that are removed */
2035 for(i=0; i< data->numsocks; i++) {
2037 s = data->sockets[i];
2038 for(j=0; j<num; j++) {
2040 /* this is still supervised */
2041 s = CURL_SOCKET_BAD;
2045 if(s != CURL_SOCKET_BAD) {
2047 /* this socket has been removed. Tell the app to remove it */
2048 remove_sock_from_hash = TRUE;
2050 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2052 /* check if the socket to be removed serves a connection which has
2053 other easy-s in a pipeline. In this case the socket should not be
2055 struct connectdata *easy_conn = data->easy_conn;
2057 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2058 /* the handle should not be removed from the pipe yet */
2059 remove_sock_from_hash = FALSE;
2061 /* Update the sockhash entry to instead point to the next in line
2062 for the recv_pipe, or the first (in case this particular easy
2064 if(entry->easy == data) {
2065 if(isHandleAtHead(data, easy_conn->recv_pipe))
2066 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2068 entry->easy = easy_conn->recv_pipe->head->ptr;
2071 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2072 /* the handle should not be removed from the pipe yet */
2073 remove_sock_from_hash = FALSE;
2075 /* Update the sockhash entry to instead point to the next in line
2076 for the send_pipe, or the first (in case this particular easy
2078 if(entry->easy == data) {
2079 if(isHandleAtHead(data, easy_conn->send_pipe))
2080 entry->easy = easy_conn->send_pipe->head->next->ptr;
2082 entry->easy = easy_conn->send_pipe->head->ptr;
2085 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2086 when action will be asked on the socket (see multi_socket()), the
2087 head of the correct pipe will be taken according to the
2092 /* just a precaution, this socket really SHOULD be in the hash already
2093 but in case it isn't, we don't have to tell the app to remove it
2094 either since it never got to know about it */
2095 remove_sock_from_hash = FALSE;
2097 if(remove_sock_from_hash) {
2098 /* in this case 'entry' is always non-NULL */
2099 if(multi->socket_cb)
2100 multi->socket_cb(data,
2103 multi->socket_userp,
2105 sh_delentry(multi->sockhash, s);
2111 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2112 data->numsocks = num;
2116 * Curl_multi_closed()
2118 * Used by the connect code to tell the multi_socket code that one of the
2119 * sockets we were using is about to be closed. This function will then
2120 * remove it from the sockethash for this handle to make the multi_socket API
2121 * behave properly, especially for the case when libcurl will create another
2122 * socket again and it gets the same file descriptor number.
2125 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2127 struct Curl_multi *multi = conn->data->multi;
2129 /* this is set if this connection is part of a handle that is added to
2130 a multi handle, and only then this is necessary */
2131 struct Curl_sh_entry *entry =
2132 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2135 if(multi->socket_cb)
2136 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2137 multi->socket_userp,
2140 /* now remove it from the socket hash */
2141 sh_delentry(multi->sockhash, s);
2149 * add_next_timeout()
2151 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2152 * when it has just been removed from the splay tree because the timeout has
2153 * expired. This function is then to advance in the list to pick the next
2154 * timeout to use (skip the already expired ones) and add this node back to
2155 * the splay tree again.
2157 * The splay tree only has each sessionhandle as a single node and the nearest
2158 * timeout is used to sort it on.
2160 static CURLMcode add_next_timeout(struct timeval now,
2161 struct Curl_multi *multi,
2162 struct SessionHandle *d)
2164 struct timeval *tv = &d->state.expiretime;
2165 struct curl_llist *list = d->state.timeoutlist;
2166 struct curl_llist_element *e;
2168 /* move over the timeout list for this specific handle and remove all
2169 timeouts that are now passed tense and store the next pending
2171 for(e = list->head; e; ) {
2172 struct curl_llist_element *n = e->next;
2173 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2175 /* remove outdated entry */
2176 Curl_llist_remove(list, e, NULL);
2178 /* the list is sorted so get out on the first mismatch */
2184 /* clear the expire times within the handles that we remove from the
2190 /* copy the first entry to 'tv' */
2191 memcpy(tv, e->ptr, sizeof(*tv));
2193 /* remove first entry from list */
2194 Curl_llist_remove(list, e, NULL);
2196 /* insert this node again into the splay */
2197 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2198 &d->state.timenode);
2203 static CURLMcode multi_socket(struct Curl_multi *multi,
2207 int *running_handles)
2209 CURLMcode result = CURLM_OK;
2210 struct SessionHandle *data = NULL;
2211 struct Curl_tree *t;
2212 struct timeval now = Curl_tvnow();
2215 /* *perform() deals with running_handles on its own */
2216 result = curl_multi_perform(multi, running_handles);
2218 /* walk through each easy handle and do the socket state change magic
2220 if(result != CURLM_BAD_HANDLE) {
2223 singlesocket(multi, data);
2228 /* or should we fall-through and do the timer-based stuff? */
2231 else if(s != CURL_SOCKET_TIMEOUT) {
2233 struct Curl_sh_entry *entry =
2234 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2237 /* Unmatched socket, we can't act on it but we ignore this fact. In
2238 real-world tests it has been proved that libevent can in fact give
2239 the application actions even though the socket was just previously
2240 asked to get removed, so thus we better survive stray socket actions
2241 and just move on. */
2244 SIGPIPE_VARIABLE(pipe_st);
2248 if(data->magic != CURLEASY_MAGIC_NUMBER)
2249 /* bad bad bad bad bad bad bad */
2250 return CURLM_INTERNAL_ERROR;
2252 /* If the pipeline is enabled, take the handle which is in the head of
2253 the pipeline. If we should write into the socket, take the send_pipe
2254 head. If we should read from the socket, take the recv_pipe head. */
2255 if(data->easy_conn) {
2256 if((ev_bitmask & CURL_POLL_OUT) &&
2257 data->easy_conn->send_pipe &&
2258 data->easy_conn->send_pipe->head)
2259 data = data->easy_conn->send_pipe->head->ptr;
2260 else if((ev_bitmask & CURL_POLL_IN) &&
2261 data->easy_conn->recv_pipe &&
2262 data->easy_conn->recv_pipe->head)
2263 data = data->easy_conn->recv_pipe->head->ptr;
2266 if(data->easy_conn &&
2267 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2268 /* set socket event bitmask if they're not locked */
2269 data->easy_conn->cselect_bits = ev_bitmask;
2271 sigpipe_ignore(data, &pipe_st);
2272 result = multi_runsingle(multi, now, data);
2273 sigpipe_restore(&pipe_st);
2275 if(data->easy_conn &&
2276 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2277 /* clear the bitmask only if not locked */
2278 data->easy_conn->cselect_bits = 0;
2280 if(CURLM_OK >= result)
2281 /* get the socket(s) and check if the state has been changed since
2283 singlesocket(multi, data);
2285 /* Now we fall-through and do the timer-based stuff, since we don't want
2286 to force the user to have to deal with timeouts as long as at least
2287 one connection in fact has traffic. */
2289 data = NULL; /* set data to NULL again to avoid calling
2290 multi_runsingle() in case there's no need to */
2291 now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
2292 may have taken some time */
2296 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
2297 update_timer() to trigger a callback to the app again even if the same
2298 timeout is still the one to run after this call. That handles the case
2299 when the application asks libcurl to run the timeout prematurely. */
2300 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
2304 * The loop following here will go on as long as there are expire-times left
2305 * to process in the splay and 'data' will be re-assigned for every expired
2306 * handle we deal with.
2309 /* the first loop lap 'data' can be NULL */
2311 SIGPIPE_VARIABLE(pipe_st);
2313 sigpipe_ignore(data, &pipe_st);
2314 result = multi_runsingle(multi, now, data);
2315 sigpipe_restore(&pipe_st);
2317 if(CURLM_OK >= result)
2318 /* get the socket(s) and check if the state has been changed since
2320 singlesocket(multi, data);
2323 /* Check if there's one (more) expired timer to deal with! This function
2324 extracts a matching node if there is one */
2326 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2328 data = t->payload; /* assign this for next loop */
2329 (void)add_next_timeout(now, multi, t->payload);
2334 *running_handles = multi->num_alive;
2338 #undef curl_multi_setopt
2339 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2340 CURLMoption option, ...)
2342 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2343 CURLMcode res = CURLM_OK;
2346 if(!GOOD_MULTI_HANDLE(multi))
2347 return CURLM_BAD_HANDLE;
2349 va_start(param, option);
2352 case CURLMOPT_SOCKETFUNCTION:
2353 multi->socket_cb = va_arg(param, curl_socket_callback);
2355 case CURLMOPT_SOCKETDATA:
2356 multi->socket_userp = va_arg(param, void *);
2358 case CURLMOPT_PIPELINING:
2359 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2361 case CURLMOPT_TIMERFUNCTION:
2362 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2364 case CURLMOPT_TIMERDATA:
2365 multi->timer_userp = va_arg(param, void *);
2367 case CURLMOPT_MAXCONNECTS:
2368 multi->maxconnects = va_arg(param, long);
2370 case CURLMOPT_MAX_HOST_CONNECTIONS:
2371 multi->max_host_connections = va_arg(param, long);
2373 case CURLMOPT_MAX_PIPELINE_LENGTH:
2374 multi->max_pipeline_length = va_arg(param, long);
2376 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2377 multi->content_length_penalty_size = va_arg(param, long);
2379 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2380 multi->chunk_length_penalty_size = va_arg(param, long);
2382 case CURLMOPT_PIPELINING_SITE_BL:
2383 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2384 &multi->pipelining_site_bl);
2386 case CURLMOPT_PIPELINING_SERVER_BL:
2387 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2388 &multi->pipelining_server_bl);
2390 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2391 multi->max_total_connections = va_arg(param, long);
2394 res = CURLM_UNKNOWN_OPTION;
2401 /* we define curl_multi_socket() in the public multi.h header */
2402 #undef curl_multi_socket
2404 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2405 int *running_handles)
2407 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2408 0, running_handles);
2409 if(CURLM_OK >= result)
2410 update_timer((struct Curl_multi *)multi_handle);
2414 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2415 int ev_bitmask, int *running_handles)
2417 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2418 ev_bitmask, running_handles);
2419 if(CURLM_OK >= result)
2420 update_timer((struct Curl_multi *)multi_handle);
2424 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2427 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2428 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2429 if(CURLM_OK >= result)
2430 update_timer((struct Curl_multi *)multi_handle);
2434 static CURLMcode multi_timeout(struct Curl_multi *multi,
2437 static struct timeval tv_zero = {0,0};
2439 if(multi->timetree) {
2440 /* we have a tree of expire times */
2441 struct timeval now = Curl_tvnow();
2443 /* splay the lowest to the bottom */
2444 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2446 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2447 /* some time left before expiration */
2448 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2451 * Since we only provide millisecond resolution on the returned value
2452 * and the diff might be less than one millisecond here, we don't
2453 * return zero as that may cause short bursts of busyloops on fast
2454 * processors while the diff is still present but less than one
2455 * millisecond! instead we return 1 until the time is ripe.
2460 /* 0 means immediately */
2469 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2472 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2474 /* First, make some basic checks that the CURLM handle is a good handle */
2475 if(!GOOD_MULTI_HANDLE(multi))
2476 return CURLM_BAD_HANDLE;
2478 return multi_timeout(multi, timeout_ms);
2482 * Tell the application it should update its timers, if it subscribes to the
2483 * update timer callback.
2485 static int update_timer(struct Curl_multi *multi)
2489 if(!multi->timer_cb)
2491 if(multi_timeout(multi, &timeout_ms)) {
2494 if(timeout_ms < 0) {
2495 static const struct timeval none={0,0};
2496 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2497 multi->timer_lastcall = none;
2498 /* there's no timeout now but there was one previously, tell the app to
2500 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2505 /* When multi_timeout() is done, multi->timetree points to the node with the
2506 * timeout we got the (relative) time-out time for. We can thus easily check
2507 * if this is the same (fixed) time as we got in a previous call and then
2508 * avoid calling the callback again. */
2509 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2512 multi->timer_lastcall = multi->timetree->key;
2514 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2517 static bool isHandleAtHead(struct SessionHandle *handle,
2518 struct curl_llist *pipeline)
2520 struct curl_llist_element *curr = pipeline->head;
2522 return (curr->ptr == handle) ? TRUE : FALSE;
2528 * multi_freetimeout()
2530 * Callback used by the llist system when a single timeout list entry is
2533 static void multi_freetimeout(void *user, void *entryptr)
2537 /* the entry was plain malloc()'ed */
2542 * multi_addtimeout()
2544 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2545 * of list is always the timeout nearest in time.
2549 multi_addtimeout(struct curl_llist *timeoutlist,
2550 struct timeval *stamp)
2552 struct curl_llist_element *e;
2553 struct timeval *timedup;
2554 struct curl_llist_element *prev = NULL;
2556 timedup = malloc(sizeof(*timedup));
2558 return CURLM_OUT_OF_MEMORY;
2560 /* copy the timestamp */
2561 memcpy(timedup, stamp, sizeof(*timedup));
2563 if(Curl_llist_count(timeoutlist)) {
2564 /* find the correct spot in the list */
2565 for(e = timeoutlist->head; e; e = e->next) {
2566 struct timeval *checktime = e->ptr;
2567 long diff = curlx_tvdiff(*checktime, *timedup);
2575 this is the first timeout on the list */
2577 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2579 return CURLM_OUT_OF_MEMORY;
2588 * given a number of milliseconds from now to use to set the 'act before
2589 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2591 * Note that the timeout will be added to a queue of timeouts if it defines a
2592 * moment in time that is later than the current head of queue.
2594 * Pass zero to clear all timeout values for this handle.
2596 void Curl_expire(struct SessionHandle *data, long milli)
2598 struct Curl_multi *multi = data->multi;
2599 struct timeval *nowp = &data->state.expiretime;
2602 /* this is only interesting while there is still an associated multi struct
2608 /* No timeout, clear the time data. */
2609 if(nowp->tv_sec || nowp->tv_usec) {
2610 /* Since this is an cleared time, we must remove the previous entry from
2612 struct curl_llist *list = data->state.timeoutlist;
2614 rc = Curl_splayremovebyaddr(multi->timetree,
2615 &data->state.timenode,
2618 infof(data, "Internal error clearing splay node = %d\n", rc);
2620 /* flush the timeout list too */
2621 while(list->size > 0)
2622 Curl_llist_remove(list, list->tail, NULL);
2625 infof(data, "Expire cleared\n");
2635 set.tv_sec += milli/1000;
2636 set.tv_usec += (milli%1000)*1000;
2638 if(set.tv_usec >= 1000000) {
2640 set.tv_usec -= 1000000;
2643 if(nowp->tv_sec || nowp->tv_usec) {
2644 /* This means that the struct is added as a node in the splay tree.
2645 Compare if the new time is earlier, and only remove-old/add-new if it
2647 long diff = curlx_tvdiff(set, *nowp);
2649 /* the new expire time was later so just add it to the queue
2651 multi_addtimeout(data->state.timeoutlist, &set);
2655 /* the new time is newer than the presently set one, so add the current
2656 to the queue and update the head */
2657 multi_addtimeout(data->state.timeoutlist, nowp);
2659 /* Since this is an updated time, we must remove the previous entry from
2660 the splay tree first and then re-add the new value */
2661 rc = Curl_splayremovebyaddr(multi->timetree,
2662 &data->state.timenode,
2665 infof(data, "Internal error removing splay node = %d\n", rc);
2669 data->state.timenode.payload = data;
2670 multi->timetree = Curl_splayinsert(*nowp,
2672 &data->state.timenode);
2675 Curl_splayprint(multi->timetree, 0, TRUE);
2680 * Curl_expire_latest()
2682 * This is like Curl_expire() but will only add a timeout node to the list of
2683 * timers if there is no timeout that will expire before the given time.
2685 * Use this function if the code logic risks calling this function many times
2686 * or if there's no particular conditional wait in the code for this specific
2687 * time-out period to expire.
2690 void Curl_expire_latest(struct SessionHandle *data, long milli)
2692 struct timeval *expire = &data->state.expiretime;
2697 set.tv_sec += milli / 1000;
2698 set.tv_usec += (milli % 1000) * 1000;
2700 if(set.tv_usec >= 1000000) {
2702 set.tv_usec -= 1000000;
2705 if(expire->tv_sec || expire->tv_usec) {
2706 /* This means that the struct is added as a node in the splay tree.
2707 Compare if the new time is earlier, and only remove-old/add-new if it
2709 long diff = curlx_tvdiff(set, *expire);
2711 /* the new expire time was later than the top time, so just skip this */
2715 /* Just add the timeout like normal */
2716 Curl_expire(data, milli);
2719 CURLMcode curl_multi_assign(CURLM *multi_handle,
2720 curl_socket_t s, void *hashp)
2722 struct Curl_sh_entry *there = NULL;
2723 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2725 if(s != CURL_SOCKET_BAD)
2726 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2729 return CURLM_BAD_SOCKET;
2731 there->socketp = hashp;
2736 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2738 return multi ? multi->max_host_connections : 0;
2741 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2743 return multi ? multi->max_total_connections : 0;
2746 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2748 return multi ? multi->max_pipeline_length : 0;
2751 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2753 return multi ? multi->content_length_penalty_size : 0;
2756 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2758 return multi ? multi->chunk_length_penalty_size : 0;
2761 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2763 return multi->pipelining_site_bl;
2766 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2768 return multi->pipelining_server_bl;
2771 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2773 struct curl_llist_element *e = multi->pending->head;
2776 struct SessionHandle *data = e->ptr;
2777 struct curl_llist_element *next = e->next;
2779 if(data->mstate == CURLM_STATE_CONNECT_PEND) {
2780 multistate(data, CURLM_STATE_CONNECT);
2782 /* Remove this node from the list */
2783 Curl_llist_remove(multi->pending, e, NULL);
2785 /* Make sure that the handle will be processed soonish. */
2786 Curl_expire_latest(data, 1);
2789 e = next; /* operate on next handle */
2794 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2796 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2797 struct SessionHandle *data;
2799 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2800 multi->num_easy, multi->num_alive);
2801 for(data=multi->easyp; data; data = data->next) {
2802 if(data->mstate < CURLM_STATE_COMPLETED) {
2803 /* only display handles that are not completed */
2804 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2806 statename[data->mstate], data->numsocks);
2807 for(i=0; i < data->numsocks; i++) {
2808 curl_socket_t s = data->sockets[i];
2809 struct Curl_sh_entry *entry =
2810 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2812 fprintf(stderr, "%d ", (int)s);
2814 fprintf(stderr, "INTERNAL CONFUSION\n");
2817 fprintf(stderr, "[%s %s] ",
2818 entry->action&CURL_POLL_IN?"RECVING":"",
2819 entry->action&CURL_POLL_OUT?"SENDING":"");
2822 fprintf(stderr, "\n");