1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #include <curl/curl.h>
39 #include "speedcheck.h"
40 #include "conncache.h"
42 #include "multihandle.h"
45 #define _MPRINTF_REPLACE /* use our functions only */
46 #include <curl/mprintf.h>
48 #include "curl_memory.h"
49 /* The last #include file should be: */
53 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
54 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
55 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
57 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
58 #define CURL_SOCKET_HASH_TABLE_SIZE 911
61 #define CURL_CONNECTION_HASH_SIZE 97
63 #define CURL_MULTI_HANDLE 0x000bab1e
65 #define GOOD_MULTI_HANDLE(x) \
66 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
67 #define GOOD_EASY_HANDLE(x) \
68 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
70 static void singlesocket(struct Curl_multi *multi,
71 struct Curl_one_easy *easy);
72 static int update_timer(struct Curl_multi *multi);
74 static bool isHandleAtHead(struct SessionHandle *handle,
75 struct curl_llist *pipeline);
76 static CURLMcode add_next_timeout(struct timeval now,
77 struct Curl_multi *multi,
78 struct SessionHandle *d);
79 static CURLMcode multi_timeout(struct Curl_multi *multi,
83 static const char * const statename[]={
105 static void multi_freetimeout(void *a, void *b);
107 /* always use this function to change state, to make debugging easier */
108 static void mstate(struct Curl_one_easy *easy, CURLMstate state
115 long connection_id = -5000;
117 CURLMstate oldstate = easy->mstate;
119 if(oldstate == state)
120 /* don't bother when the new state is the same as the old state */
123 easy->mstate = state;
126 if(easy->mstate >= CURLM_STATE_CONNECT_PEND &&
127 easy->mstate < CURLM_STATE_COMPLETED) {
129 connection_id = easy->easy_conn->connection_id;
132 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
133 statename[oldstate], statename[easy->mstate],
134 (void *)easy, lineno, connection_id);
137 if(state == CURLM_STATE_COMPLETED)
138 /* changing to COMPLETED means there's one less easy handle 'alive' */
139 easy->multi->num_alive--;
143 #define multistate(x,y) mstate(x,y)
145 #define multistate(x,y) mstate(x,y, __LINE__)
149 * We add one of these structs to the sockhash for a particular socket
152 struct Curl_sh_entry {
153 struct SessionHandle *easy;
155 int action; /* what action READ/WRITE this socket waits for */
156 curl_socket_t socket; /* mainly to ease debugging */
157 void *socketp; /* settable by users with curl_multi_assign() */
159 /* bits for 'action' having no bits means this socket is not expecting any
164 /* make sure this socket is present in the hash for this handle */
165 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
167 struct SessionHandle *data)
169 struct Curl_sh_entry *there =
170 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
171 struct Curl_sh_entry *check;
174 /* it is present, return fine */
177 /* not present, add it */
178 check = calloc(1, sizeof(struct Curl_sh_entry));
180 return NULL; /* major failure */
184 /* make/add new hash entry */
185 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
187 return NULL; /* major failure */
190 return check; /* things are good in sockhash land */
194 /* delete the given socket + handle from the hash */
195 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
197 struct Curl_sh_entry *there =
198 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
201 /* this socket is in the hash */
202 /* We remove the hash entry. (This'll end up in a call to
204 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
209 * free a sockhash entry
211 static void sh_freeentry(void *freethis)
213 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
219 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
221 (void) k1_len; (void) k2_len;
223 return (*((int *) k1)) == (*((int *) k2));
226 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
228 int fd = *((int *) key);
231 return (fd % (int)slots_num);
235 * sh_init() creates a new socket hash and returns the handle for it.
237 * Quote from README.multi_socket:
239 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
240 * is somewhat of a bottle neck. Its current implementation may be a bit too
241 * limiting. It simply has a fixed-size array, and on each entry in the array
242 * it has a linked list with entries. So the hash only checks which list to
243 * scan through. The code I had used so for used a list with merely 7 slots
244 * (as that is what the DNS hash uses) but with 7000 connections that would
245 * make an average of 1000 nodes in each list to run through. I upped that to
246 * 97 slots (I believe a prime is suitable) and noticed a significant speed
247 * increase. I need to reconsider the hash implementation or use a rather
248 * large default value like this. At 9000 connections I was still below 10us
252 static struct curl_hash *sh_init(int hashsize)
254 return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
261 * Called when a transfer is completed. Adds the given msg pointer to
262 * the list kept in the multi handle.
264 static CURLMcode multi_addmsg(struct Curl_multi *multi,
265 struct Curl_message *msg)
267 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
268 return CURLM_OUT_OF_MEMORY;
276 * Callback used by the llist system when a single list entry is destroyed.
278 static void multi_freeamsg(void *a, void *b)
284 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
285 int chashsize) /* connection hash */
287 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
292 multi->type = CURL_MULTI_HANDLE;
294 multi->hostcache = Curl_mk_dnscache();
295 if(!multi->hostcache)
298 multi->sockhash = sh_init(hashsize);
302 multi->conn_cache = Curl_conncache_init(chashsize);
303 if(!multi->conn_cache)
306 multi->msglist = Curl_llist_alloc(multi_freeamsg);
310 multi->max_pipeline_length = 5;
311 return (CURLM *) multi;
315 Curl_hash_destroy(multi->sockhash);
316 multi->sockhash = NULL;
317 Curl_hash_destroy(multi->hostcache);
318 multi->hostcache = NULL;
319 Curl_conncache_destroy(multi->conn_cache);
320 multi->conn_cache = NULL;
326 CURLM *curl_multi_init(void)
328 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
329 CURL_CONNECTION_HASH_SIZE);
333 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
336 struct curl_llist *timeoutlist;
337 struct Curl_one_easy *easy;
338 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
339 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
340 struct SessionHandle *new_closure = NULL;
341 struct curl_hash *hostcache = NULL;
343 /* First, make some basic checks that the CURLM handle is a good handle */
344 if(!GOOD_MULTI_HANDLE(multi))
345 return CURLM_BAD_HANDLE;
347 /* Verify that we got a somewhat good easy handle too */
348 if(!GOOD_EASY_HANDLE(easy_handle))
349 return CURLM_BAD_EASY_HANDLE;
351 /* Prevent users from adding same easy handle more than
352 once and prevent adding to more than one multi stack */
354 /* possibly we should create a new unique error code for this condition */
355 return CURLM_BAD_EASY_HANDLE;
357 /* Allocate and initialize timeout list for easy handle */
358 timeoutlist = Curl_llist_alloc(multi_freetimeout);
360 return CURLM_OUT_OF_MEMORY;
364 /* In case multi handle has no hostcache yet, allocate one */
365 if(!multi->hostcache) {
366 hostcache = Curl_mk_dnscache();
369 Curl_llist_destroy(timeoutlist, NULL);
370 return CURLM_OUT_OF_MEMORY;
374 /* In case multi handle has no closure_handle yet, allocate
375 a new easy handle to use when closing cached connections */
376 if(!multi->closure_handle) {
377 new_closure = (struct SessionHandle *)curl_easy_init();
379 Curl_hash_destroy(hostcache);
381 Curl_llist_destroy(timeoutlist, NULL);
382 return CURLM_OUT_OF_MEMORY;
387 ** No failure allowed in this function beyond this point. And
388 ** no modification of easy nor multi handle allowed before this
389 ** except for potential multi's connection cache growing which
390 ** won't be undone in this function no matter what.
393 /* In case a new closure handle has been initialized above, it
394 is associated now with the multi handle which lacked one. */
396 multi->closure_handle = new_closure;
397 Curl_easy_addmulti(multi->closure_handle, multi_handle);
398 multi->closure_handle->state.conn_cache = multi->conn_cache;
401 /* In case hostcache has been allocated above,
402 it is associated now with the multi handle. */
404 multi->hostcache = hostcache;
406 /* Make easy handle use timeout list initialized above */
407 data->state.timeoutlist = timeoutlist;
410 /* set the easy handle */
411 multistate(easy, CURLM_STATE_INIT);
413 /* set the back pointer to one_easy to assist in removal */
414 easy->multi_pos = easy;
416 /* for multi interface connections, we share DNS cache automatically if the
417 easy handle's one is currently not set. */
418 if(!easy->dns.hostcache ||
419 (easy->dns.hostcachetype == HCACHE_NONE)) {
420 easy->dns.hostcache = multi->hostcache;
421 easy->dns.hostcachetype = HCACHE_MULTI;
424 /* Point to the multi's connection cache */
425 easy->state.conn_cache = multi->conn_cache;
427 /* This adds the new entry at the 'end' of the doubly-linked circular
428 list of Curl_one_easy structs to try and maintain a FIFO queue so
429 the pipelined requests are in order. */
431 /* We add this new entry last in the list. */
433 easy->next = NULL; /* end of the line */
435 struct Curl_one_easy *last = multi->easylp;
438 multi->easylp = easy; /* the new last node */
441 /* first node, make both prev and next be NULL! */
444 multi->easylp = multi->easyp = easy; /* both first and last */
447 /* make the SessionHandle refer back to this multi handle */
448 Curl_easy_addmulti(easy_handle, multi_handle);
450 /* make the SessionHandle struct refer back to this struct */
451 easy->set.one_easy = easy;
453 /* Set the timeout for this handle to expire really soon so that it will
454 be taken care of even when this handle is added in the midst of operation
455 when only the curl_multi_socket() API is used. During that flow, only
456 sockets that time-out or have actions will be dealt with. Since this
457 handle has no action yet, we make sure it times out to get things to
459 Curl_expire(easy, 1);
461 /* increase the node-counter */
464 /* increase the alive-counter */
467 /* A somewhat crude work-around for a little glitch in update_timer() that
468 happens if the lastcall time is set to the same time when the handle is
469 removed as when the next handle is added, as then the check in
470 update_timer() that prevents calling the application multiple times with
471 the same timer infor will not trigger and then the new handle's timeout
472 will not be notified to the app.
474 The work-around is thus simply to clear the 'lastcall' variable to force
475 update_timer() to always trigger a callback to the app when a new easy
477 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
484 /* Debug-function, used like this:
486 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
488 * Enable the hash print function first by editing hash.c
490 static void debug_print_sock_hash(void *p)
492 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
494 fprintf(stderr, " [easy %p/magic %x/socket %d]",
495 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
499 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
502 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
503 struct Curl_one_easy *easy;
504 struct SessionHandle *data = curl_handle;
506 /* First, make some basic checks that the CURLM handle is a good handle */
507 if(!GOOD_MULTI_HANDLE(multi))
508 return CURLM_BAD_HANDLE;
510 /* Verify that we got a somewhat good easy handle too */
511 if(!GOOD_EASY_HANDLE(curl_handle))
512 return CURLM_BAD_EASY_HANDLE;
514 /* pick-up from the 'curl_handle' the kept position in the list */
515 easy = data->multi_pos;
518 bool premature = (easy->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
519 bool easy_owns_conn = (easy->easy_conn &&
520 (easy->easy_conn->data == easy)) ?
523 /* If the 'state' is not INIT or COMPLETED, we might need to do something
524 nice to put the easy_handle in a good known state when this returns. */
526 /* this handle is "alive" so we need to count down the total number of
527 alive connections when this is removed */
530 if(easy->easy_conn &&
531 (easy->easy_conn->send_pipe->size +
532 easy->easy_conn->recv_pipe->size > 1) &&
533 easy->mstate > CURLM_STATE_WAITDO &&
534 easy->mstate < CURLM_STATE_COMPLETED) {
535 /* If the handle is in a pipeline and has started sending off its
536 request but not received its response yet, we need to close
538 easy->easy_conn->bits.close = TRUE;
539 /* Set connection owner so that Curl_done() closes it.
540 We can sefely do this here since connection is killed. */
541 easy->easy_conn->data = easy;
544 /* The timer must be shut down before easy->multi is set to NULL,
545 else the timenode will remain in the splay tree after
546 curl_easy_cleanup is called. */
547 Curl_expire(easy, 0);
549 /* destroy the timeout list that is held in the easy handle */
550 if(data->state.timeoutlist) {
551 Curl_llist_destroy(data->state.timeoutlist, NULL);
552 data->state.timeoutlist = NULL;
555 if(easy->dns.hostcachetype == HCACHE_MULTI) {
556 /* stop using the multi handle's DNS cache */
557 easy->dns.hostcache = NULL;
558 easy->dns.hostcachetype = HCACHE_NONE;
561 if(easy->easy_conn) {
563 /* we must call Curl_done() here (if we still "own it") so that we don't
564 leave a half-baked one around */
567 /* Curl_done() clears the conn->data field to lose the association
568 between the easy handle and the connection
570 Note that this ignores the return code simply because there's
571 nothing really useful to do with it anyway! */
572 (void)Curl_done(&easy->easy_conn, easy->result, premature);
575 /* Clear connection pipelines, if Curl_done above was not called */
576 Curl_getoff_all_pipelines(easy, easy->easy_conn);
579 /* as this was using a shared connection cache we clear the pointer
580 to that since we're not part of that multi handle anymore */
581 easy->state.conn_cache = NULL;
583 /* change state without using multistate(), only to make singlesocket() do
585 easy->mstate = CURLM_STATE_COMPLETED;
586 singlesocket(multi, easy); /* to let the application know what sockets
587 that vanish with this handle */
589 /* Remove the association between the connection and the handle */
590 if(easy->easy_conn) {
591 easy->easy_conn->data = NULL;
592 easy->easy_conn = NULL;
595 Curl_easy_addmulti(easy, NULL); /* clear the association
596 to this multi handle */
599 /* make sure there's no pending message in the queue sent from this easy
601 struct curl_llist_element *e;
603 for(e = multi->msglist->head; e; e = e->next) {
604 struct Curl_message *msg = e->ptr;
606 if(msg->extmsg.easy_handle == easy) {
607 Curl_llist_remove(multi->msglist, e, NULL);
608 /* there can only be one from this specific handle */
614 /* make the previous node point to our next */
616 easy->prev->next = easy->next;
618 multi->easyp = easy->next; /* point to first node */
620 /* make our next point to our previous node */
622 easy->next->prev = easy->prev;
624 multi->easylp = easy->prev; /* point to last node */
626 easy->set.one_easy = NULL; /* detached */
628 /* Null the position in the controlling structure */
629 easy->multi_pos = NULL;
632 We do not touch the easy handle here! */
634 multi->num_easy--; /* one less to care about now */
640 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
643 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
645 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
648 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
650 struct Curl_one_easy *one_easy = data->set.one_easy;
653 one_easy->easy_conn = NULL;
656 static int waitconnect_getsock(struct connectdata *conn,
661 return GETSOCK_BLANK;
663 sock[0] = conn->sock[FIRSTSOCKET];
665 /* when we've sent a CONNECT to a proxy, we should rather wait for the
666 socket to become readable to be able to get the response headers */
667 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
668 return GETSOCK_READSOCK(0);
670 return GETSOCK_WRITESOCK(0);
673 static int domore_getsock(struct connectdata *conn,
674 curl_socket_t *socks,
677 if(conn && conn->handler->domore_getsock)
678 return conn->handler->domore_getsock(conn, socks, numsocks);
679 return GETSOCK_BLANK;
682 /* returns bitmapped flags for this handle and its sockets */
683 static int multi_getsock(struct Curl_one_easy *easy,
684 curl_socket_t *socks, /* points to numsocks number
688 /* If the pipe broke, or if there's no connection left for this easy handle,
689 then we MUST bail out now with no bitmask set. The no connection case can
690 happen when this is called from curl_multi_remove_handle() =>
691 singlesocket() => multi_getsock().
693 if(easy->state.pipe_broke || !easy->easy_conn)
696 if(easy->mstate > CURLM_STATE_CONNECT &&
697 easy->mstate < CURLM_STATE_COMPLETED) {
698 /* Set up ownership correctly */
699 easy->easy_conn->data = easy;
702 switch(easy->mstate) {
704 #if 0 /* switch back on these cases to get the compiler to check for all enums
706 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
707 case CURLM_STATE_COMPLETED:
708 case CURLM_STATE_MSGSENT:
709 case CURLM_STATE_INIT:
710 case CURLM_STATE_CONNECT:
711 case CURLM_STATE_WAITDO:
712 case CURLM_STATE_DONE:
713 case CURLM_STATE_LAST:
714 /* this will get called with CURLM_STATE_COMPLETED when a handle is
719 case CURLM_STATE_WAITRESOLVE:
720 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
722 case CURLM_STATE_PROTOCONNECT:
723 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
726 case CURLM_STATE_DOING:
727 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
729 case CURLM_STATE_WAITPROXYCONNECT:
730 case CURLM_STATE_WAITCONNECT:
731 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
733 case CURLM_STATE_DO_MORE:
734 return domore_getsock(easy->easy_conn, socks, numsocks);
736 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
737 to waiting for the same as the *PERFORM
739 case CURLM_STATE_PERFORM:
740 case CURLM_STATE_WAITPERFORM:
741 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
746 CURLMcode curl_multi_fdset(CURLM *multi_handle,
747 fd_set *read_fd_set, fd_set *write_fd_set,
748 fd_set *exc_fd_set, int *max_fd)
750 /* Scan through all the easy handles to get the file descriptors set.
751 Some easy handles may not have connected to the remote host yet,
752 and then we must make sure that is done. */
753 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
754 struct Curl_one_easy *easy;
756 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
759 (void)exc_fd_set; /* not used */
761 if(!GOOD_MULTI_HANDLE(multi))
762 return CURLM_BAD_HANDLE;
766 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
768 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
769 curl_socket_t s = CURL_SOCKET_BAD;
771 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
772 FD_SET(sockbunch[i], read_fd_set);
775 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
776 FD_SET(sockbunch[i], write_fd_set);
779 if(s == CURL_SOCKET_BAD)
780 /* this socket is unused, break out of loop */
783 if((int)s > this_max_fd)
784 this_max_fd = (int)s;
788 easy = easy->next; /* check next handle */
791 *max_fd = this_max_fd;
796 CURLMcode curl_multi_wait(CURLM *multi_handle,
797 struct curl_waitfd extra_fds[],
798 unsigned int extra_nfds,
802 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
803 struct Curl_one_easy *easy;
804 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
807 unsigned int nfds = 0;
808 unsigned int curlfds;
809 struct pollfd *ufds = NULL;
810 long timeout_internal;
812 if(!GOOD_MULTI_HANDLE(multi))
813 return CURLM_BAD_HANDLE;
815 /* If the internally desired timeout is actually shorter than requested from
816 the outside, then use the shorter time! But only if the internal timer
817 is actually larger than 0! */
818 (void)multi_timeout(multi, &timeout_internal);
819 if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
820 timeout_ms = (int)timeout_internal;
822 /* Count up how many fds we have from the multi handle */
825 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
827 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
828 curl_socket_t s = CURL_SOCKET_BAD;
830 if(bitmap & GETSOCK_READSOCK(i)) {
834 if(bitmap & GETSOCK_WRITESOCK(i)) {
838 if(s == CURL_SOCKET_BAD) {
843 easy = easy->next; /* check next handle */
846 curlfds = nfds; /* number of internal file descriptors */
847 nfds += extra_nfds; /* add the externally provided ones */
850 ufds = malloc(nfds * sizeof(struct pollfd));
852 return CURLM_OUT_OF_MEMORY;
856 /* only do the second loop if we found descriptors in the first stage run
860 /* Add the curl handles to our pollfds first */
863 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
865 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
866 curl_socket_t s = CURL_SOCKET_BAD;
868 if(bitmap & GETSOCK_READSOCK(i)) {
869 ufds[nfds].fd = sockbunch[i];
870 ufds[nfds].events = POLLIN;
874 if(bitmap & GETSOCK_WRITESOCK(i)) {
875 ufds[nfds].fd = sockbunch[i];
876 ufds[nfds].events = POLLOUT;
880 if(s == CURL_SOCKET_BAD) {
885 easy = easy->next; /* check next handle */
889 /* Add external file descriptions from poll-like struct curl_waitfd */
890 for(i = 0; i < extra_nfds; i++) {
891 ufds[nfds].fd = extra_fds[i].fd;
892 ufds[nfds].events = 0;
893 if(extra_fds[i].events & CURL_WAIT_POLLIN)
894 ufds[nfds].events |= POLLIN;
895 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
896 ufds[nfds].events |= POLLPRI;
897 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
898 ufds[nfds].events |= POLLOUT;
904 i = Curl_poll(ufds, nfds, timeout_ms);
908 /* copy revents results from the poll to the curl_multi_wait poll
909 struct, the bit values of the actual underlying poll() implementation
910 may not be the same as the ones in the public libcurl API! */
911 for(j = 0; j < extra_nfds; j++) {
912 unsigned short mask = 0;
913 unsigned r = ufds[curlfds + j].revents;
916 mask |= CURL_WAIT_POLLIN;
918 mask |= CURL_WAIT_POLLOUT;
920 mask |= CURL_WAIT_POLLPRI;
922 extra_fds[j].revents = mask;
935 static CURLMcode multi_runsingle(struct Curl_multi *multi,
937 struct Curl_one_easy *easy)
939 struct Curl_message *msg = NULL;
942 bool protocol_connect = FALSE;
943 bool dophase_done = FALSE;
945 CURLMcode result = CURLM_OK;
946 struct SingleRequest *k;
947 struct SessionHandle *data;
950 if(!GOOD_EASY_HANDLE(easy))
951 return CURLM_BAD_EASY_HANDLE;
956 /* this is a single-iteration do-while loop just to allow a
957 break to skip to the end of it */
958 bool disconnect_conn = FALSE;
960 /* Handle the case when the pipe breaks, i.e., the connection
961 we're using gets cleaned up and we're left with nothing. */
962 if(data->state.pipe_broke) {
963 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
964 (void *)easy, data->state.path);
966 if(easy->mstate < CURLM_STATE_COMPLETED) {
967 /* Head back to the CONNECT state */
968 multistate(easy, CURLM_STATE_CONNECT);
969 result = CURLM_CALL_MULTI_PERFORM;
970 easy->result = CURLE_OK;
973 data->state.pipe_broke = FALSE;
974 easy->easy_conn = NULL;
978 if(!easy->easy_conn &&
979 easy->mstate > CURLM_STATE_CONNECT &&
980 easy->mstate < CURLM_STATE_DONE) {
981 /* In all these states, the code will blindly access 'easy->easy_conn'
982 so this is precaution that it isn't NULL. And it silences static
984 failf(data, "In state %d with no easy_conn, bail out!\n", easy->mstate);
985 return CURLM_INTERNAL_ERROR;
988 if(easy->easy_conn && easy->mstate > CURLM_STATE_CONNECT &&
989 easy->mstate < CURLM_STATE_COMPLETED)
990 /* Make sure we set the connection's current owner */
991 easy->easy_conn->data = data;
993 if(easy->easy_conn &&
994 (easy->mstate >= CURLM_STATE_CONNECT) &&
995 (easy->mstate < CURLM_STATE_COMPLETED)) {
996 /* we need to wait for the connect state as only then is the start time
997 stored, but we must not check already completed handles */
999 timeout_ms = Curl_timeleft(data, &now,
1000 (easy->mstate <= CURLM_STATE_WAITDO)?
1003 if(timeout_ms < 0) {
1004 /* Handle timed out */
1005 if(easy->mstate == CURLM_STATE_WAITRESOLVE)
1006 failf(data, "Resolving timed out after %ld milliseconds",
1007 Curl_tvdiff(now, data->progress.t_startsingle));
1008 else if(easy->mstate == CURLM_STATE_WAITCONNECT)
1009 failf(data, "Connection timed out after %ld milliseconds",
1010 Curl_tvdiff(now, data->progress.t_startsingle));
1013 failf(data, "Operation timed out after %ld milliseconds with %"
1014 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1015 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1019 /* Force the connection closed because the server could continue to
1020 send us stuff at any time. (The disconnect_conn logic used below
1021 doesn't work at this point). */
1022 easy->easy_conn->bits.close = TRUE;
1023 easy->result = CURLE_OPERATION_TIMEDOUT;
1024 multistate(easy, CURLM_STATE_COMPLETED);
1029 switch(easy->mstate) {
1030 case CURLM_STATE_INIT:
1031 /* init this transfer. */
1032 easy->result=Curl_pretransfer(data);
1034 if(CURLE_OK == easy->result) {
1035 /* after init, go CONNECT */
1036 multistate(easy, CURLM_STATE_CONNECT);
1037 result = CURLM_CALL_MULTI_PERFORM;
1041 case CURLM_STATE_CONNECT_PEND:
1042 /* We will stay here until there is a connection available. Then
1043 we try again in the CURLM_STATE_CONNECT state. */
1046 case CURLM_STATE_CONNECT:
1047 /* Connect. We want to get a connection identifier filled in. */
1048 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1049 easy->result = Curl_connect(data, &easy->easy_conn,
1050 &async, &protocol_connect);
1051 if(CURLE_NO_CONNECTION_AVAILABLE == easy->result) {
1052 /* There was no connection available. We will go to the pending
1053 state and wait for an available connection. */
1054 multistate(easy, CURLM_STATE_CONNECT_PEND);
1055 easy->result = CURLE_OK;
1059 if(CURLE_OK == easy->result) {
1060 /* Add this handle to the send or pend pipeline */
1061 easy->result = Curl_add_handle_to_pipeline(data, easy->easy_conn);
1062 if(CURLE_OK != easy->result)
1063 disconnect_conn = TRUE;
1066 /* We're now waiting for an asynchronous name lookup */
1067 multistate(easy, CURLM_STATE_WAITRESOLVE);
1069 /* after the connect has been sent off, go WAITCONNECT unless the
1070 protocol connect is already done and we can go directly to
1072 result = CURLM_CALL_MULTI_PERFORM;
1074 if(protocol_connect)
1075 multistate(easy, multi->pipelining_enabled?
1076 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1078 #ifndef CURL_DISABLE_HTTP
1079 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1080 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1083 multistate(easy, CURLM_STATE_WAITCONNECT);
1090 case CURLM_STATE_WAITRESOLVE:
1091 /* awaiting an asynch name resolve to complete */
1093 struct Curl_dns_entry *dns = NULL;
1095 /* check if we have the name resolved by now */
1096 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1098 /* Update sockets here, because the socket(s) may have been
1099 closed and the application thus needs to be told, even if it
1100 is likely that the same socket(s) will again be used further
1101 down. If the name has not yet been resolved, it is likely
1102 that new sockets have been opened in an attempt to contact
1103 another resolver. */
1104 singlesocket(multi, easy);
1107 /* Perform the next step in the connection phase, and then move on
1108 to the WAITCONNECT state */
1109 easy->result = Curl_async_resolved(easy->easy_conn,
1112 if(CURLE_OK != easy->result)
1113 /* if Curl_async_resolved() returns failure, the connection struct
1114 is already freed and gone */
1115 easy->easy_conn = NULL; /* no more connection */
1117 /* call again please so that we get the next socket setup */
1118 result = CURLM_CALL_MULTI_PERFORM;
1119 if(protocol_connect)
1120 multistate(easy, multi->pipelining_enabled?
1121 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1123 #ifndef CURL_DISABLE_HTTP
1124 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1125 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1128 multistate(easy, CURLM_STATE_WAITCONNECT);
1133 if(CURLE_OK != easy->result) {
1134 /* failure detected */
1135 disconnect_conn = TRUE;
1141 #ifndef CURL_DISABLE_HTTP
1142 case CURLM_STATE_WAITPROXYCONNECT:
1143 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1144 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1146 if(easy->easy_conn->bits.proxy_connect_closed) {
1147 /* reset the error buffer */
1148 if(data->set.errorbuffer)
1149 data->set.errorbuffer[0] = '\0';
1150 data->state.errorbuf = FALSE;
1152 easy->result = CURLE_OK;
1153 result = CURLM_CALL_MULTI_PERFORM;
1154 multistate(easy, CURLM_STATE_CONNECT);
1156 else if(CURLE_OK == easy->result) {
1157 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1158 multistate(easy, CURLM_STATE_WAITCONNECT);
1163 case CURLM_STATE_WAITCONNECT:
1164 /* awaiting a completion of an asynch connect */
1165 easy->result = Curl_is_connected(easy->easy_conn,
1171 /* if everything is still fine we do the protocol-specific connect
1173 easy->result = Curl_protocol_connect(easy->easy_conn,
1177 if(CURLE_OK != easy->result) {
1178 /* failure detected */
1179 /* Just break, the cleaning up is handled all in one place */
1180 disconnect_conn = TRUE;
1185 if(!protocol_connect) {
1186 /* We have a TCP connection, but 'protocol_connect' may be false
1187 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1188 connect is TRUE, we move on to STATE_DO.
1189 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1191 #ifndef CURL_DISABLE_HTTP
1192 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1193 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1196 multistate(easy, CURLM_STATE_PROTOCONNECT);
1200 /* after the connect has completed, go WAITDO or DO */
1201 multistate(easy, multi->pipelining_enabled?
1202 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1204 result = CURLM_CALL_MULTI_PERFORM;
1208 case CURLM_STATE_PROTOCONNECT:
1209 /* protocol-specific connect phase */
1210 easy->result = Curl_protocol_connecting(easy->easy_conn,
1212 if((easy->result == CURLE_OK) && protocol_connect) {
1213 /* after the connect has completed, go WAITDO or DO */
1214 multistate(easy, multi->pipelining_enabled?
1215 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1216 result = CURLM_CALL_MULTI_PERFORM;
1218 else if(easy->result) {
1219 /* failure detected */
1220 Curl_posttransfer(data);
1221 Curl_done(&easy->easy_conn, easy->result, TRUE);
1222 disconnect_conn = TRUE;
1226 case CURLM_STATE_WAITDO:
1227 /* Wait for our turn to DO when we're pipelining requests */
1229 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
1230 easy->easy_conn->connection_id,
1231 easy->easy_conn->send_pipe->size,
1232 easy->easy_conn->writechannel_inuse?"TRUE":"FALSE",
1233 isHandleAtHead(data,
1234 easy->easy_conn->send_pipe)?"TRUE":"FALSE");
1236 if(!easy->easy_conn->writechannel_inuse &&
1237 isHandleAtHead(data,
1238 easy->easy_conn->send_pipe)) {
1239 /* Grab the channel */
1240 easy->easy_conn->writechannel_inuse = TRUE;
1241 multistate(easy, CURLM_STATE_DO);
1242 result = CURLM_CALL_MULTI_PERFORM;
1246 case CURLM_STATE_DO:
1247 if(data->set.connect_only) {
1248 /* keep connection open for application to use the socket */
1249 easy->easy_conn->bits.close = FALSE;
1250 multistate(easy, CURLM_STATE_DONE);
1251 easy->result = CURLE_OK;
1252 result = CURLM_CALL_MULTI_PERFORM;
1255 /* Perform the protocol's DO action */
1256 easy->result = Curl_do(&easy->easy_conn, &dophase_done);
1258 /* When Curl_do() returns failure, easy->easy_conn might be NULL! */
1260 if(CURLE_OK == easy->result) {
1262 /* some steps needed for wildcard matching */
1263 if(data->set.wildcardmatch) {
1264 struct WildcardData *wc = &data->wildcard;
1265 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1266 /* skip some states if it is important */
1267 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1268 multistate(easy, CURLM_STATE_DONE);
1269 result = CURLM_CALL_MULTI_PERFORM;
1273 /* DO was not completed in one function call, we must continue
1275 multistate(easy, CURLM_STATE_DOING);
1279 /* after DO, go DO_DONE... or DO_MORE */
1280 else if(easy->easy_conn->bits.do_more) {
1281 /* we're supposed to do more, but we need to sit down, relax
1282 and wait a little while first */
1283 multistate(easy, CURLM_STATE_DO_MORE);
1287 /* we're done with the DO, now DO_DONE */
1288 multistate(easy, CURLM_STATE_DO_DONE);
1289 result = CURLM_CALL_MULTI_PERFORM;
1292 else if((CURLE_SEND_ERROR == easy->result) &&
1293 easy->easy_conn->bits.reuse) {
1295 * In this situation, a connection that we were trying to use
1296 * may have unexpectedly died. If possible, send the connection
1297 * back to the CONNECT phase so we can try again.
1299 char *newurl = NULL;
1300 followtype follow=FOLLOW_NONE;
1304 drc = Curl_retry_request(easy->easy_conn, &newurl);
1306 /* a failure here pretty much implies an out of memory */
1308 disconnect_conn = TRUE;
1311 retry = (newurl)?TRUE:FALSE;
1313 Curl_posttransfer(data);
1314 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1316 /* When set to retry the connection, we must to go back to
1317 * the CONNECT state */
1319 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1320 follow = FOLLOW_RETRY;
1321 drc = Curl_follow(data, newurl, follow);
1322 if(drc == CURLE_OK) {
1323 multistate(easy, CURLM_STATE_CONNECT);
1324 result = CURLM_CALL_MULTI_PERFORM;
1325 easy->result = CURLE_OK;
1334 /* done didn't return OK or SEND_ERROR */
1340 /* Have error handler disconnect conn if we can't retry */
1341 disconnect_conn = TRUE;
1345 /* failure detected */
1346 Curl_posttransfer(data);
1348 Curl_done(&easy->easy_conn, easy->result, FALSE);
1349 disconnect_conn = TRUE;
1354 case CURLM_STATE_DOING:
1355 /* we continue DOING until the DO phase is complete */
1356 easy->result = Curl_protocol_doing(easy->easy_conn,
1358 if(CURLE_OK == easy->result) {
1360 /* after DO, go DO_DONE or DO_MORE */
1361 multistate(easy, easy->easy_conn->bits.do_more?
1362 CURLM_STATE_DO_MORE:
1363 CURLM_STATE_DO_DONE);
1364 result = CURLM_CALL_MULTI_PERFORM;
1365 } /* dophase_done */
1368 /* failure detected */
1369 Curl_posttransfer(data);
1370 Curl_done(&easy->easy_conn, easy->result, FALSE);
1371 disconnect_conn = TRUE;
1375 case CURLM_STATE_DO_MORE:
1377 * When we are connected, DO MORE and then go DO_DONE
1379 easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1381 /* No need to remove this handle from the send pipeline here since that
1382 is done in Curl_done() */
1383 if(CURLE_OK == easy->result) {
1385 multistate(easy, CURLM_STATE_DO_DONE);
1386 result = CURLM_CALL_MULTI_PERFORM;
1389 /* stay in DO_MORE */
1393 /* failure detected */
1394 Curl_posttransfer(data);
1395 Curl_done(&easy->easy_conn, easy->result, FALSE);
1396 disconnect_conn = TRUE;
1400 case CURLM_STATE_DO_DONE:
1401 /* Move ourselves from the send to recv pipeline */
1402 Curl_move_handle_from_send_to_recv_pipe(data, easy->easy_conn);
1403 /* Check if we can move pending requests to send pipe */
1404 Curl_multi_process_pending_handles(multi);
1405 multistate(easy, CURLM_STATE_WAITPERFORM);
1406 result = CURLM_CALL_MULTI_PERFORM;
1409 case CURLM_STATE_WAITPERFORM:
1410 /* Wait for our turn to PERFORM */
1411 if(!easy->easy_conn->readchannel_inuse &&
1412 isHandleAtHead(data,
1413 easy->easy_conn->recv_pipe)) {
1414 /* Grab the channel */
1415 easy->easy_conn->readchannel_inuse = TRUE;
1416 multistate(easy, CURLM_STATE_PERFORM);
1417 result = CURLM_CALL_MULTI_PERFORM;
1421 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
1422 easy->easy_conn->connection_id,
1423 easy->easy_conn->recv_pipe->size,
1424 easy->easy_conn->readchannel_inuse?"TRUE":"FALSE",
1425 isHandleAtHead(data,
1426 easy->easy_conn->recv_pipe)?"TRUE":"FALSE");
1431 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1432 /* if both rates are within spec, resume transfer */
1433 if(Curl_pgrsUpdate(easy->easy_conn))
1434 easy->result = CURLE_ABORTED_BY_CALLBACK;
1436 easy->result = Curl_speedcheck(data, now);
1438 if(( (data->set.max_send_speed == 0) ||
1439 (data->progress.ulspeed < data->set.max_send_speed )) &&
1440 ( (data->set.max_recv_speed == 0) ||
1441 (data->progress.dlspeed < data->set.max_recv_speed)))
1442 multistate(easy, CURLM_STATE_PERFORM);
1445 case CURLM_STATE_PERFORM:
1447 char *newurl = NULL;
1450 /* check if over send speed */
1451 if((data->set.max_send_speed > 0) &&
1452 (data->progress.ulspeed > data->set.max_send_speed)) {
1455 multistate(easy, CURLM_STATE_TOOFAST);
1457 /* calculate upload rate-limitation timeout. */
1458 buffersize = (int)(data->set.buffer_size ?
1459 data->set.buffer_size : BUFSIZE);
1460 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1461 data->progress.ulspeed, buffersize);
1462 Curl_expire(data, timeout_ms);
1466 /* check if over recv speed */
1467 if((data->set.max_recv_speed > 0) &&
1468 (data->progress.dlspeed > data->set.max_recv_speed)) {
1471 multistate(easy, CURLM_STATE_TOOFAST);
1473 /* Calculate download rate-limitation timeout. */
1474 buffersize = (int)(data->set.buffer_size ?
1475 data->set.buffer_size : BUFSIZE);
1476 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1477 data->progress.dlspeed, buffersize);
1478 Curl_expire(data, timeout_ms);
1482 /* read/write data if it is ready to do so */
1483 easy->result = Curl_readwrite(easy->easy_conn, &done);
1487 if(!(k->keepon & KEEP_RECV)) {
1488 /* We're done receiving */
1489 easy->easy_conn->readchannel_inuse = FALSE;
1492 if(!(k->keepon & KEEP_SEND)) {
1493 /* We're done sending */
1494 easy->easy_conn->writechannel_inuse = FALSE;
1497 if(done || (easy->result == CURLE_RECV_ERROR)) {
1498 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1499 * condition and the server closed the re-used connection exactly when
1500 * we wanted to use it, so figure out if that is indeed the case.
1502 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1504 retry = (newurl)?TRUE:FALSE;
1507 /* if we are to retry, set the result to OK and consider the
1509 easy->result = CURLE_OK;
1516 * The transfer phase returned error, we mark the connection to get
1517 * closed to prevent being re-used. This is because we can't possibly
1518 * know if the connection is in a good shape or not now. Unless it is
1519 * a protocol which uses two "channels" like FTP, as then the error
1520 * happened in the data connection.
1523 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1524 easy->easy_conn->bits.close = TRUE;
1526 Curl_posttransfer(data);
1527 Curl_done(&easy->easy_conn, easy->result, FALSE);
1530 followtype follow=FOLLOW_NONE;
1532 /* call this even if the readwrite function returned error */
1533 Curl_posttransfer(data);
1535 /* we're no longer receiving */
1536 Curl_removeHandleFromPipeline(data, easy->easy_conn->recv_pipe);
1538 /* expire the new receiving pipeline head */
1539 if(easy->easy_conn->recv_pipe->head)
1540 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1542 /* Check if we can move pending requests to send pipe */
1543 Curl_multi_process_pending_handles(multi);
1545 /* When we follow redirects or is set to retry the connection, we must
1546 to go back to the CONNECT state */
1547 if(data->req.newurl || retry) {
1549 /* if the URL is a follow-location and not just a retried request
1550 then figure out the URL here */
1551 newurl = data->req.newurl;
1552 data->req.newurl = NULL;
1553 follow = FOLLOW_REDIR;
1556 follow = FOLLOW_RETRY;
1557 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1558 if(CURLE_OK == easy->result) {
1559 easy->result = Curl_follow(data, newurl, follow);
1560 if(CURLE_OK == easy->result) {
1561 multistate(easy, CURLM_STATE_CONNECT);
1562 result = CURLM_CALL_MULTI_PERFORM;
1563 newurl = NULL; /* handed over the memory ownership to
1564 Curl_follow(), make sure we don't free() it
1570 /* after the transfer is done, go DONE */
1572 /* but first check to see if we got a location info even though we're
1573 not following redirects */
1574 if(data->req.location) {
1577 newurl = data->req.location;
1578 data->req.location = NULL;
1579 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1580 if(CURLE_OK == easy->result)
1581 newurl = NULL; /* allocation was handed over Curl_follow() */
1583 disconnect_conn = TRUE;
1586 multistate(easy, CURLM_STATE_DONE);
1587 result = CURLM_CALL_MULTI_PERFORM;
1596 case CURLM_STATE_DONE:
1598 if(easy->easy_conn) {
1599 /* Remove ourselves from the receive pipeline, if we are there. */
1600 Curl_removeHandleFromPipeline(data,
1601 easy->easy_conn->recv_pipe);
1602 /* Check if we can move pending requests to send pipe */
1603 Curl_multi_process_pending_handles(multi);
1605 if(easy->easy_conn->bits.stream_was_rewound) {
1606 /* This request read past its response boundary so we quickly let
1607 the other requests consume those bytes since there is no
1608 guarantee that the socket will become active again */
1609 result = CURLM_CALL_MULTI_PERFORM;
1612 /* post-transfer command */
1613 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1615 * If there are other handles on the pipeline, Curl_done won't set
1616 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1617 * access free'd data, if the connection is free'd and the handle
1618 * removed before we perform the processing in CURLM_STATE_COMPLETED
1621 easy->easy_conn = NULL;
1624 if(data->set.wildcardmatch) {
1625 if(data->wildcard.state != CURLWC_DONE) {
1626 /* if a wildcard is set and we are not ending -> lets start again
1627 with CURLM_STATE_INIT */
1628 result = CURLM_CALL_MULTI_PERFORM;
1629 multistate(easy, CURLM_STATE_INIT);
1634 /* after we have DONE what we're supposed to do, go COMPLETED, and
1635 it doesn't matter what the Curl_done() returned! */
1636 multistate(easy, CURLM_STATE_COMPLETED);
1640 case CURLM_STATE_COMPLETED:
1641 /* this is a completed transfer, it is likely to still be connected */
1643 /* This node should be delinked from the list now and we should post
1644 an information message that we are complete. */
1646 /* Important: reset the conn pointer so that we don't point to memory
1647 that could be freed anytime */
1648 easy->easy_conn = NULL;
1650 Curl_expire(data, 0); /* stop all timers */
1653 case CURLM_STATE_MSGSENT:
1654 return CURLM_OK; /* do nothing */
1657 return CURLM_INTERNAL_ERROR;
1660 if(easy->mstate < CURLM_STATE_COMPLETED) {
1661 if(CURLE_OK != easy->result) {
1663 * If an error was returned, and we aren't in completed state now,
1664 * then we go to completed and consider this transfer aborted.
1667 /* NOTE: no attempt to disconnect connections must be made
1668 in the case blocks above - cleanup happens only here */
1670 data->state.pipe_broke = FALSE;
1672 if(easy->easy_conn) {
1673 /* if this has a connection, unsubscribe from the pipelines */
1674 easy->easy_conn->writechannel_inuse = FALSE;
1675 easy->easy_conn->readchannel_inuse = FALSE;
1676 Curl_removeHandleFromPipeline(data,
1677 easy->easy_conn->send_pipe);
1678 Curl_removeHandleFromPipeline(data,
1679 easy->easy_conn->recv_pipe);
1680 /* Check if we can move pending requests to send pipe */
1681 Curl_multi_process_pending_handles(multi);
1683 if(disconnect_conn) {
1684 /* disconnect properly */
1685 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1687 /* This is where we make sure that the easy_conn pointer is reset.
1688 We don't have to do this in every case block above where a
1689 failure is detected */
1690 easy->easy_conn = NULL;
1693 else if(easy->mstate == CURLM_STATE_CONNECT) {
1694 /* Curl_connect() failed */
1695 (void)Curl_posttransfer(data);
1698 multistate(easy, CURLM_STATE_COMPLETED);
1700 /* if there's still a connection to use, call the progress function */
1701 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1702 /* aborted due to progress callback return code must close the
1704 easy->easy_conn->bits.close = TRUE;
1706 /* if not yet in DONE state, go there, otherwise COMPLETED */
1707 multistate(easy, (easy->mstate < CURLM_STATE_DONE)?
1708 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1709 result = CURLM_CALL_MULTI_PERFORM;
1712 } WHILE_FALSE; /* just to break out from! */
1714 if(CURLM_STATE_COMPLETED == easy->mstate) {
1715 /* now fill in the Curl_message with this info */
1718 msg->extmsg.msg = CURLMSG_DONE;
1719 msg->extmsg.easy_handle = data;
1720 msg->extmsg.data.result = easy->result;
1722 result = multi_addmsg(multi, msg);
1724 multistate(easy, CURLM_STATE_MSGSENT);
1731 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1733 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1734 struct Curl_one_easy *easy;
1735 CURLMcode returncode=CURLM_OK;
1736 struct Curl_tree *t;
1737 struct timeval now = Curl_tvnow();
1739 if(!GOOD_MULTI_HANDLE(multi))
1740 return CURLM_BAD_HANDLE;
1745 struct WildcardData *wc = &easy->wildcard;
1747 if(easy->set.wildcardmatch) {
1749 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1751 return CURLM_OUT_OF_MEMORY;
1756 result = multi_runsingle(multi, now, easy);
1757 while(CURLM_CALL_MULTI_PERFORM == result);
1759 if(easy->set.wildcardmatch) {
1760 /* destruct wildcard structures if it is needed */
1761 if(wc->state == CURLWC_DONE || result)
1762 Curl_wildcard_dtor(wc);
1766 returncode = result;
1768 easy = easy->next; /* operate on next handle */
1772 * Simply remove all expired timers from the splay since handles are dealt
1773 * with unconditionally by this function and curl_multi_timeout() requires
1774 * that already passed/handled expire times are removed from the splay.
1776 * It is important that the 'now' value is set at the entry of this function
1777 * and not for the current time as it may have ticked a little while since
1778 * then and then we risk this loop to remove timers that actually have not
1782 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1784 /* the removed may have another timeout in queue */
1785 (void)add_next_timeout(now, multi, t->payload);
1789 *running_handles = multi->num_alive;
1791 if(CURLM_OK >= returncode)
1792 update_timer(multi);
1797 static void close_all_connections(struct Curl_multi *multi)
1799 struct connectdata *conn;
1801 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1803 conn->data = multi->closure_handle;
1805 /* This will remove the connection from the cache */
1806 (void)Curl_disconnect(conn, FALSE);
1808 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1812 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1814 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1815 struct Curl_one_easy *easy;
1816 struct Curl_one_easy *nexteasy;
1818 if(GOOD_MULTI_HANDLE(multi)) {
1819 multi->type = 0; /* not good anymore */
1821 /* Close all the connections in the connection cache */
1822 close_all_connections(multi);
1824 if(multi->closure_handle) {
1825 multi->closure_handle->dns.hostcache = multi->hostcache;
1826 Curl_hostcache_clean(multi->closure_handle);
1828 Curl_close(multi->closure_handle);
1829 multi->closure_handle = NULL;
1832 Curl_hash_destroy(multi->sockhash);
1833 multi->sockhash = NULL;
1835 Curl_conncache_destroy(multi->conn_cache);
1836 multi->conn_cache = NULL;
1838 /* remove the pending list of messages */
1839 Curl_llist_destroy(multi->msglist, NULL);
1840 multi->msglist = NULL;
1842 /* remove all easy handles */
1843 easy = multi->easyp;
1845 nexteasy=easy->next;
1846 if(easy->dns.hostcachetype == HCACHE_MULTI) {
1847 /* clear out the usage of the shared DNS cache */
1848 Curl_hostcache_clean(easy);
1849 easy->dns.hostcache = NULL;
1850 easy->dns.hostcachetype = HCACHE_NONE;
1853 /* Clear the pointer to the connection cache */
1854 easy->state.conn_cache = NULL;
1856 Curl_easy_addmulti(easy, NULL); /* clear the association */
1861 Curl_hash_destroy(multi->hostcache);
1862 multi->hostcache = NULL;
1864 /* Free the blacklists by setting them to NULL */
1865 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1866 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1873 return CURLM_BAD_HANDLE;
1877 * curl_multi_info_read()
1879 * This function is the primary way for a multi/multi_socket application to
1880 * figure out if a transfer has ended. We MUST make this function as fast as
1881 * possible as it will be polled frequently and we MUST NOT scan any lists in
1882 * here to figure out things. We must scale fine to thousands of handles and
1883 * beyond. The current design is fully O(1).
1886 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1888 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1889 struct Curl_message *msg;
1891 *msgs_in_queue = 0; /* default to none */
1893 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1894 /* there is one or more messages in the list */
1895 struct curl_llist_element *e;
1897 /* extract the head of the list to return */
1898 e = multi->msglist->head;
1902 /* remove the extracted entry */
1903 Curl_llist_remove(multi->msglist, e, NULL);
1905 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1907 return &msg->extmsg;
1914 * singlesocket() checks what sockets we deal with and their "action state"
1915 * and if we have a different state in any of those sockets from last time we
1916 * call the callback accordingly.
1918 static void singlesocket(struct Curl_multi *multi,
1919 struct Curl_one_easy *easy)
1921 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1923 struct Curl_sh_entry *entry;
1926 unsigned int curraction;
1927 struct Curl_one_easy *easy_by_hash;
1928 bool remove_sock_from_hash;
1930 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1931 socks[i] = CURL_SOCKET_BAD;
1933 /* Fill in the 'current' struct with the state as it is now: what sockets to
1934 supervise and for what actions */
1935 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1937 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1938 sockets we should have from now on. Detect the differences, remove no
1939 longer supervised ones and add new ones */
1941 /* walk over the sockets we got right now */
1942 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1943 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1945 int action = CURL_POLL_NONE;
1949 /* get it from the hash */
1950 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1952 if(curraction & GETSOCK_READSOCK(i))
1953 action |= CURL_POLL_IN;
1954 if(curraction & GETSOCK_WRITESOCK(i))
1955 action |= CURL_POLL_OUT;
1958 /* yeps, already present so check if it has the same action set */
1959 if(entry->action == action)
1960 /* same, continue */
1964 /* this is a socket we didn't have before, add it! */
1965 entry = sh_addentry(multi->sockhash, s, easy);
1971 /* we know (entry != NULL) at this point, see the logic above */
1972 if(multi->socket_cb)
1973 multi->socket_cb(easy,
1976 multi->socket_userp,
1979 entry->action = action; /* store the current action state */
1982 num = i; /* number of sockets */
1984 /* when we've walked over all the sockets we should have right now, we must
1985 make sure to detect sockets that are removed */
1986 for(i=0; i< easy->numsocks; i++) {
1988 s = easy->sockets[i];
1989 for(j=0; j<num; j++) {
1991 /* this is still supervised */
1992 s = CURL_SOCKET_BAD;
1996 if(s != CURL_SOCKET_BAD) {
1998 /* this socket has been removed. Tell the app to remove it */
1999 remove_sock_from_hash = TRUE;
2001 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2003 /* check if the socket to be removed serves a connection which has
2004 other easy-s in a pipeline. In this case the socket should not be
2006 struct connectdata *easy_conn;
2008 easy_by_hash = entry->easy->multi_pos;
2009 easy_conn = easy_by_hash->easy_conn;
2011 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2012 /* the handle should not be removed from the pipe yet */
2013 remove_sock_from_hash = FALSE;
2015 /* Update the sockhash entry to instead point to the next in line
2016 for the recv_pipe, or the first (in case this particular easy
2018 if(entry->easy == easy) {
2019 if(isHandleAtHead(easy, easy_conn->recv_pipe))
2020 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2022 entry->easy = easy_conn->recv_pipe->head->ptr;
2025 if(easy_conn->send_pipe && easy_conn->send_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 send_pipe, or the first (in case this particular easy
2032 if(entry->easy == easy) {
2033 if(isHandleAtHead(easy, easy_conn->send_pipe))
2034 entry->easy = easy_conn->send_pipe->head->next->ptr;
2036 entry->easy = easy_conn->send_pipe->head->ptr;
2039 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2040 when action will be asked on the socket (see multi_socket()), the
2041 head of the correct pipe will be taken according to the
2046 /* just a precaution, this socket really SHOULD be in the hash already
2047 but in case it isn't, we don't have to tell the app to remove it
2048 either since it never got to know about it */
2049 remove_sock_from_hash = FALSE;
2051 if(remove_sock_from_hash) {
2052 /* in this case 'entry' is always non-NULL */
2053 if(multi->socket_cb)
2054 multi->socket_cb(easy,
2057 multi->socket_userp,
2059 sh_delentry(multi->sockhash, s);
2065 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2066 easy->numsocks = num;
2070 * Curl_multi_closed()
2072 * Used by the connect code to tell the multi_socket code that one of the
2073 * sockets we were using have just been closed. This function will then
2074 * remove it from the sockethash for this handle to make the multi_socket API
2075 * behave properly, especially for the case when libcurl will create another
2076 * socket again and it gets the same file descriptor number.
2079 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2081 struct Curl_multi *multi = conn->data->multi;
2083 /* this is set if this connection is part of a handle that is added to
2084 a multi handle, and only then this is necessary */
2085 struct Curl_sh_entry *entry =
2086 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2089 if(multi->socket_cb)
2090 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2091 multi->socket_userp,
2094 /* now remove it from the socket hash */
2095 sh_delentry(multi->sockhash, s);
2103 * add_next_timeout()
2105 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2106 * when it has just been removed from the splay tree because the timeout has
2107 * expired. This function is then to advance in the list to pick the next
2108 * timeout to use (skip the already expired ones) and add this node back to
2109 * the splay tree again.
2111 * The splay tree only has each sessionhandle as a single node and the nearest
2112 * timeout is used to sort it on.
2114 static CURLMcode add_next_timeout(struct timeval now,
2115 struct Curl_multi *multi,
2116 struct SessionHandle *d)
2118 struct timeval *tv = &d->state.expiretime;
2119 struct curl_llist *list = d->state.timeoutlist;
2120 struct curl_llist_element *e;
2122 /* move over the timeout list for this specific handle and remove all
2123 timeouts that are now passed tense and store the next pending
2125 for(e = list->head; e; ) {
2126 struct curl_llist_element *n = e->next;
2127 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2129 /* remove outdated entry */
2130 Curl_llist_remove(list, e, NULL);
2132 /* the list is sorted so get out on the first mismatch */
2138 /* clear the expire times within the handles that we remove from the
2144 /* copy the first entry to 'tv' */
2145 memcpy(tv, e->ptr, sizeof(*tv));
2147 /* remove first entry from list */
2148 Curl_llist_remove(list, e, NULL);
2150 /* insert this node again into the splay */
2151 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2152 &d->state.timenode);
2158 #define TIMEOUT_INACCURACY 40000
2160 #define TIMEOUT_INACCURACY 3000
2163 static CURLMcode multi_socket(struct Curl_multi *multi,
2167 int *running_handles)
2169 CURLMcode result = CURLM_OK;
2170 struct SessionHandle *data = NULL;
2171 struct Curl_tree *t;
2172 struct timeval now = Curl_tvnow();
2175 struct Curl_one_easy *easy;
2176 /* *perform() deals with running_handles on its own */
2177 result = curl_multi_perform(multi, running_handles);
2179 /* walk through each easy handle and do the socket state change magic
2183 singlesocket(multi, easy);
2187 /* or should we fall-through and do the timer-based stuff? */
2190 else if(s != CURL_SOCKET_TIMEOUT) {
2192 struct Curl_sh_entry *entry =
2193 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2196 /* Unmatched socket, we can't act on it but we ignore this fact. In
2197 real-world tests it has been proved that libevent can in fact give
2198 the application actions even though the socket was just previously
2199 asked to get removed, so thus we better survive stray socket actions
2200 and just move on. */
2205 if(data->magic != CURLEASY_MAGIC_NUMBER)
2206 /* bad bad bad bad bad bad bad */
2207 return CURLM_INTERNAL_ERROR;
2209 /* If the pipeline is enabled, take the handle which is in the head of
2210 the pipeline. If we should write into the socket, take the send_pipe
2211 head. If we should read from the socket, take the recv_pipe head. */
2212 if(data->set.one_easy->easy_conn) {
2213 if((ev_bitmask & CURL_POLL_OUT) &&
2214 data->set.one_easy->easy_conn->send_pipe &&
2215 data->set.one_easy->easy_conn->send_pipe->head)
2216 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2217 else if((ev_bitmask & CURL_POLL_IN) &&
2218 data->set.one_easy->easy_conn->recv_pipe &&
2219 data->set.one_easy->easy_conn->recv_pipe->head)
2220 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2223 if(data->set.one_easy->easy_conn &&
2224 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2225 /* set socket event bitmask if they're not locked */
2226 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2229 result = multi_runsingle(multi, now, data->set.one_easy);
2230 while(CURLM_CALL_MULTI_PERFORM == result);
2232 if(data->set.one_easy->easy_conn &&
2233 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2234 /* clear the bitmask only if not locked */
2235 data->set.one_easy->easy_conn->cselect_bits = 0;
2237 if(CURLM_OK >= result)
2238 /* get the socket(s) and check if the state has been changed since
2240 singlesocket(multi, data->set.one_easy);
2242 /* Now we fall-through and do the timer-based stuff, since we don't want
2243 to force the user to have to deal with timeouts as long as at least
2244 one connection in fact has traffic. */
2246 data = NULL; /* set data to NULL again to avoid calling
2247 multi_runsingle() in case there's no need to */
2251 /* Compensate for bad precision timers that might've triggered too early.
2253 This precaution was added in commit 2c72732ebf3da5e as a result of bad
2254 resolution in the windows function use(d).
2256 The problematic case here is when using the multi_socket API and libcurl
2257 has told the application about a timeout, and that timeout is what fires
2258 off a bit early. As we don't have any IDs associated with the timeout we
2259 can't tell which timeout that fired off but we only have the times to use
2260 to check what to do. If it fires off too early, we don't run the correct
2261 actions and we don't tell the application again about the same timeout as
2262 was already first in the queue...
2264 Originally we made the timeouts run 40 milliseconds early on all systems,
2265 but now we have an #ifdef setup to provide a decent precaution inaccuracy
2269 now.tv_usec += TIMEOUT_INACCURACY;
2270 if(now.tv_usec >= 1000000) {
2272 now.tv_usec -= 1000000;
2276 * The loop following here will go on as long as there are expire-times left
2277 * to process in the splay and 'data' will be re-assigned for every expired
2278 * handle we deal with.
2281 /* the first loop lap 'data' can be NULL */
2284 result = multi_runsingle(multi, now, data->set.one_easy);
2285 while(CURLM_CALL_MULTI_PERFORM == result);
2287 if(CURLM_OK >= result)
2288 /* get the socket(s) and check if the state has been changed since
2290 singlesocket(multi, data->set.one_easy);
2293 /* Check if there's one (more) expired timer to deal with! This function
2294 extracts a matching node if there is one */
2296 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2298 data = t->payload; /* assign this for next loop */
2299 (void)add_next_timeout(now, multi, t->payload);
2304 *running_handles = multi->num_alive;
2308 #undef curl_multi_setopt
2309 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2310 CURLMoption option, ...)
2312 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2313 CURLMcode res = CURLM_OK;
2316 if(!GOOD_MULTI_HANDLE(multi))
2317 return CURLM_BAD_HANDLE;
2319 va_start(param, option);
2322 case CURLMOPT_SOCKETFUNCTION:
2323 multi->socket_cb = va_arg(param, curl_socket_callback);
2325 case CURLMOPT_SOCKETDATA:
2326 multi->socket_userp = va_arg(param, void *);
2328 case CURLMOPT_PIPELINING:
2329 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2331 case CURLMOPT_TIMERFUNCTION:
2332 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2334 case CURLMOPT_TIMERDATA:
2335 multi->timer_userp = va_arg(param, void *);
2337 case CURLMOPT_MAXCONNECTS:
2338 multi->maxconnects = va_arg(param, long);
2340 case CURLMOPT_MAX_HOST_CONNECTIONS:
2341 multi->max_host_connections = va_arg(param, long);
2343 case CURLMOPT_MAX_PIPELINE_LENGTH:
2344 multi->max_pipeline_length = va_arg(param, long);
2346 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2347 multi->content_length_penalty_size = va_arg(param, long);
2349 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2350 multi->chunk_length_penalty_size = va_arg(param, long);
2352 case CURLMOPT_PIPELINING_SITE_BL:
2353 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2354 &multi->pipelining_site_bl);
2356 case CURLMOPT_PIPELINING_SERVER_BL:
2357 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2358 &multi->pipelining_server_bl);
2360 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2361 multi->max_total_connections = va_arg(param, long);
2364 res = CURLM_UNKNOWN_OPTION;
2371 /* we define curl_multi_socket() in the public multi.h header */
2372 #undef curl_multi_socket
2374 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2375 int *running_handles)
2377 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2378 0, running_handles);
2379 if(CURLM_OK >= result)
2380 update_timer((struct Curl_multi *)multi_handle);
2384 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2385 int ev_bitmask, int *running_handles)
2387 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2388 ev_bitmask, running_handles);
2389 if(CURLM_OK >= result)
2390 update_timer((struct Curl_multi *)multi_handle);
2394 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2397 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2398 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2399 if(CURLM_OK >= result)
2400 update_timer((struct Curl_multi *)multi_handle);
2404 static CURLMcode multi_timeout(struct Curl_multi *multi,
2407 static struct timeval tv_zero = {0,0};
2409 if(multi->timetree) {
2410 /* we have a tree of expire times */
2411 struct timeval now = Curl_tvnow();
2413 /* splay the lowest to the bottom */
2414 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2416 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2417 /* some time left before expiration */
2418 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2421 * Since we only provide millisecond resolution on the returned value
2422 * and the diff might be less than one millisecond here, we don't
2423 * return zero as that may cause short bursts of busyloops on fast
2424 * processors while the diff is still present but less than one
2425 * millisecond! instead we return 1 until the time is ripe.
2430 /* 0 means immediately */
2439 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2442 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2444 /* First, make some basic checks that the CURLM handle is a good handle */
2445 if(!GOOD_MULTI_HANDLE(multi))
2446 return CURLM_BAD_HANDLE;
2448 return multi_timeout(multi, timeout_ms);
2452 * Tell the application it should update its timers, if it subscribes to the
2453 * update timer callback.
2455 static int update_timer(struct Curl_multi *multi)
2459 if(!multi->timer_cb)
2461 if(multi_timeout(multi, &timeout_ms)) {
2464 if(timeout_ms < 0) {
2465 static const struct timeval none={0,0};
2466 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2467 multi->timer_lastcall = none;
2468 /* there's no timeout now but there was one previously, tell the app to
2470 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2475 /* When multi_timeout() is done, multi->timetree points to the node with the
2476 * timeout we got the (relative) time-out time for. We can thus easily check
2477 * if this is the same (fixed) time as we got in a previous call and then
2478 * avoid calling the callback again. */
2479 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2482 multi->timer_lastcall = multi->timetree->key;
2484 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2487 void Curl_multi_set_easy_connection(struct SessionHandle *handle,
2488 struct connectdata *conn)
2490 handle->set.one_easy->easy_conn = conn;
2493 static bool isHandleAtHead(struct SessionHandle *handle,
2494 struct curl_llist *pipeline)
2496 struct curl_llist_element *curr = pipeline->head;
2498 return (curr->ptr == handle) ? TRUE : FALSE;
2504 * multi_freetimeout()
2506 * Callback used by the llist system when a single timeout list entry is
2509 static void multi_freetimeout(void *user, void *entryptr)
2513 /* the entry was plain malloc()'ed */
2518 * multi_addtimeout()
2520 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2521 * of list is always the timeout nearest in time.
2525 multi_addtimeout(struct curl_llist *timeoutlist,
2526 struct timeval *stamp)
2528 struct curl_llist_element *e;
2529 struct timeval *timedup;
2530 struct curl_llist_element *prev = NULL;
2532 timedup = malloc(sizeof(*timedup));
2534 return CURLM_OUT_OF_MEMORY;
2536 /* copy the timestamp */
2537 memcpy(timedup, stamp, sizeof(*timedup));
2539 if(Curl_llist_count(timeoutlist)) {
2540 /* find the correct spot in the list */
2541 for(e = timeoutlist->head; e; e = e->next) {
2542 struct timeval *checktime = e->ptr;
2543 long diff = curlx_tvdiff(*checktime, *timedup);
2551 this is the first timeout on the list */
2553 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2555 return CURLM_OUT_OF_MEMORY;
2564 * given a number of milliseconds from now to use to set the 'act before
2565 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2567 * Note that the timeout will be added to a queue of timeouts if it defines a
2568 * moment in time that is later than the current head of queue.
2570 * Pass zero to clear all timeout values for this handle.
2572 void Curl_expire(struct SessionHandle *data, long milli)
2574 struct Curl_multi *multi = data->multi;
2575 struct timeval *nowp = &data->state.expiretime;
2578 /* this is only interesting for multi-interface using libcurl, and only
2579 while there is still a multi interface struct remaining! */
2584 /* No timeout, clear the time data. */
2585 if(nowp->tv_sec || nowp->tv_usec) {
2586 /* Since this is an cleared time, we must remove the previous entry from
2588 struct curl_llist *list = data->state.timeoutlist;
2590 rc = Curl_splayremovebyaddr(multi->timetree,
2591 &data->state.timenode,
2594 infof(data, "Internal error clearing splay node = %d\n", rc);
2596 /* flush the timeout list too */
2597 while(list->size > 0)
2598 Curl_llist_remove(list, list->tail, NULL);
2601 infof(data, "Expire cleared\n");
2611 set.tv_sec += milli/1000;
2612 set.tv_usec += (milli%1000)*1000;
2614 if(set.tv_usec >= 1000000) {
2616 set.tv_usec -= 1000000;
2619 if(nowp->tv_sec || nowp->tv_usec) {
2620 /* This means that the struct is added as a node in the splay tree.
2621 Compare if the new time is earlier, and only remove-old/add-new if it
2623 long diff = curlx_tvdiff(set, *nowp);
2625 /* the new expire time was later so just add it to the queue
2627 multi_addtimeout(data->state.timeoutlist, &set);
2631 /* the new time is newer than the presently set one, so add the current
2632 to the queue and update the head */
2633 multi_addtimeout(data->state.timeoutlist, nowp);
2635 /* Since this is an updated time, we must remove the previous entry from
2636 the splay tree first and then re-add the new value */
2637 rc = Curl_splayremovebyaddr(multi->timetree,
2638 &data->state.timenode,
2641 infof(data, "Internal error removing splay node = %d\n", rc);
2645 data->state.timenode.payload = data;
2646 multi->timetree = Curl_splayinsert(*nowp,
2648 &data->state.timenode);
2651 Curl_splayprint(multi->timetree, 0, TRUE);
2655 CURLMcode curl_multi_assign(CURLM *multi_handle,
2656 curl_socket_t s, void *hashp)
2658 struct Curl_sh_entry *there = NULL;
2659 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2661 if(s != CURL_SOCKET_BAD)
2662 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2665 return CURLM_BAD_SOCKET;
2667 there->socketp = hashp;
2672 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2674 return multi ? multi->max_host_connections : 0;
2677 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2679 return multi ? multi->max_total_connections : 0;
2682 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2684 return multi ? multi->max_pipeline_length : 0;
2687 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2689 return multi ? multi->content_length_penalty_size : 0;
2692 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2694 return multi ? multi->chunk_length_penalty_size : 0;
2697 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2699 return multi->pipelining_site_bl;
2702 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2704 return multi->pipelining_server_bl;
2707 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2709 struct Curl_one_easy *easy;
2713 if(easy->mstate == CURLM_STATE_CONNECT_PEND) {
2714 multistate(easy, CURLM_STATE_CONNECT);
2715 /* Make sure that the handle will be processed soonish. */
2716 Curl_expire(easy, 1);
2718 easy = easy->next; /* operate on next handle */
2723 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2725 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2726 struct Curl_one_easy *easy;
2728 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2729 multi->num_easy, multi->num_alive);
2730 for(easy=multi->easyp; easy; easy = easy->next) {
2731 if(easy->mstate < CURLM_STATE_COMPLETED) {
2732 /* only display handles that are not completed */
2733 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2735 statename[easy->mstate], easy->numsocks);
2736 for(i=0; i < easy->numsocks; i++) {
2737 curl_socket_t s = easy->sockets[i];
2738 struct Curl_sh_entry *entry =
2739 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2741 fprintf(stderr, "%d ", (int)s);
2743 fprintf(stderr, "INTERNAL CONFUSION\n");
2746 fprintf(stderr, "[%s %s] ",
2747 entry->action&CURL_POLL_IN?"RECVING":"",
2748 entry->action&CURL_POLL_OUT?"SENDING":"");
2751 fprintf(stderr, "\n");