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->state;
119 if(oldstate == state)
120 /* don't bother when the new state is the same as the old state */
126 if(easy->state >= CURLM_STATE_CONNECT_PEND &&
127 easy->state < CURLM_STATE_COMPLETED) {
129 connection_id = easy->easy_conn->connection_id;
131 infof(easy->easy_handle,
132 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
133 statename[oldstate], statename[easy->state],
134 (char *)easy, lineno, connection_id);
137 if(state == CURLM_STATE_COMPLETED)
138 /* changing to COMPLETED means there's one less easy handle 'alive' */
139 easy->easy_handle->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 /* Let's make the doubly-linked list a circular list. This makes
311 the linked list code simpler and allows inserting at the end
312 with less work (we didn't keep a tail pointer before). */
313 multi->easy.next = &multi->easy;
314 multi->easy.prev = &multi->easy;
316 multi->max_pipeline_length = 5;
317 return (CURLM *) multi;
321 Curl_hash_destroy(multi->sockhash);
322 multi->sockhash = NULL;
323 Curl_hash_destroy(multi->hostcache);
324 multi->hostcache = NULL;
325 Curl_conncache_destroy(multi->conn_cache);
326 multi->conn_cache = NULL;
332 CURLM *curl_multi_init(void)
334 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
335 CURL_CONNECTION_HASH_SIZE);
339 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
342 struct curl_llist *timeoutlist;
343 struct Curl_one_easy *easy;
344 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
345 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
346 struct SessionHandle *new_closure = NULL;
347 struct curl_hash *hostcache = NULL;
349 /* First, make some basic checks that the CURLM handle is a good handle */
350 if(!GOOD_MULTI_HANDLE(multi))
351 return CURLM_BAD_HANDLE;
353 /* Verify that we got a somewhat good easy handle too */
354 if(!GOOD_EASY_HANDLE(easy_handle))
355 return CURLM_BAD_EASY_HANDLE;
357 /* Prevent users from adding same easy handle more than
358 once and prevent adding to more than one multi stack */
360 /* possibly we should create a new unique error code for this condition */
361 return CURLM_BAD_EASY_HANDLE;
363 /* Allocate and initialize timeout list for easy handle */
364 timeoutlist = Curl_llist_alloc(multi_freetimeout);
366 return CURLM_OUT_OF_MEMORY;
368 /* Allocate new node for the doubly-linked circular list of
369 Curl_one_easy structs that holds pointers to easy handles */
370 easy = calloc(1, sizeof(struct Curl_one_easy));
372 Curl_llist_destroy(timeoutlist, NULL);
373 return CURLM_OUT_OF_MEMORY;
376 /* In case multi handle has no hostcache yet, allocate one */
377 if(!multi->hostcache) {
378 hostcache = Curl_mk_dnscache();
381 Curl_llist_destroy(timeoutlist, NULL);
382 return CURLM_OUT_OF_MEMORY;
386 /* In case multi handle has no closure_handle yet, allocate
387 a new easy handle to use when closing cached connections */
388 if(!multi->closure_handle) {
389 new_closure = (struct SessionHandle *)curl_easy_init();
391 Curl_hash_destroy(hostcache);
393 Curl_llist_destroy(timeoutlist, NULL);
394 return CURLM_OUT_OF_MEMORY;
399 ** No failure allowed in this function beyond this point. And
400 ** no modification of easy nor multi handle allowed before this
401 ** except for potential multi's connection cache growing which
402 ** won't be undone in this function no matter what.
405 /* In case a new closure handle has been initialized above, it
406 is associated now with the multi handle which lacked one. */
408 multi->closure_handle = new_closure;
409 Curl_easy_addmulti(multi->closure_handle, multi_handle);
410 multi->closure_handle->state.conn_cache = multi->conn_cache;
413 /* In case hostcache has been allocated above,
414 it is associated now with the multi handle. */
416 multi->hostcache = hostcache;
418 /* Make easy handle use timeout list initialized above */
419 data->state.timeoutlist = timeoutlist;
422 /* set the easy handle */
423 easy->easy_handle = data;
424 multistate(easy, CURLM_STATE_INIT);
426 /* set the back pointer to one_easy to assist in removal */
427 easy->easy_handle->multi_pos = easy;
429 /* for multi interface connections, we share DNS cache automatically if the
430 easy handle's one is currently not set. */
431 if(!easy->easy_handle->dns.hostcache ||
432 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
433 easy->easy_handle->dns.hostcache = multi->hostcache;
434 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
437 /* Point to the multi's connection cache */
438 easy->easy_handle->state.conn_cache = multi->conn_cache;
440 /* This adds the new entry at the 'end' of the doubly-linked circular
441 list of Curl_one_easy structs to try and maintain a FIFO queue so
442 the pipelined requests are in order. */
444 /* We add this new entry last in the list. We make our 'next' point to the
445 'first' struct and our 'prev' point to the previous 'prev' */
446 easy->next = &multi->easy;
447 easy->prev = multi->easy.prev;
449 /* make 'easy' the last node in the chain */
450 multi->easy.prev = easy;
452 /* if there was a prev node, make sure its 'next' pointer links to
454 easy->prev->next = easy;
456 /* make the SessionHandle refer back to this multi handle */
457 Curl_easy_addmulti(easy_handle, multi_handle);
459 /* make the SessionHandle struct refer back to this struct */
460 easy->easy_handle->set.one_easy = easy;
462 /* Set the timeout for this handle to expire really soon so that it will
463 be taken care of even when this handle is added in the midst of operation
464 when only the curl_multi_socket() API is used. During that flow, only
465 sockets that time-out or have actions will be dealt with. Since this
466 handle has no action yet, we make sure it times out to get things to
468 Curl_expire(easy->easy_handle, 1);
470 /* increase the node-counter */
473 /* increase the alive-counter */
476 /* A somewhat crude work-around for a little glitch in update_timer() that
477 happens if the lastcall time is set to the same time when the handle is
478 removed as when the next handle is added, as then the check in
479 update_timer() that prevents calling the application multiple times with
480 the same timer infor will not trigger and then the new handle's timeout
481 will not be notified to the app.
483 The work-around is thus simply to clear the 'lastcall' variable to force
484 update_timer() to always trigger a callback to the app when a new easy
486 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
493 /* Debug-function, used like this:
495 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
497 * Enable the hash print function first by editing hash.c
499 static void debug_print_sock_hash(void *p)
501 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
503 fprintf(stderr, " [easy %p/magic %x/socket %d]",
504 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
508 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
511 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
512 struct Curl_one_easy *easy;
513 struct SessionHandle *data = curl_handle;
515 /* First, make some basic checks that the CURLM handle is a good handle */
516 if(!GOOD_MULTI_HANDLE(multi))
517 return CURLM_BAD_HANDLE;
519 /* Verify that we got a somewhat good easy handle too */
520 if(!GOOD_EASY_HANDLE(curl_handle))
521 return CURLM_BAD_EASY_HANDLE;
523 /* pick-up from the 'curl_handle' the kept position in the list */
524 easy = data->multi_pos;
527 bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
528 bool easy_owns_conn = (easy->easy_conn &&
529 (easy->easy_conn->data == easy->easy_handle)) ?
532 /* If the 'state' is not INIT or COMPLETED, we might need to do something
533 nice to put the easy_handle in a good known state when this returns. */
535 /* this handle is "alive" so we need to count down the total number of
536 alive connections when this is removed */
539 if(easy->easy_conn &&
540 (easy->easy_conn->send_pipe->size +
541 easy->easy_conn->recv_pipe->size > 1) &&
542 easy->state > CURLM_STATE_WAITDO &&
543 easy->state < CURLM_STATE_COMPLETED) {
544 /* If the handle is in a pipeline and has started sending off its
545 request but not received its response yet, we need to close
547 easy->easy_conn->bits.close = TRUE;
548 /* Set connection owner so that Curl_done() closes it.
549 We can sefely do this here since connection is killed. */
550 easy->easy_conn->data = easy->easy_handle;
553 /* The timer must be shut down before easy->multi is set to NULL,
554 else the timenode will remain in the splay tree after
555 curl_easy_cleanup is called. */
556 Curl_expire(easy->easy_handle, 0);
558 /* destroy the timeout list that is held in the easy handle */
559 if(data->state.timeoutlist) {
560 Curl_llist_destroy(data->state.timeoutlist, NULL);
561 data->state.timeoutlist = NULL;
564 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
565 /* stop using the multi handle's DNS cache */
566 easy->easy_handle->dns.hostcache = NULL;
567 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
570 if(easy->easy_conn) {
572 /* we must call Curl_done() here (if we still "own it") so that we don't
573 leave a half-baked one around */
576 /* Curl_done() clears the conn->data field to lose the association
577 between the easy handle and the connection
579 Note that this ignores the return code simply because there's
580 nothing really useful to do with it anyway! */
581 (void)Curl_done(&easy->easy_conn, easy->result, premature);
584 /* Clear connection pipelines, if Curl_done above was not called */
585 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
588 /* as this was using a shared connection cache we clear the pointer
589 to that since we're not part of that multi handle anymore */
590 easy->easy_handle->state.conn_cache = NULL;
592 /* change state without using multistate(), only to make singlesocket() do
594 easy->state = CURLM_STATE_COMPLETED;
595 singlesocket(multi, easy); /* to let the application know what sockets
596 that vanish with this handle */
598 /* Remove the association between the connection and the handle */
599 if(easy->easy_conn) {
600 easy->easy_conn->data = NULL;
601 easy->easy_conn = NULL;
604 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
605 to this multi handle */
608 /* make sure there's no pending message in the queue sent from this easy
610 struct curl_llist_element *e;
612 for(e = multi->msglist->head; e; e = e->next) {
613 struct Curl_message *msg = e->ptr;
615 if(msg->extmsg.easy_handle == easy->easy_handle) {
616 Curl_llist_remove(multi->msglist, e, NULL);
617 /* there can only be one from this specific handle */
623 /* make the previous node point to our next */
625 easy->prev->next = easy->next;
626 /* make our next point to our previous node */
628 easy->next->prev = easy->prev;
630 easy->easy_handle->set.one_easy = NULL; /* detached */
632 /* Null the position in the controlling structure */
633 easy->easy_handle->multi_pos = NULL;
636 We do not touch the easy handle here! */
639 multi->num_easy--; /* one less to care about now */
645 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
648 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
650 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
653 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
655 struct Curl_one_easy *one_easy = data->set.one_easy;
658 one_easy->easy_conn = NULL;
661 static int waitconnect_getsock(struct connectdata *conn,
666 return GETSOCK_BLANK;
668 sock[0] = conn->sock[FIRSTSOCKET];
670 /* when we've sent a CONNECT to a proxy, we should rather wait for the
671 socket to become readable to be able to get the response headers */
672 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
673 return GETSOCK_READSOCK(0);
675 return GETSOCK_WRITESOCK(0);
678 static int domore_getsock(struct connectdata *conn,
679 curl_socket_t *socks,
682 if(conn && conn->handler->domore_getsock)
683 return conn->handler->domore_getsock(conn, socks, numsocks);
684 return GETSOCK_BLANK;
687 /* returns bitmapped flags for this handle and its sockets */
688 static int multi_getsock(struct Curl_one_easy *easy,
689 curl_socket_t *socks, /* points to numsocks number
693 /* If the pipe broke, or if there's no connection left for this easy handle,
694 then we MUST bail out now with no bitmask set. The no connection case can
695 happen when this is called from curl_multi_remove_handle() =>
696 singlesocket() => multi_getsock().
698 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
701 if(easy->state > CURLM_STATE_CONNECT &&
702 easy->state < CURLM_STATE_COMPLETED) {
703 /* Set up ownership correctly */
704 easy->easy_conn->data = easy->easy_handle;
707 switch(easy->state) {
709 #if 0 /* switch back on these cases to get the compiler to check for all enums
711 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
712 case CURLM_STATE_COMPLETED:
713 case CURLM_STATE_MSGSENT:
714 case CURLM_STATE_INIT:
715 case CURLM_STATE_CONNECT:
716 case CURLM_STATE_WAITDO:
717 case CURLM_STATE_DONE:
718 case CURLM_STATE_LAST:
719 /* this will get called with CURLM_STATE_COMPLETED when a handle is
724 case CURLM_STATE_WAITRESOLVE:
725 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
727 case CURLM_STATE_PROTOCONNECT:
728 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
731 case CURLM_STATE_DOING:
732 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
734 case CURLM_STATE_WAITPROXYCONNECT:
735 case CURLM_STATE_WAITCONNECT:
736 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
738 case CURLM_STATE_DO_MORE:
739 return domore_getsock(easy->easy_conn, socks, numsocks);
741 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
742 to waiting for the same as the *PERFORM
744 case CURLM_STATE_PERFORM:
745 case CURLM_STATE_WAITPERFORM:
746 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
751 CURLMcode curl_multi_fdset(CURLM *multi_handle,
752 fd_set *read_fd_set, fd_set *write_fd_set,
753 fd_set *exc_fd_set, int *max_fd)
755 /* Scan through all the easy handles to get the file descriptors set.
756 Some easy handles may not have connected to the remote host yet,
757 and then we must make sure that is done. */
758 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
759 struct Curl_one_easy *easy;
761 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
764 (void)exc_fd_set; /* not used */
766 if(!GOOD_MULTI_HANDLE(multi))
767 return CURLM_BAD_HANDLE;
769 easy=multi->easy.next;
770 while(easy != &multi->easy) {
771 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
773 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
774 curl_socket_t s = CURL_SOCKET_BAD;
776 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
777 FD_SET(sockbunch[i], read_fd_set);
780 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
781 FD_SET(sockbunch[i], write_fd_set);
784 if(s == CURL_SOCKET_BAD)
785 /* this socket is unused, break out of loop */
788 if((int)s > this_max_fd)
789 this_max_fd = (int)s;
793 easy = easy->next; /* check next handle */
796 *max_fd = this_max_fd;
801 CURLMcode curl_multi_wait(CURLM *multi_handle,
802 struct curl_waitfd extra_fds[],
803 unsigned int extra_nfds,
807 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
808 struct Curl_one_easy *easy;
809 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
812 unsigned int nfds = 0;
813 unsigned int curlfds;
814 struct pollfd *ufds = NULL;
815 long timeout_internal;
817 if(!GOOD_MULTI_HANDLE(multi))
818 return CURLM_BAD_HANDLE;
820 /* If the internally desired timeout is actually shorter than requested from
821 the outside, then use the shorter time! */
822 (void)multi_timeout(multi, &timeout_internal);
823 if(timeout_internal < (long)timeout_ms)
824 timeout_ms = (int)timeout_internal;
826 /* Count up how many fds we have from the multi handle */
827 easy=multi->easy.next;
828 while(easy != &multi->easy) {
829 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
831 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
832 curl_socket_t s = CURL_SOCKET_BAD;
834 if(bitmap & GETSOCK_READSOCK(i)) {
838 if(bitmap & GETSOCK_WRITESOCK(i)) {
842 if(s == CURL_SOCKET_BAD) {
847 easy = easy->next; /* check next handle */
850 curlfds = nfds; /* number of internal file descriptors */
851 nfds += extra_nfds; /* add the externally provided ones */
854 ufds = malloc(nfds * sizeof(struct pollfd));
856 return CURLM_OUT_OF_MEMORY;
860 /* only do the second loop if we found descriptors in the first stage run
864 /* Add the curl handles to our pollfds first */
865 easy=multi->easy.next;
866 while(easy != &multi->easy) {
867 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
869 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
870 curl_socket_t s = CURL_SOCKET_BAD;
872 if(bitmap & GETSOCK_READSOCK(i)) {
873 ufds[nfds].fd = sockbunch[i];
874 ufds[nfds].events = POLLIN;
878 if(bitmap & GETSOCK_WRITESOCK(i)) {
879 ufds[nfds].fd = sockbunch[i];
880 ufds[nfds].events = POLLOUT;
884 if(s == CURL_SOCKET_BAD) {
889 easy = easy->next; /* check next handle */
893 /* Add external file descriptions from poll-like struct curl_waitfd */
894 for(i = 0; i < extra_nfds; i++) {
895 ufds[nfds].fd = extra_fds[i].fd;
896 ufds[nfds].events = 0;
897 if(extra_fds[i].events & CURL_WAIT_POLLIN)
898 ufds[nfds].events |= POLLIN;
899 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
900 ufds[nfds].events |= POLLPRI;
901 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
902 ufds[nfds].events |= POLLOUT;
908 i = Curl_poll(ufds, nfds, timeout_ms);
918 static CURLMcode multi_runsingle(struct Curl_multi *multi,
920 struct Curl_one_easy *easy)
922 struct Curl_message *msg = NULL;
925 bool protocol_connect = FALSE;
926 bool dophase_done = FALSE;
928 CURLMcode result = CURLM_OK;
929 struct SingleRequest *k;
930 struct SessionHandle *data;
933 if(!GOOD_EASY_HANDLE(easy->easy_handle))
934 return CURLM_BAD_EASY_HANDLE;
936 data = easy->easy_handle;
939 /* this is a single-iteration do-while loop just to allow a
940 break to skip to the end of it */
941 bool disconnect_conn = FALSE;
943 /* Handle the case when the pipe breaks, i.e., the connection
944 we're using gets cleaned up and we're left with nothing. */
945 if(data->state.pipe_broke) {
946 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
947 easy, data->state.path);
949 if(easy->state < CURLM_STATE_COMPLETED) {
950 /* Head back to the CONNECT state */
951 multistate(easy, CURLM_STATE_CONNECT);
952 result = CURLM_CALL_MULTI_PERFORM;
953 easy->result = CURLE_OK;
956 data->state.pipe_broke = FALSE;
957 easy->easy_conn = NULL;
961 if(!easy->easy_conn &&
962 easy->state > CURLM_STATE_CONNECT &&
963 easy->state < CURLM_STATE_DONE) {
964 /* In all these states, the code will blindly access 'easy->easy_conn'
965 so this is precaution that it isn't NULL. And it silences static
967 failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
968 return CURLM_INTERNAL_ERROR;
971 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
972 easy->state < CURLM_STATE_COMPLETED)
973 /* Make sure we set the connection's current owner */
974 easy->easy_conn->data = data;
976 if(easy->easy_conn &&
977 (easy->state >= CURLM_STATE_CONNECT) &&
978 (easy->state < CURLM_STATE_COMPLETED)) {
979 /* we need to wait for the connect state as only then is the start time
980 stored, but we must not check already completed handles */
982 timeout_ms = Curl_timeleft(data, &now,
983 (easy->state <= CURLM_STATE_WAITDO)?
987 /* Handle timed out */
988 if(easy->state == CURLM_STATE_WAITRESOLVE)
989 failf(data, "Resolving timed out after %ld milliseconds",
990 Curl_tvdiff(now, data->progress.t_startsingle));
991 else if(easy->state == CURLM_STATE_WAITCONNECT)
992 failf(data, "Connection timed out after %ld milliseconds",
993 Curl_tvdiff(now, data->progress.t_startsingle));
996 failf(data, "Operation timed out after %ld milliseconds with %"
997 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
998 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1002 /* Force the connection closed because the server could continue to
1003 send us stuff at any time. (The disconnect_conn logic used below
1004 doesn't work at this point). */
1005 easy->easy_conn->bits.close = TRUE;
1006 easy->result = CURLE_OPERATION_TIMEDOUT;
1007 multistate(easy, CURLM_STATE_COMPLETED);
1012 switch(easy->state) {
1013 case CURLM_STATE_INIT:
1014 /* init this transfer. */
1015 easy->result=Curl_pretransfer(data);
1017 if(CURLE_OK == easy->result) {
1018 /* after init, go CONNECT */
1019 multistate(easy, CURLM_STATE_CONNECT);
1020 result = CURLM_CALL_MULTI_PERFORM;
1024 case CURLM_STATE_CONNECT_PEND:
1025 /* We will stay here until there is a connection available. Then
1026 we try again in the CURLM_STATE_CONNECT state. */
1029 case CURLM_STATE_CONNECT:
1030 /* Connect. We want to get a connection identifier filled in. */
1031 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1032 easy->result = Curl_connect(data, &easy->easy_conn,
1033 &async, &protocol_connect);
1034 if(CURLE_NO_CONNECTION_AVAILABLE == easy->result) {
1035 /* There was no connection available. We will go to the pending
1036 state and wait for an available connection. */
1037 multistate(easy, CURLM_STATE_CONNECT_PEND);
1038 easy->result = CURLE_OK;
1042 if(CURLE_OK == easy->result) {
1043 /* Add this handle to the send or pend pipeline */
1044 easy->result = Curl_add_handle_to_pipeline(data, easy->easy_conn);
1045 if(CURLE_OK != easy->result)
1046 disconnect_conn = TRUE;
1049 /* We're now waiting for an asynchronous name lookup */
1050 multistate(easy, CURLM_STATE_WAITRESOLVE);
1052 /* after the connect has been sent off, go WAITCONNECT unless the
1053 protocol connect is already done and we can go directly to
1055 result = CURLM_CALL_MULTI_PERFORM;
1057 if(protocol_connect)
1058 multistate(easy, multi->pipelining_enabled?
1059 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1061 #ifndef CURL_DISABLE_HTTP
1062 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1063 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1066 multistate(easy, CURLM_STATE_WAITCONNECT);
1073 case CURLM_STATE_WAITRESOLVE:
1074 /* awaiting an asynch name resolve to complete */
1076 struct Curl_dns_entry *dns = NULL;
1078 /* check if we have the name resolved by now */
1079 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1081 /* Update sockets here, because the socket(s) may have been
1082 closed and the application thus needs to be told, even if it
1083 is likely that the same socket(s) will again be used further
1084 down. If the name has not yet been resolved, it is likely
1085 that new sockets have been opened in an attempt to contact
1086 another resolver. */
1087 singlesocket(multi, easy);
1090 /* Perform the next step in the connection phase, and then move on
1091 to the WAITCONNECT state */
1092 easy->result = Curl_async_resolved(easy->easy_conn,
1095 if(CURLE_OK != easy->result)
1096 /* if Curl_async_resolved() returns failure, the connection struct
1097 is already freed and gone */
1098 easy->easy_conn = NULL; /* no more connection */
1100 /* call again please so that we get the next socket setup */
1101 result = CURLM_CALL_MULTI_PERFORM;
1102 if(protocol_connect)
1103 multistate(easy, multi->pipelining_enabled?
1104 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1106 #ifndef CURL_DISABLE_HTTP
1107 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1108 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1111 multistate(easy, CURLM_STATE_WAITCONNECT);
1116 if(CURLE_OK != easy->result) {
1117 /* failure detected */
1118 disconnect_conn = TRUE;
1124 #ifndef CURL_DISABLE_HTTP
1125 case CURLM_STATE_WAITPROXYCONNECT:
1126 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1127 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1129 if(easy->easy_conn->bits.proxy_connect_closed) {
1130 /* reset the error buffer */
1131 if(data->set.errorbuffer)
1132 data->set.errorbuffer[0] = '\0';
1133 data->state.errorbuf = FALSE;
1135 easy->result = CURLE_OK;
1136 result = CURLM_CALL_MULTI_PERFORM;
1137 multistate(easy, CURLM_STATE_CONNECT);
1139 else if(CURLE_OK == easy->result) {
1140 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1141 multistate(easy, CURLM_STATE_WAITCONNECT);
1146 case CURLM_STATE_WAITCONNECT:
1147 /* awaiting a completion of an asynch connect */
1148 easy->result = Curl_is_connected(easy->easy_conn,
1154 /* if everything is still fine we do the protocol-specific connect
1156 easy->result = Curl_protocol_connect(easy->easy_conn,
1160 if(CURLE_OK != easy->result) {
1161 /* failure detected */
1162 /* Just break, the cleaning up is handled all in one place */
1163 disconnect_conn = TRUE;
1168 if(!protocol_connect) {
1169 /* We have a TCP connection, but 'protocol_connect' may be false
1170 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1171 connect is TRUE, we move on to STATE_DO.
1172 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1174 #ifndef CURL_DISABLE_HTTP
1175 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1176 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1179 multistate(easy, CURLM_STATE_PROTOCONNECT);
1183 /* after the connect has completed, go WAITDO or DO */
1184 multistate(easy, multi->pipelining_enabled?
1185 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1187 result = CURLM_CALL_MULTI_PERFORM;
1191 case CURLM_STATE_PROTOCONNECT:
1192 /* protocol-specific connect phase */
1193 easy->result = Curl_protocol_connecting(easy->easy_conn,
1195 if((easy->result == CURLE_OK) && protocol_connect) {
1196 /* after the connect has completed, go WAITDO or DO */
1197 multistate(easy, multi->pipelining_enabled?
1198 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1199 result = CURLM_CALL_MULTI_PERFORM;
1201 else if(easy->result) {
1202 /* failure detected */
1203 Curl_posttransfer(data);
1204 Curl_done(&easy->easy_conn, easy->result, TRUE);
1205 disconnect_conn = TRUE;
1209 case CURLM_STATE_WAITDO:
1210 /* Wait for our turn to DO when we're pipelining requests */
1212 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
1213 easy->easy_conn->connection_id,
1214 easy->easy_conn->send_pipe->size,
1215 easy->easy_conn->writechannel_inuse?1:0,
1216 isHandleAtHead(data,
1217 easy->easy_conn->send_pipe)?1:0);
1219 if(!easy->easy_conn->writechannel_inuse &&
1220 isHandleAtHead(data,
1221 easy->easy_conn->send_pipe)) {
1222 /* Grab the channel */
1223 easy->easy_conn->writechannel_inuse = TRUE;
1224 multistate(easy, CURLM_STATE_DO);
1225 result = CURLM_CALL_MULTI_PERFORM;
1229 case CURLM_STATE_DO:
1230 if(data->set.connect_only) {
1231 /* keep connection open for application to use the socket */
1232 easy->easy_conn->bits.close = FALSE;
1233 multistate(easy, CURLM_STATE_DONE);
1234 easy->result = CURLE_OK;
1235 result = CURLM_CALL_MULTI_PERFORM;
1238 /* Perform the protocol's DO action */
1239 easy->result = Curl_do(&easy->easy_conn, &dophase_done);
1241 /* When Curl_do() returns failure, easy->easy_conn might be NULL! */
1243 if(CURLE_OK == easy->result) {
1245 /* some steps needed for wildcard matching */
1246 if(data->set.wildcardmatch) {
1247 struct WildcardData *wc = &data->wildcard;
1248 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1249 /* skip some states if it is important */
1250 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1251 multistate(easy, CURLM_STATE_DONE);
1252 result = CURLM_CALL_MULTI_PERFORM;
1256 /* DO was not completed in one function call, we must continue
1258 multistate(easy, CURLM_STATE_DOING);
1262 /* after DO, go DO_DONE... or DO_MORE */
1263 else if(easy->easy_conn->bits.do_more) {
1264 /* we're supposed to do more, but we need to sit down, relax
1265 and wait a little while first */
1266 multistate(easy, CURLM_STATE_DO_MORE);
1270 /* we're done with the DO, now DO_DONE */
1271 multistate(easy, CURLM_STATE_DO_DONE);
1272 result = CURLM_CALL_MULTI_PERFORM;
1275 else if((CURLE_SEND_ERROR == easy->result) &&
1276 easy->easy_conn->bits.reuse) {
1278 * In this situation, a connection that we were trying to use
1279 * may have unexpectedly died. If possible, send the connection
1280 * back to the CONNECT phase so we can try again.
1282 char *newurl = NULL;
1283 followtype follow=FOLLOW_NONE;
1287 drc = Curl_retry_request(easy->easy_conn, &newurl);
1289 /* a failure here pretty much implies an out of memory */
1291 disconnect_conn = TRUE;
1294 retry = (newurl)?TRUE:FALSE;
1296 Curl_posttransfer(data);
1297 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1299 /* When set to retry the connection, we must to go back to
1300 * the CONNECT state */
1302 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1303 follow = FOLLOW_RETRY;
1304 drc = Curl_follow(data, newurl, follow);
1305 if(drc == CURLE_OK) {
1306 multistate(easy, CURLM_STATE_CONNECT);
1307 result = CURLM_CALL_MULTI_PERFORM;
1308 easy->result = CURLE_OK;
1317 /* done didn't return OK or SEND_ERROR */
1323 /* Have error handler disconnect conn if we can't retry */
1324 disconnect_conn = TRUE;
1328 /* failure detected */
1329 Curl_posttransfer(data);
1331 Curl_done(&easy->easy_conn, easy->result, FALSE);
1332 disconnect_conn = TRUE;
1337 case CURLM_STATE_DOING:
1338 /* we continue DOING until the DO phase is complete */
1339 easy->result = Curl_protocol_doing(easy->easy_conn,
1341 if(CURLE_OK == easy->result) {
1343 /* after DO, go DO_DONE or DO_MORE */
1344 multistate(easy, easy->easy_conn->bits.do_more?
1345 CURLM_STATE_DO_MORE:
1346 CURLM_STATE_DO_DONE);
1347 result = CURLM_CALL_MULTI_PERFORM;
1348 } /* dophase_done */
1351 /* failure detected */
1352 Curl_posttransfer(data);
1353 Curl_done(&easy->easy_conn, easy->result, FALSE);
1354 disconnect_conn = TRUE;
1358 case CURLM_STATE_DO_MORE:
1360 * When we are connected, DO MORE and then go DO_DONE
1362 easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1364 /* No need to remove this handle from the send pipeline here since that
1365 is done in Curl_done() */
1366 if(CURLE_OK == easy->result) {
1368 multistate(easy, CURLM_STATE_DO_DONE);
1369 result = CURLM_CALL_MULTI_PERFORM;
1372 /* stay in DO_MORE */
1376 /* failure detected */
1377 Curl_posttransfer(data);
1378 Curl_done(&easy->easy_conn, easy->result, FALSE);
1379 disconnect_conn = TRUE;
1383 case CURLM_STATE_DO_DONE:
1384 /* Move ourselves from the send to recv pipeline */
1385 Curl_move_handle_from_send_to_recv_pipe(data, easy->easy_conn);
1386 /* Check if we can move pending requests to send pipe */
1387 Curl_multi_process_pending_handles(multi);
1388 multistate(easy, CURLM_STATE_WAITPERFORM);
1389 result = CURLM_CALL_MULTI_PERFORM;
1392 case CURLM_STATE_WAITPERFORM:
1393 /* Wait for our turn to PERFORM */
1394 if(!easy->easy_conn->readchannel_inuse &&
1395 isHandleAtHead(data,
1396 easy->easy_conn->recv_pipe)) {
1397 /* Grab the channel */
1398 easy->easy_conn->readchannel_inuse = TRUE;
1399 multistate(easy, CURLM_STATE_PERFORM);
1400 result = CURLM_CALL_MULTI_PERFORM;
1404 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
1405 easy->easy_conn->connection_id,
1406 easy->easy_conn->recv_pipe->size,
1407 easy->easy_conn->readchannel_inuse?1:0,
1408 isHandleAtHead(data,
1409 easy->easy_conn->recv_pipe)?1:0);
1414 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1415 /* if both rates are within spec, resume transfer */
1416 if(Curl_pgrsUpdate(easy->easy_conn))
1417 easy->result = CURLE_ABORTED_BY_CALLBACK;
1419 easy->result = Curl_speedcheck(data, now);
1421 if(( (data->set.max_send_speed == 0) ||
1422 (data->progress.ulspeed < data->set.max_send_speed )) &&
1423 ( (data->set.max_recv_speed == 0) ||
1424 (data->progress.dlspeed < data->set.max_recv_speed)))
1425 multistate(easy, CURLM_STATE_PERFORM);
1428 case CURLM_STATE_PERFORM:
1430 char *newurl = NULL;
1433 /* check if over send speed */
1434 if((data->set.max_send_speed > 0) &&
1435 (data->progress.ulspeed > data->set.max_send_speed)) {
1438 multistate(easy, CURLM_STATE_TOOFAST);
1440 /* calculate upload rate-limitation timeout. */
1441 buffersize = (int)(data->set.buffer_size ?
1442 data->set.buffer_size : BUFSIZE);
1443 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1444 data->progress.ulspeed, buffersize);
1445 Curl_expire(data, timeout_ms);
1449 /* check if over recv speed */
1450 if((data->set.max_recv_speed > 0) &&
1451 (data->progress.dlspeed > data->set.max_recv_speed)) {
1454 multistate(easy, CURLM_STATE_TOOFAST);
1456 /* Calculate download rate-limitation timeout. */
1457 buffersize = (int)(data->set.buffer_size ?
1458 data->set.buffer_size : BUFSIZE);
1459 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1460 data->progress.dlspeed, buffersize);
1461 Curl_expire(data, timeout_ms);
1465 /* read/write data if it is ready to do so */
1466 easy->result = Curl_readwrite(easy->easy_conn, &done);
1470 if(!(k->keepon & KEEP_RECV)) {
1471 /* We're done receiving */
1472 easy->easy_conn->readchannel_inuse = FALSE;
1475 if(!(k->keepon & KEEP_SEND)) {
1476 /* We're done sending */
1477 easy->easy_conn->writechannel_inuse = FALSE;
1480 if(done || (easy->result == CURLE_RECV_ERROR)) {
1481 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1482 * condition and the server closed the re-used connection exactly when
1483 * we wanted to use it, so figure out if that is indeed the case.
1485 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1487 retry = (newurl)?TRUE:FALSE;
1490 /* if we are to retry, set the result to OK and consider the
1492 easy->result = CURLE_OK;
1499 * The transfer phase returned error, we mark the connection to get
1500 * closed to prevent being re-used. This is because we can't possibly
1501 * know if the connection is in a good shape or not now. Unless it is
1502 * a protocol which uses two "channels" like FTP, as then the error
1503 * happened in the data connection.
1506 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1507 easy->easy_conn->bits.close = TRUE;
1509 Curl_posttransfer(data);
1510 Curl_done(&easy->easy_conn, easy->result, FALSE);
1513 followtype follow=FOLLOW_NONE;
1515 /* call this even if the readwrite function returned error */
1516 Curl_posttransfer(data);
1518 /* we're no longer receiving */
1519 Curl_removeHandleFromPipeline(data, easy->easy_conn->recv_pipe);
1521 /* expire the new receiving pipeline head */
1522 if(easy->easy_conn->recv_pipe->head)
1523 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1525 /* Check if we can move pending requests to send pipe */
1526 Curl_multi_process_pending_handles(multi);
1528 /* When we follow redirects or is set to retry the connection, we must
1529 to go back to the CONNECT state */
1530 if(data->req.newurl || retry) {
1532 /* if the URL is a follow-location and not just a retried request
1533 then figure out the URL here */
1534 newurl = data->req.newurl;
1535 data->req.newurl = NULL;
1536 follow = FOLLOW_REDIR;
1539 follow = FOLLOW_RETRY;
1540 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1541 if(CURLE_OK == easy->result) {
1542 easy->result = Curl_follow(data, newurl, follow);
1543 if(CURLE_OK == easy->result) {
1544 multistate(easy, CURLM_STATE_CONNECT);
1545 result = CURLM_CALL_MULTI_PERFORM;
1546 newurl = NULL; /* handed over the memory ownership to
1547 Curl_follow(), make sure we don't free() it
1553 /* after the transfer is done, go DONE */
1555 /* but first check to see if we got a location info even though we're
1556 not following redirects */
1557 if(data->req.location) {
1560 newurl = data->req.location;
1561 data->req.location = NULL;
1562 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1563 if(CURLE_OK == easy->result)
1564 newurl = NULL; /* allocation was handed over Curl_follow() */
1566 disconnect_conn = TRUE;
1569 multistate(easy, CURLM_STATE_DONE);
1570 result = CURLM_CALL_MULTI_PERFORM;
1579 case CURLM_STATE_DONE:
1581 if(easy->easy_conn) {
1582 /* Remove ourselves from the receive pipeline, if we are there. */
1583 Curl_removeHandleFromPipeline(data,
1584 easy->easy_conn->recv_pipe);
1585 /* Check if we can move pending requests to send pipe */
1586 Curl_multi_process_pending_handles(multi);
1588 if(easy->easy_conn->bits.stream_was_rewound) {
1589 /* This request read past its response boundary so we quickly let
1590 the other requests consume those bytes since there is no
1591 guarantee that the socket will become active again */
1592 result = CURLM_CALL_MULTI_PERFORM;
1595 /* post-transfer command */
1596 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1598 * If there are other handles on the pipeline, Curl_done won't set
1599 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1600 * access free'd data, if the connection is free'd and the handle
1601 * removed before we perform the processing in CURLM_STATE_COMPLETED
1604 easy->easy_conn = NULL;
1607 if(data->set.wildcardmatch) {
1608 if(data->wildcard.state != CURLWC_DONE) {
1609 /* if a wildcard is set and we are not ending -> lets start again
1610 with CURLM_STATE_INIT */
1611 result = CURLM_CALL_MULTI_PERFORM;
1612 multistate(easy, CURLM_STATE_INIT);
1617 /* after we have DONE what we're supposed to do, go COMPLETED, and
1618 it doesn't matter what the Curl_done() returned! */
1619 multistate(easy, CURLM_STATE_COMPLETED);
1623 case CURLM_STATE_COMPLETED:
1624 /* this is a completed transfer, it is likely to still be connected */
1626 /* This node should be delinked from the list now and we should post
1627 an information message that we are complete. */
1629 /* Important: reset the conn pointer so that we don't point to memory
1630 that could be freed anytime */
1631 easy->easy_conn = NULL;
1633 Curl_expire(data, 0); /* stop all timers */
1636 case CURLM_STATE_MSGSENT:
1637 return CURLM_OK; /* do nothing */
1640 return CURLM_INTERNAL_ERROR;
1643 if(easy->state < CURLM_STATE_COMPLETED) {
1644 if(CURLE_OK != easy->result) {
1646 * If an error was returned, and we aren't in completed state now,
1647 * then we go to completed and consider this transfer aborted.
1650 /* NOTE: no attempt to disconnect connections must be made
1651 in the case blocks above - cleanup happens only here */
1653 data->state.pipe_broke = FALSE;
1655 if(easy->easy_conn) {
1656 /* if this has a connection, unsubscribe from the pipelines */
1657 easy->easy_conn->writechannel_inuse = FALSE;
1658 easy->easy_conn->readchannel_inuse = FALSE;
1659 Curl_removeHandleFromPipeline(data,
1660 easy->easy_conn->send_pipe);
1661 Curl_removeHandleFromPipeline(data,
1662 easy->easy_conn->recv_pipe);
1663 /* Check if we can move pending requests to send pipe */
1664 Curl_multi_process_pending_handles(multi);
1666 if(disconnect_conn) {
1667 /* disconnect properly */
1668 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1670 /* This is where we make sure that the easy_conn pointer is reset.
1671 We don't have to do this in every case block above where a
1672 failure is detected */
1673 easy->easy_conn = NULL;
1676 else if(easy->state == CURLM_STATE_CONNECT) {
1677 /* Curl_connect() failed */
1678 (void)Curl_posttransfer(data);
1681 multistate(easy, CURLM_STATE_COMPLETED);
1683 /* if there's still a connection to use, call the progress function */
1684 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1685 /* aborted due to progress callback return code must close the
1687 easy->easy_conn->bits.close = TRUE;
1689 /* if not yet in DONE state, go there, otherwise COMPLETED */
1690 multistate(easy, (easy->state < CURLM_STATE_DONE)?
1691 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1692 result = CURLM_CALL_MULTI_PERFORM;
1695 } WHILE_FALSE; /* just to break out from! */
1697 if(CURLM_STATE_COMPLETED == easy->state) {
1698 /* now fill in the Curl_message with this info */
1701 msg->extmsg.msg = CURLMSG_DONE;
1702 msg->extmsg.easy_handle = data;
1703 msg->extmsg.data.result = easy->result;
1705 result = multi_addmsg(multi, msg);
1707 multistate(easy, CURLM_STATE_MSGSENT);
1714 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1716 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1717 struct Curl_one_easy *easy;
1718 CURLMcode returncode=CURLM_OK;
1719 struct Curl_tree *t;
1720 struct timeval now = Curl_tvnow();
1722 if(!GOOD_MULTI_HANDLE(multi))
1723 return CURLM_BAD_HANDLE;
1725 easy=multi->easy.next;
1726 while(easy != &multi->easy) {
1728 struct WildcardData *wc = &easy->easy_handle->wildcard;
1730 if(easy->easy_handle->set.wildcardmatch) {
1732 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1734 return CURLM_OUT_OF_MEMORY;
1739 result = multi_runsingle(multi, now, easy);
1740 while(CURLM_CALL_MULTI_PERFORM == result);
1742 if(easy->easy_handle->set.wildcardmatch) {
1743 /* destruct wildcard structures if it is needed */
1744 if(wc->state == CURLWC_DONE || result)
1745 Curl_wildcard_dtor(wc);
1749 returncode = result;
1751 easy = easy->next; /* operate on next handle */
1755 * Simply remove all expired timers from the splay since handles are dealt
1756 * with unconditionally by this function and curl_multi_timeout() requires
1757 * that already passed/handled expire times are removed from the splay.
1759 * It is important that the 'now' value is set at the entry of this function
1760 * and not for the current time as it may have ticked a little while since
1761 * then and then we risk this loop to remove timers that actually have not
1765 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1767 /* the removed may have another timeout in queue */
1768 (void)add_next_timeout(now, multi, t->payload);
1772 *running_handles = multi->num_alive;
1774 if(CURLM_OK >= returncode)
1775 update_timer(multi);
1780 static void close_all_connections(struct Curl_multi *multi)
1782 struct connectdata *conn;
1784 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1786 conn->data = multi->closure_handle;
1788 /* This will remove the connection from the cache */
1789 (void)Curl_disconnect(conn, FALSE);
1791 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1795 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1797 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1798 struct Curl_one_easy *easy;
1799 struct Curl_one_easy *nexteasy;
1801 if(GOOD_MULTI_HANDLE(multi)) {
1802 multi->type = 0; /* not good anymore */
1804 /* Close all the connections in the connection cache */
1805 close_all_connections(multi);
1807 if(multi->closure_handle) {
1808 multi->closure_handle->dns.hostcache = multi->hostcache;
1809 Curl_hostcache_clean(multi->closure_handle);
1811 Curl_close(multi->closure_handle);
1812 multi->closure_handle = NULL;
1815 Curl_hash_destroy(multi->sockhash);
1816 multi->sockhash = NULL;
1818 Curl_conncache_destroy(multi->conn_cache);
1819 multi->conn_cache = NULL;
1821 /* remove the pending list of messages */
1822 Curl_llist_destroy(multi->msglist, NULL);
1823 multi->msglist = NULL;
1825 /* remove all easy handles */
1826 easy = multi->easy.next;
1827 while(easy != &multi->easy) {
1828 nexteasy=easy->next;
1829 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1830 /* clear out the usage of the shared DNS cache */
1831 Curl_hostcache_clean(easy->easy_handle);
1832 easy->easy_handle->dns.hostcache = NULL;
1833 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1836 /* Clear the pointer to the connection cache */
1837 easy->easy_handle->state.conn_cache = NULL;
1839 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1845 Curl_hash_destroy(multi->hostcache);
1846 multi->hostcache = NULL;
1848 /* Free the blacklists by setting them to NULL */
1849 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1850 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1857 return CURLM_BAD_HANDLE;
1861 * curl_multi_info_read()
1863 * This function is the primary way for a multi/multi_socket application to
1864 * figure out if a transfer has ended. We MUST make this function as fast as
1865 * possible as it will be polled frequently and we MUST NOT scan any lists in
1866 * here to figure out things. We must scale fine to thousands of handles and
1867 * beyond. The current design is fully O(1).
1870 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1872 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1873 struct Curl_message *msg;
1875 *msgs_in_queue = 0; /* default to none */
1877 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1878 /* there is one or more messages in the list */
1879 struct curl_llist_element *e;
1881 /* extract the head of the list to return */
1882 e = multi->msglist->head;
1886 /* remove the extracted entry */
1887 Curl_llist_remove(multi->msglist, e, NULL);
1889 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1891 return &msg->extmsg;
1898 * singlesocket() checks what sockets we deal with and their "action state"
1899 * and if we have a different state in any of those sockets from last time we
1900 * call the callback accordingly.
1902 static void singlesocket(struct Curl_multi *multi,
1903 struct Curl_one_easy *easy)
1905 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1907 struct Curl_sh_entry *entry;
1910 unsigned int curraction;
1911 struct Curl_one_easy *easy_by_hash;
1912 bool remove_sock_from_hash;
1914 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1915 socks[i] = CURL_SOCKET_BAD;
1917 /* Fill in the 'current' struct with the state as it is now: what sockets to
1918 supervise and for what actions */
1919 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1921 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1922 sockets we should have from now on. Detect the differences, remove no
1923 longer supervised ones and add new ones */
1925 /* walk over the sockets we got right now */
1926 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1927 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1929 int action = CURL_POLL_NONE;
1933 /* get it from the hash */
1934 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1936 if(curraction & GETSOCK_READSOCK(i))
1937 action |= CURL_POLL_IN;
1938 if(curraction & GETSOCK_WRITESOCK(i))
1939 action |= CURL_POLL_OUT;
1942 /* yeps, already present so check if it has the same action set */
1943 if(entry->action == action)
1944 /* same, continue */
1948 /* this is a socket we didn't have before, add it! */
1949 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1955 /* we know (entry != NULL) at this point, see the logic above */
1956 if(multi->socket_cb)
1957 multi->socket_cb(easy->easy_handle,
1960 multi->socket_userp,
1963 entry->action = action; /* store the current action state */
1966 num = i; /* number of sockets */
1968 /* when we've walked over all the sockets we should have right now, we must
1969 make sure to detect sockets that are removed */
1970 for(i=0; i< easy->numsocks; i++) {
1972 s = easy->sockets[i];
1973 for(j=0; j<num; j++) {
1975 /* this is still supervised */
1976 s = CURL_SOCKET_BAD;
1980 if(s != CURL_SOCKET_BAD) {
1982 /* this socket has been removed. Tell the app to remove it */
1983 remove_sock_from_hash = TRUE;
1985 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1987 /* check if the socket to be removed serves a connection which has
1988 other easy-s in a pipeline. In this case the socket should not be
1990 struct connectdata *easy_conn;
1992 easy_by_hash = entry->easy->multi_pos;
1993 easy_conn = easy_by_hash->easy_conn;
1995 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1996 /* the handle should not be removed from the pipe yet */
1997 remove_sock_from_hash = FALSE;
1999 /* Update the sockhash entry to instead point to the next in line
2000 for the recv_pipe, or the first (in case this particular easy
2002 if(entry->easy == easy->easy_handle) {
2003 if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
2004 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2006 entry->easy = easy_conn->recv_pipe->head->ptr;
2009 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2010 /* the handle should not be removed from the pipe yet */
2011 remove_sock_from_hash = FALSE;
2013 /* Update the sockhash entry to instead point to the next in line
2014 for the send_pipe, or the first (in case this particular easy
2016 if(entry->easy == easy->easy_handle) {
2017 if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
2018 entry->easy = easy_conn->send_pipe->head->next->ptr;
2020 entry->easy = easy_conn->send_pipe->head->ptr;
2023 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2024 when action will be asked on the socket (see multi_socket()), the
2025 head of the correct pipe will be taken according to the
2030 /* just a precaution, this socket really SHOULD be in the hash already
2031 but in case it isn't, we don't have to tell the app to remove it
2032 either since it never got to know about it */
2033 remove_sock_from_hash = FALSE;
2035 if(remove_sock_from_hash) {
2036 /* in this case 'entry' is always non-NULL */
2037 if(multi->socket_cb)
2038 multi->socket_cb(easy->easy_handle,
2041 multi->socket_userp,
2043 sh_delentry(multi->sockhash, s);
2049 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2050 easy->numsocks = num;
2054 * add_next_timeout()
2056 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2057 * when it has just been removed from the splay tree because the timeout has
2058 * expired. This function is then to advance in the list to pick the next
2059 * timeout to use (skip the already expired ones) and add this node back to
2060 * the splay tree again.
2062 * The splay tree only has each sessionhandle as a single node and the nearest
2063 * timeout is used to sort it on.
2065 static CURLMcode add_next_timeout(struct timeval now,
2066 struct Curl_multi *multi,
2067 struct SessionHandle *d)
2069 struct timeval *tv = &d->state.expiretime;
2070 struct curl_llist *list = d->state.timeoutlist;
2071 struct curl_llist_element *e;
2073 /* move over the timeout list for this specific handle and remove all
2074 timeouts that are now passed tense and store the next pending
2076 for(e = list->head; e; ) {
2077 struct curl_llist_element *n = e->next;
2078 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2080 /* remove outdated entry */
2081 Curl_llist_remove(list, e, NULL);
2083 /* the list is sorted so get out on the first mismatch */
2089 /* clear the expire times within the handles that we remove from the
2095 /* copy the first entry to 'tv' */
2096 memcpy(tv, e->ptr, sizeof(*tv));
2098 /* remove first entry from list */
2099 Curl_llist_remove(list, e, NULL);
2101 /* insert this node again into the splay */
2102 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2103 &d->state.timenode);
2109 static CURLMcode multi_socket(struct Curl_multi *multi,
2113 int *running_handles)
2115 CURLMcode result = CURLM_OK;
2116 struct SessionHandle *data = NULL;
2117 struct Curl_tree *t;
2118 struct timeval now = Curl_tvnow();
2121 struct Curl_one_easy *easyp;
2122 /* *perform() deals with running_handles on its own */
2123 result = curl_multi_perform(multi, running_handles);
2125 /* walk through each easy handle and do the socket state change magic
2127 easyp=multi->easy.next;
2128 while(easyp != &multi->easy) {
2129 singlesocket(multi, easyp);
2130 easyp = easyp->next;
2133 /* or should we fall-through and do the timer-based stuff? */
2136 else if(s != CURL_SOCKET_TIMEOUT) {
2138 struct Curl_sh_entry *entry =
2139 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2142 /* Unmatched socket, we can't act on it but we ignore this fact. In
2143 real-world tests it has been proved that libevent can in fact give
2144 the application actions even though the socket was just previously
2145 asked to get removed, so thus we better survive stray socket actions
2146 and just move on. */
2151 if(data->magic != CURLEASY_MAGIC_NUMBER)
2152 /* bad bad bad bad bad bad bad */
2153 return CURLM_INTERNAL_ERROR;
2155 /* If the pipeline is enabled, take the handle which is in the head of
2156 the pipeline. If we should write into the socket, take the send_pipe
2157 head. If we should read from the socket, take the recv_pipe head. */
2158 if(data->set.one_easy->easy_conn) {
2159 if((ev_bitmask & CURL_POLL_OUT) &&
2160 data->set.one_easy->easy_conn->send_pipe &&
2161 data->set.one_easy->easy_conn->send_pipe->head)
2162 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2163 else if((ev_bitmask & CURL_POLL_IN) &&
2164 data->set.one_easy->easy_conn->recv_pipe &&
2165 data->set.one_easy->easy_conn->recv_pipe->head)
2166 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2169 if(data->set.one_easy->easy_conn &&
2170 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2171 /* set socket event bitmask if they're not locked */
2172 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2175 result = multi_runsingle(multi, now, data->set.one_easy);
2176 while(CURLM_CALL_MULTI_PERFORM == result);
2178 if(data->set.one_easy->easy_conn &&
2179 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2180 /* clear the bitmask only if not locked */
2181 data->set.one_easy->easy_conn->cselect_bits = 0;
2183 if(CURLM_OK >= result)
2184 /* get the socket(s) and check if the state has been changed since
2186 singlesocket(multi, data->set.one_easy);
2188 /* Now we fall-through and do the timer-based stuff, since we don't want
2189 to force the user to have to deal with timeouts as long as at least
2190 one connection in fact has traffic. */
2192 data = NULL; /* set data to NULL again to avoid calling
2193 multi_runsingle() in case there's no need to */
2197 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2198 triggered too early */
2199 if(now.tv_usec >= 1000000) {
2201 now.tv_usec -= 1000000;
2205 * The loop following here will go on as long as there are expire-times left
2206 * to process in the splay and 'data' will be re-assigned for every expired
2207 * handle we deal with.
2210 /* the first loop lap 'data' can be NULL */
2213 result = multi_runsingle(multi, now, data->set.one_easy);
2214 while(CURLM_CALL_MULTI_PERFORM == result);
2216 if(CURLM_OK >= result)
2217 /* get the socket(s) and check if the state has been changed since
2219 singlesocket(multi, data->set.one_easy);
2222 /* Check if there's one (more) expired timer to deal with! This function
2223 extracts a matching node if there is one */
2225 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2227 data = t->payload; /* assign this for next loop */
2228 (void)add_next_timeout(now, multi, t->payload);
2233 *running_handles = multi->num_alive;
2237 #undef curl_multi_setopt
2238 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2239 CURLMoption option, ...)
2241 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2242 CURLMcode res = CURLM_OK;
2245 if(!GOOD_MULTI_HANDLE(multi))
2246 return CURLM_BAD_HANDLE;
2248 va_start(param, option);
2251 case CURLMOPT_SOCKETFUNCTION:
2252 multi->socket_cb = va_arg(param, curl_socket_callback);
2254 case CURLMOPT_SOCKETDATA:
2255 multi->socket_userp = va_arg(param, void *);
2257 case CURLMOPT_PIPELINING:
2258 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2260 case CURLMOPT_TIMERFUNCTION:
2261 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2263 case CURLMOPT_TIMERDATA:
2264 multi->timer_userp = va_arg(param, void *);
2266 case CURLMOPT_MAXCONNECTS:
2267 multi->maxconnects = va_arg(param, long);
2269 case CURLMOPT_MAX_HOST_CONNECTIONS:
2270 multi->max_host_connections = va_arg(param, long);
2272 case CURLMOPT_MAX_PIPELINE_LENGTH:
2273 multi->max_pipeline_length = va_arg(param, long);
2275 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2276 multi->content_length_penalty_size = va_arg(param, long);
2278 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2279 multi->chunk_length_penalty_size = va_arg(param, long);
2281 case CURLMOPT_PIPELINING_SITE_BL:
2282 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2283 &multi->pipelining_site_bl);
2285 case CURLMOPT_PIPELINING_SERVER_BL:
2286 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2287 &multi->pipelining_server_bl);
2289 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2290 multi->max_total_connections = va_arg(param, long);
2293 res = CURLM_UNKNOWN_OPTION;
2300 /* we define curl_multi_socket() in the public multi.h header */
2301 #undef curl_multi_socket
2303 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2304 int *running_handles)
2306 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2307 0, running_handles);
2308 if(CURLM_OK >= result)
2309 update_timer((struct Curl_multi *)multi_handle);
2313 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2314 int ev_bitmask, int *running_handles)
2316 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2317 ev_bitmask, running_handles);
2318 if(CURLM_OK >= result)
2319 update_timer((struct Curl_multi *)multi_handle);
2323 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2326 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2327 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2328 if(CURLM_OK >= result)
2329 update_timer((struct Curl_multi *)multi_handle);
2333 static CURLMcode multi_timeout(struct Curl_multi *multi,
2336 static struct timeval tv_zero = {0,0};
2338 if(multi->timetree) {
2339 /* we have a tree of expire times */
2340 struct timeval now = Curl_tvnow();
2342 /* splay the lowest to the bottom */
2343 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2345 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2346 /* some time left before expiration */
2347 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2350 * Since we only provide millisecond resolution on the returned value
2351 * and the diff might be less than one millisecond here, we don't
2352 * return zero as that may cause short bursts of busyloops on fast
2353 * processors while the diff is still present but less than one
2354 * millisecond! instead we return 1 until the time is ripe.
2359 /* 0 means immediately */
2368 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2371 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2373 /* First, make some basic checks that the CURLM handle is a good handle */
2374 if(!GOOD_MULTI_HANDLE(multi))
2375 return CURLM_BAD_HANDLE;
2377 return multi_timeout(multi, timeout_ms);
2381 * Tell the application it should update its timers, if it subscribes to the
2382 * update timer callback.
2384 static int update_timer(struct Curl_multi *multi)
2388 if(!multi->timer_cb)
2390 if(multi_timeout(multi, &timeout_ms)) {
2393 if(timeout_ms < 0) {
2394 static const struct timeval none={0,0};
2395 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2396 multi->timer_lastcall = none;
2397 /* there's no timeout now but there was one previously, tell the app to
2399 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2404 /* When multi_timeout() is done, multi->timetree points to the node with the
2405 * timeout we got the (relative) time-out time for. We can thus easily check
2406 * if this is the same (fixed) time as we got in a previous call and then
2407 * avoid calling the callback again. */
2408 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2411 multi->timer_lastcall = multi->timetree->key;
2413 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2416 void Curl_multi_set_easy_connection(struct SessionHandle *handle,
2417 struct connectdata *conn)
2419 handle->set.one_easy->easy_conn = conn;
2422 static bool isHandleAtHead(struct SessionHandle *handle,
2423 struct curl_llist *pipeline)
2425 struct curl_llist_element *curr = pipeline->head;
2427 return (curr->ptr == handle) ? TRUE : FALSE;
2433 * multi_freetimeout()
2435 * Callback used by the llist system when a single timeout list entry is
2438 static void multi_freetimeout(void *user, void *entryptr)
2442 /* the entry was plain malloc()'ed */
2447 * multi_addtimeout()
2449 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2450 * of list is always the timeout nearest in time.
2454 multi_addtimeout(struct curl_llist *timeoutlist,
2455 struct timeval *stamp)
2457 struct curl_llist_element *e;
2458 struct timeval *timedup;
2459 struct curl_llist_element *prev = NULL;
2461 timedup = malloc(sizeof(*timedup));
2463 return CURLM_OUT_OF_MEMORY;
2465 /* copy the timestamp */
2466 memcpy(timedup, stamp, sizeof(*timedup));
2468 if(Curl_llist_count(timeoutlist)) {
2469 /* find the correct spot in the list */
2470 for(e = timeoutlist->head; e; e = e->next) {
2471 struct timeval *checktime = e->ptr;
2472 long diff = curlx_tvdiff(*checktime, *timedup);
2480 this is the first timeout on the list */
2482 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2484 return CURLM_OUT_OF_MEMORY;
2493 * given a number of milliseconds from now to use to set the 'act before
2494 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2496 * Note that the timeout will be added to a queue of timeouts if it defines a
2497 * moment in time that is later than the current head of queue.
2499 * Pass zero to clear all timeout values for this handle.
2501 void Curl_expire(struct SessionHandle *data, long milli)
2503 struct Curl_multi *multi = data->multi;
2504 struct timeval *nowp = &data->state.expiretime;
2507 /* this is only interesting for multi-interface using libcurl, and only
2508 while there is still a multi interface struct remaining! */
2513 /* No timeout, clear the time data. */
2514 if(nowp->tv_sec || nowp->tv_usec) {
2515 /* Since this is an cleared time, we must remove the previous entry from
2517 struct curl_llist *list = data->state.timeoutlist;
2519 rc = Curl_splayremovebyaddr(multi->timetree,
2520 &data->state.timenode,
2523 infof(data, "Internal error clearing splay node = %d\n", rc);
2525 /* flush the timeout list too */
2526 while(list->size > 0)
2527 Curl_llist_remove(list, list->tail, NULL);
2530 infof(data, "Expire cleared\n");
2540 set.tv_sec += milli/1000;
2541 set.tv_usec += (milli%1000)*1000;
2543 if(set.tv_usec >= 1000000) {
2545 set.tv_usec -= 1000000;
2548 if(nowp->tv_sec || nowp->tv_usec) {
2549 /* This means that the struct is added as a node in the splay tree.
2550 Compare if the new time is earlier, and only remove-old/add-new if it
2552 long diff = curlx_tvdiff(set, *nowp);
2554 /* the new expire time was later so just add it to the queue
2556 multi_addtimeout(data->state.timeoutlist, &set);
2560 /* the new time is newer than the presently set one, so add the current
2561 to the queue and update the head */
2562 multi_addtimeout(data->state.timeoutlist, nowp);
2564 /* Since this is an updated time, we must remove the previous entry from
2565 the splay tree first and then re-add the new value */
2566 rc = Curl_splayremovebyaddr(multi->timetree,
2567 &data->state.timenode,
2570 infof(data, "Internal error removing splay node = %d\n", rc);
2574 data->state.timenode.payload = data;
2575 multi->timetree = Curl_splayinsert(*nowp,
2577 &data->state.timenode);
2580 Curl_splayprint(multi->timetree, 0, TRUE);
2584 CURLMcode curl_multi_assign(CURLM *multi_handle,
2585 curl_socket_t s, void *hashp)
2587 struct Curl_sh_entry *there = NULL;
2588 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2590 if(s != CURL_SOCKET_BAD)
2591 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2594 return CURLM_BAD_SOCKET;
2596 there->socketp = hashp;
2601 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2603 return multi ? multi->max_host_connections : 0;
2606 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2608 return multi ? multi->max_total_connections : 0;
2611 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2613 return multi ? multi->max_pipeline_length : 0;
2616 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2618 return multi ? multi->content_length_penalty_size : 0;
2621 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2623 return multi ? multi->chunk_length_penalty_size : 0;
2626 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2628 return multi->pipelining_site_bl;
2631 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2633 return multi->pipelining_server_bl;
2636 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2638 struct Curl_one_easy *easy;
2640 easy=multi->easy.next;
2641 while(easy != &multi->easy) {
2642 if(easy->state == CURLM_STATE_CONNECT_PEND) {
2643 multistate(easy, CURLM_STATE_CONNECT);
2644 /* Make sure that the handle will be processed soonish. */
2645 Curl_expire(easy->easy_handle, 1);
2647 easy = easy->next; /* operate on next handle */
2652 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2654 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2655 struct Curl_one_easy *easy;
2657 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2658 multi->num_easy, multi->num_alive);
2659 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2660 if(easy->state < CURLM_STATE_COMPLETED) {
2661 /* only display handles that are not completed */
2662 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2663 (void *)easy->easy_handle,
2664 statename[easy->state], easy->numsocks);
2665 for(i=0; i < easy->numsocks; i++) {
2666 curl_socket_t s = easy->sockets[i];
2667 struct Curl_sh_entry *entry =
2668 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2670 fprintf(stderr, "%d ", (int)s);
2672 fprintf(stderr, "INTERNAL CONFUSION\n");
2675 fprintf(stderr, "[%s %s] ",
2676 entry->action&CURL_POLL_IN?"RECVING":"",
2677 entry->action&CURL_POLL_OUT?"SENDING":"");
2680 fprintf(stderr, "\n");