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"
44 #define _MPRINTF_REPLACE /* use our functions only */
45 #include <curl/mprintf.h>
47 #include "curl_memory.h"
48 /* The last #include file should be: */
52 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
53 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
54 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
56 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
57 #define CURL_SOCKET_HASH_TABLE_SIZE 911
61 #define CURL_MULTI_HANDLE 0x000bab1e
63 #define GOOD_MULTI_HANDLE(x) \
64 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
65 #define GOOD_EASY_HANDLE(x) \
66 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
68 static void singlesocket(struct Curl_multi *multi,
69 struct Curl_one_easy *easy);
70 static int update_timer(struct Curl_multi *multi);
72 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
73 struct connectdata *conn);
74 static int checkPendPipeline(struct connectdata *conn);
75 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
76 struct connectdata *conn);
77 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
78 struct connectdata *conn);
79 static bool isHandleAtHead(struct SessionHandle *handle,
80 struct curl_llist *pipeline);
81 static CURLMcode add_next_timeout(struct timeval now,
82 struct Curl_multi *multi,
83 struct SessionHandle *d);
86 static const char * const statename[]={
107 static void multi_freetimeout(void *a, void *b);
109 /* always use this function to change state, to make debugging easier */
110 static void mstate(struct Curl_one_easy *easy, CURLMstate state
117 long connection_id = -5000;
119 CURLMstate oldstate = easy->state;
121 if(oldstate == state)
122 /* don't bother when the new state is the same as the old state */
128 if(easy->easy_conn) {
129 if(easy->state > CURLM_STATE_CONNECT &&
130 easy->state < CURLM_STATE_COMPLETED)
131 connection_id = easy->easy_conn->connection_id;
133 infof(easy->easy_handle,
134 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
135 statename[oldstate], statename[easy->state],
136 (char *)easy, lineno, connection_id);
139 if(state == CURLM_STATE_COMPLETED)
140 /* changing to COMPLETED means there's one less easy handle 'alive' */
141 easy->easy_handle->multi->num_alive--;
145 #define multistate(x,y) mstate(x,y)
147 #define multistate(x,y) mstate(x,y, __LINE__)
151 * We add one of these structs to the sockhash for a particular socket
154 struct Curl_sh_entry {
155 struct SessionHandle *easy;
157 int action; /* what action READ/WRITE this socket waits for */
158 curl_socket_t socket; /* mainly to ease debugging */
159 void *socketp; /* settable by users with curl_multi_assign() */
161 /* bits for 'action' having no bits means this socket is not expecting any
166 /* make sure this socket is present in the hash for this handle */
167 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
169 struct SessionHandle *data)
171 struct Curl_sh_entry *there =
172 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
173 struct Curl_sh_entry *check;
176 /* it is present, return fine */
179 /* not present, add it */
180 check = calloc(1, sizeof(struct Curl_sh_entry));
182 return NULL; /* major failure */
186 /* make/add new hash entry */
187 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
189 return NULL; /* major failure */
192 return check; /* things are good in sockhash land */
196 /* delete the given socket + handle from the hash */
197 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
199 struct Curl_sh_entry *there =
200 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
203 /* this socket is in the hash */
204 /* We remove the hash entry. (This'll end up in a call to
206 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
211 * free a sockhash entry
213 static void sh_freeentry(void *freethis)
215 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
221 static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
223 (void) k1_len; (void) k2_len;
225 return (*((int* ) k1)) == (*((int* ) k2));
228 static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
230 int fd = * ((int* ) key);
233 return (fd % (int)slots_num);
237 * sh_init() creates a new socket hash and returns the handle for it.
239 * Quote from README.multi_socket:
241 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
242 * is somewhat of a bottle neck. Its current implementation may be a bit too
243 * limiting. It simply has a fixed-size array, and on each entry in the array
244 * it has a linked list with entries. So the hash only checks which list to
245 * scan through. The code I had used so for used a list with merely 7 slots
246 * (as that is what the DNS hash uses) but with 7000 connections that would
247 * make an average of 1000 nodes in each list to run through. I upped that to
248 * 97 slots (I believe a prime is suitable) and noticed a significant speed
249 * increase. I need to reconsider the hash implementation or use a rather
250 * large default value like this. At 9000 connections I was still below 10us
254 static struct curl_hash *sh_init(void)
256 return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
263 * Called when a transfer is completed. Adds the given msg pointer to
264 * the list kept in the multi handle.
266 static CURLMcode multi_addmsg(struct Curl_multi *multi,
267 struct Curl_message *msg)
269 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
270 return CURLM_OUT_OF_MEMORY;
278 * Callback used by the llist system when a single list entry is destroyed.
280 static void multi_freeamsg(void *a, void *b)
286 CURLM *curl_multi_init(void)
288 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
293 multi->type = CURL_MULTI_HANDLE;
295 multi->hostcache = Curl_mk_dnscache();
296 if(!multi->hostcache)
299 multi->sockhash = sh_init();
303 multi->conn_cache = Curl_conncache_init();
304 if(!multi->conn_cache)
307 multi->msglist = Curl_llist_alloc(multi_freeamsg);
311 /* Let's make the doubly-linked list a circular list. This makes
312 the linked list code simpler and allows inserting at the end
313 with less work (we didn't keep a tail pointer before). */
314 multi->easy.next = &multi->easy;
315 multi->easy.prev = &multi->easy;
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 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
335 struct curl_llist *timeoutlist;
336 struct Curl_one_easy *easy;
337 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
338 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
339 struct SessionHandle *new_closure = NULL;
340 struct curl_hash *hostcache = NULL;
342 /* First, make some basic checks that the CURLM handle is a good handle */
343 if(!GOOD_MULTI_HANDLE(multi))
344 return CURLM_BAD_HANDLE;
346 /* Verify that we got a somewhat good easy handle too */
347 if(!GOOD_EASY_HANDLE(easy_handle))
348 return CURLM_BAD_EASY_HANDLE;
350 /* Prevent users from adding same easy handle more than
351 once and prevent adding to more than one multi stack */
353 /* possibly we should create a new unique error code for this condition */
354 return CURLM_BAD_EASY_HANDLE;
356 /* Allocate and initialize timeout list for easy handle */
357 timeoutlist = Curl_llist_alloc(multi_freetimeout);
359 return CURLM_OUT_OF_MEMORY;
361 /* Allocate new node for the doubly-linked circular list of
362 Curl_one_easy structs that holds pointers to easy handles */
363 easy = calloc(1, sizeof(struct Curl_one_easy));
365 Curl_llist_destroy(timeoutlist, NULL);
366 return CURLM_OUT_OF_MEMORY;
369 /* In case multi handle has no hostcache yet, allocate one */
370 if(!multi->hostcache) {
371 hostcache = Curl_mk_dnscache();
374 Curl_llist_destroy(timeoutlist, NULL);
375 return CURLM_OUT_OF_MEMORY;
379 /* In case multi handle has no closure_handle yet, allocate
380 a new easy handle to use when closing cached connections */
381 if(!multi->closure_handle) {
382 new_closure = (struct SessionHandle *)curl_easy_init();
384 Curl_hash_destroy(hostcache);
386 Curl_llist_destroy(timeoutlist, NULL);
387 return CURLM_OUT_OF_MEMORY;
392 ** No failure allowed in this function beyond this point. And
393 ** no modification of easy nor multi handle allowed before this
394 ** except for potential multi's connection cache growing which
395 ** won't be undone in this function no matter what.
398 /* In case a new closure handle has been initialized above, it
399 is associated now with the multi handle which lacked one. */
401 multi->closure_handle = new_closure;
402 Curl_easy_addmulti(multi->closure_handle, multi_handle);
403 multi->closure_handle->state.conn_cache = multi->conn_cache;
406 /* In case hostcache has been allocated above,
407 it is associated now with the multi handle. */
409 multi->hostcache = hostcache;
411 /* Make easy handle use timeout list initialized above */
412 data->state.timeoutlist = timeoutlist;
415 /* set the easy handle */
416 easy->easy_handle = data;
417 multistate(easy, CURLM_STATE_INIT);
419 /* set the back pointer to one_easy to assist in removal */
420 easy->easy_handle->multi_pos = easy;
422 /* for multi interface connections, we share DNS cache automatically if the
423 easy handle's one is currently not set. */
424 if(!easy->easy_handle->dns.hostcache ||
425 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
426 easy->easy_handle->dns.hostcache = multi->hostcache;
427 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
430 /* Point to the multi's connection cache */
431 easy->easy_handle->state.conn_cache = multi->conn_cache;
433 /* This adds the new entry at the 'end' of the doubly-linked circular
434 list of Curl_one_easy structs to try and maintain a FIFO queue so
435 the pipelined requests are in order. */
437 /* We add this new entry last in the list. We make our 'next' point to the
438 'first' struct and our 'prev' point to the previous 'prev' */
439 easy->next = &multi->easy;
440 easy->prev = multi->easy.prev;
442 /* make 'easy' the last node in the chain */
443 multi->easy.prev = easy;
445 /* if there was a prev node, make sure its 'next' pointer links to
447 easy->prev->next = easy;
449 /* make the SessionHandle refer back to this multi handle */
450 Curl_easy_addmulti(easy_handle, multi_handle);
452 /* make the SessionHandle struct refer back to this struct */
453 easy->easy_handle->set.one_easy = easy;
455 /* Set the timeout for this handle to expire really soon so that it will
456 be taken care of even when this handle is added in the midst of operation
457 when only the curl_multi_socket() API is used. During that flow, only
458 sockets that time-out or have actions will be dealt with. Since this
459 handle has no action yet, we make sure it times out to get things to
461 Curl_expire(easy->easy_handle, 1);
463 /* increase the node-counter */
466 /* increase the alive-counter */
469 /* A somewhat crude work-around for a little glitch in update_timer() that
470 happens if the lastcall time is set to the same time when the handle is
471 removed as when the next handle is added, as then the check in
472 update_timer() that prevents calling the application multiple times with
473 the same timer infor will not trigger and then the new handle's timeout
474 will not be notified to the app.
476 The work-around is thus simply to clear the 'lastcall' variable to force
477 update_timer() to always trigger a callback to the app when a new easy
479 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
486 /* Debug-function, used like this:
488 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
490 * Enable the hash print function first by editing hash.c
492 static void debug_print_sock_hash(void *p)
494 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
496 fprintf(stderr, " [easy %p/magic %x/socket %d]",
497 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
501 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
504 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
505 struct Curl_one_easy *easy;
506 struct SessionHandle *data = curl_handle;
508 /* First, make some basic checks that the CURLM handle is a good handle */
509 if(!GOOD_MULTI_HANDLE(multi))
510 return CURLM_BAD_HANDLE;
512 /* Verify that we got a somewhat good easy handle too */
513 if(!GOOD_EASY_HANDLE(curl_handle))
514 return CURLM_BAD_EASY_HANDLE;
516 /* pick-up from the 'curl_handle' the kept position in the list */
517 easy = data->multi_pos;
520 bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
521 bool easy_owns_conn = (easy->easy_conn &&
522 (easy->easy_conn->data == easy->easy_handle)) ?
525 /* If the 'state' is not INIT or COMPLETED, we might need to do something
526 nice to put the easy_handle in a good known state when this returns. */
528 /* this handle is "alive" so we need to count down the total number of
529 alive connections when this is removed */
532 if(easy->easy_conn &&
533 (easy->easy_conn->send_pipe->size +
534 easy->easy_conn->recv_pipe->size > 1) &&
535 easy->state > CURLM_STATE_WAITDO &&
536 easy->state < CURLM_STATE_COMPLETED) {
537 /* If the handle is in a pipeline and has started sending off its
538 request but not received its response yet, we need to close
540 easy->easy_conn->bits.close = TRUE;
541 /* Set connection owner so that Curl_done() closes it.
542 We can sefely do this here since connection is killed. */
543 easy->easy_conn->data = easy->easy_handle;
546 /* The timer must be shut down before easy->multi is set to NULL,
547 else the timenode will remain in the splay tree after
548 curl_easy_cleanup is called. */
549 Curl_expire(easy->easy_handle, 0);
551 /* destroy the timeout list that is held in the easy handle */
552 if(data->state.timeoutlist) {
553 Curl_llist_destroy(data->state.timeoutlist, NULL);
554 data->state.timeoutlist = NULL;
557 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
558 /* stop using the multi handle's DNS cache */
559 easy->easy_handle->dns.hostcache = NULL;
560 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
563 if(easy->easy_conn) {
565 /* we must call Curl_done() here (if we still "own it") so that we don't
566 leave a half-baked one around */
569 /* Curl_done() clears the conn->data field to lose the association
570 between the easy handle and the connection
572 Note that this ignores the return code simply because there's
573 nothing really useful to do with it anyway! */
574 (void)Curl_done(&easy->easy_conn, easy->result, premature);
577 /* Clear connection pipelines, if Curl_done above was not called */
578 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
581 /* as this was using a shared connection cache we clear the pointer
582 to that since we're not part of that multi handle anymore */
583 easy->easy_handle->state.conn_cache = NULL;
585 /* change state without using multistate(), only to make singlesocket() do
587 easy->state = CURLM_STATE_COMPLETED;
588 singlesocket(multi, easy); /* to let the application know what sockets
589 that vanish with this handle */
591 /* Remove the association between the connection and the handle */
592 if(easy->easy_conn) {
593 easy->easy_conn->data = NULL;
594 easy->easy_conn = NULL;
597 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
598 to this multi handle */
601 /* make sure there's no pending message in the queue sent from this easy
603 struct curl_llist_element *e;
605 for(e = multi->msglist->head; e; e = e->next) {
606 struct Curl_message *msg = e->ptr;
608 if(msg->extmsg.easy_handle == easy->easy_handle) {
609 Curl_llist_remove(multi->msglist, e, NULL);
610 /* there can only be one from this specific handle */
616 /* make the previous node point to our next */
618 easy->prev->next = easy->next;
619 /* make our next point to our previous node */
621 easy->next->prev = easy->prev;
623 easy->easy_handle->set.one_easy = NULL; /* detached */
625 /* Null the position in the controlling structure */
626 easy->easy_handle->multi_pos = NULL;
629 We do not touch the easy handle here! */
632 multi->num_easy--; /* one less to care about now */
638 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
641 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
643 return multi->pipelining_enabled;
646 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
648 struct Curl_one_easy *one_easy = data->set.one_easy;
651 one_easy->easy_conn = NULL;
654 static int waitconnect_getsock(struct connectdata *conn,
659 return GETSOCK_BLANK;
661 sock[0] = conn->sock[FIRSTSOCKET];
663 /* when we've sent a CONNECT to a proxy, we should rather wait for the
664 socket to become readable to be able to get the response headers */
665 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
666 return GETSOCK_READSOCK(0);
668 return GETSOCK_WRITESOCK(0);
671 static int domore_getsock(struct connectdata *conn,
672 curl_socket_t *socks,
675 if(conn && conn->handler->domore_getsock)
676 return conn->handler->domore_getsock(conn, socks, numsocks);
677 return GETSOCK_BLANK;
680 /* returns bitmapped flags for this handle and its sockets */
681 static int multi_getsock(struct Curl_one_easy *easy,
682 curl_socket_t *socks, /* points to numsocks number
686 /* If the pipe broke, or if there's no connection left for this easy handle,
687 then we MUST bail out now with no bitmask set. The no connection case can
688 happen when this is called from curl_multi_remove_handle() =>
689 singlesocket() => multi_getsock().
691 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
694 if(easy->state > CURLM_STATE_CONNECT &&
695 easy->state < CURLM_STATE_COMPLETED) {
696 /* Set up ownership correctly */
697 easy->easy_conn->data = easy->easy_handle;
700 switch(easy->state) {
702 #if 0 /* switch back on these cases to get the compiler to check for all enums
704 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
705 case CURLM_STATE_COMPLETED:
706 case CURLM_STATE_MSGSENT:
707 case CURLM_STATE_INIT:
708 case CURLM_STATE_CONNECT:
709 case CURLM_STATE_WAITDO:
710 case CURLM_STATE_DONE:
711 case CURLM_STATE_LAST:
712 /* this will get called with CURLM_STATE_COMPLETED when a handle is
717 case CURLM_STATE_WAITRESOLVE:
718 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
720 case CURLM_STATE_PROTOCONNECT:
721 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
724 case CURLM_STATE_DOING:
725 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
727 case CURLM_STATE_WAITPROXYCONNECT:
728 case CURLM_STATE_WAITCONNECT:
729 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
731 case CURLM_STATE_DO_MORE:
732 return domore_getsock(easy->easy_conn, socks, numsocks);
734 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
735 to waiting for the same as the *PERFORM
737 case CURLM_STATE_PERFORM:
738 case CURLM_STATE_WAITPERFORM:
739 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
744 CURLMcode curl_multi_fdset(CURLM *multi_handle,
745 fd_set *read_fd_set, fd_set *write_fd_set,
746 fd_set *exc_fd_set, int *max_fd)
748 /* Scan through all the easy handles to get the file descriptors set.
749 Some easy handles may not have connected to the remote host yet,
750 and then we must make sure that is done. */
751 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
752 struct Curl_one_easy *easy;
754 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
757 (void)exc_fd_set; /* not used */
759 if(!GOOD_MULTI_HANDLE(multi))
760 return CURLM_BAD_HANDLE;
762 easy=multi->easy.next;
763 while(easy != &multi->easy) {
764 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
766 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
767 curl_socket_t s = CURL_SOCKET_BAD;
769 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
770 FD_SET(sockbunch[i], read_fd_set);
773 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
774 FD_SET(sockbunch[i], write_fd_set);
777 if(s == CURL_SOCKET_BAD)
778 /* this socket is unused, break out of loop */
781 if((int)s > this_max_fd)
782 this_max_fd = (int)s;
786 easy = easy->next; /* check next handle */
789 *max_fd = this_max_fd;
794 CURLMcode curl_multi_wait(CURLM *multi_handle,
795 struct curl_waitfd extra_fds[],
796 unsigned int extra_nfds,
800 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
801 struct Curl_one_easy *easy;
802 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
805 unsigned int nfds = extra_nfds;
806 struct pollfd *ufds = NULL;
808 if(!GOOD_MULTI_HANDLE(multi))
809 return CURLM_BAD_HANDLE;
811 /* Count up how many fds we have from the multi handle */
812 easy=multi->easy.next;
813 while(easy != &multi->easy) {
814 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
816 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
817 curl_socket_t s = CURL_SOCKET_BAD;
819 if(bitmap & GETSOCK_READSOCK(i)) {
823 if(bitmap & GETSOCK_WRITESOCK(i)) {
827 if(s == CURL_SOCKET_BAD) {
832 easy = easy->next; /* check next handle */
836 ufds = malloc(nfds * sizeof(struct pollfd));
838 return CURLM_OUT_OF_MEMORY;
842 /* Add the curl handles to our pollfds first */
843 easy=multi->easy.next;
844 while(easy != &multi->easy) {
845 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
847 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
848 curl_socket_t s = CURL_SOCKET_BAD;
850 if(bitmap & GETSOCK_READSOCK(i)) {
851 ufds[nfds].fd = sockbunch[i];
852 ufds[nfds].events = POLLIN;
856 if(bitmap & GETSOCK_WRITESOCK(i)) {
857 ufds[nfds].fd = sockbunch[i];
858 ufds[nfds].events = POLLOUT;
862 if(s == CURL_SOCKET_BAD) {
867 easy = easy->next; /* check next handle */
870 /* Add external file descriptions from poll-like struct curl_waitfd */
871 for(i = 0; i < extra_nfds; i++) {
872 ufds[nfds].fd = extra_fds[i].fd;
873 ufds[nfds].events = 0;
874 if(extra_fds[i].events & CURL_WAIT_POLLIN)
875 ufds[nfds].events |= POLLIN;
876 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
877 ufds[nfds].events |= POLLPRI;
878 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
879 ufds[nfds].events |= POLLOUT;
885 i = Curl_poll(ufds, nfds, timeout_ms);
895 static CURLMcode multi_runsingle(struct Curl_multi *multi,
897 struct Curl_one_easy *easy)
899 struct Curl_message *msg = NULL;
902 bool protocol_connect = FALSE;
903 bool dophase_done = FALSE;
905 CURLMcode result = CURLM_OK;
906 struct SingleRequest *k;
907 struct SessionHandle *data;
910 if(!GOOD_EASY_HANDLE(easy->easy_handle))
911 return CURLM_BAD_EASY_HANDLE;
913 data = easy->easy_handle;
916 /* this is a single-iteration do-while loop just to allow a
917 break to skip to the end of it */
918 bool disconnect_conn = FALSE;
920 /* Handle the case when the pipe breaks, i.e., the connection
921 we're using gets cleaned up and we're left with nothing. */
922 if(data->state.pipe_broke) {
923 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
924 easy, data->state.path);
926 if(easy->state < CURLM_STATE_COMPLETED) {
927 /* Head back to the CONNECT state */
928 multistate(easy, CURLM_STATE_CONNECT);
929 result = CURLM_CALL_MULTI_PERFORM;
930 easy->result = CURLE_OK;
933 data->state.pipe_broke = FALSE;
934 easy->easy_conn = NULL;
938 if(!easy->easy_conn &&
939 easy->state > CURLM_STATE_CONNECT &&
940 easy->state < CURLM_STATE_DONE) {
941 /* In all these states, the code will blindly access 'easy->easy_conn'
942 so this is precaution that it isn't NULL. And it silences static
944 failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
945 return CURLM_INTERNAL_ERROR;
948 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
949 easy->state < CURLM_STATE_COMPLETED)
950 /* Make sure we set the connection's current owner */
951 easy->easy_conn->data = data;
953 if(easy->easy_conn &&
954 (easy->state >= CURLM_STATE_CONNECT) &&
955 (easy->state < CURLM_STATE_COMPLETED)) {
956 /* we need to wait for the connect state as only then is the start time
957 stored, but we must not check already completed handles */
959 timeout_ms = Curl_timeleft(data, &now,
960 (easy->state <= CURLM_STATE_WAITDO)?
964 /* Handle timed out */
965 if(easy->state == CURLM_STATE_WAITRESOLVE)
966 failf(data, "Resolving timed out after %ld milliseconds",
967 Curl_tvdiff(now, data->progress.t_startsingle));
968 else if(easy->state == CURLM_STATE_WAITCONNECT)
969 failf(data, "Connection timed out after %ld milliseconds",
970 Curl_tvdiff(now, data->progress.t_startsingle));
973 failf(data, "Operation timed out after %ld milliseconds with %"
974 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
975 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
979 /* Force the connection closed because the server could continue to
980 send us stuff at any time. (The disconnect_conn logic used below
981 doesn't work at this point). */
982 easy->easy_conn->bits.close = TRUE;
983 easy->result = CURLE_OPERATION_TIMEDOUT;
984 multistate(easy, CURLM_STATE_COMPLETED);
989 switch(easy->state) {
990 case CURLM_STATE_INIT:
991 /* init this transfer. */
992 easy->result=Curl_pretransfer(data);
994 if(CURLE_OK == easy->result) {
995 /* after init, go CONNECT */
996 multistate(easy, CURLM_STATE_CONNECT);
997 result = CURLM_CALL_MULTI_PERFORM;
1001 case CURLM_STATE_CONNECT:
1002 /* Connect. We get a connection identifier filled in. */
1003 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1004 easy->result = Curl_connect(data, &easy->easy_conn,
1005 &async, &protocol_connect);
1007 if(CURLE_OK == easy->result) {
1008 /* Add this handle to the send or pend pipeline */
1009 easy->result = addHandleToSendOrPendPipeline(data,
1011 if(CURLE_OK != easy->result)
1012 disconnect_conn = TRUE;
1015 /* We're now waiting for an asynchronous name lookup */
1016 multistate(easy, CURLM_STATE_WAITRESOLVE);
1018 /* after the connect has been sent off, go WAITCONNECT unless the
1019 protocol connect is already done and we can go directly to
1021 result = CURLM_CALL_MULTI_PERFORM;
1023 if(protocol_connect)
1024 multistate(easy, multi->pipelining_enabled?
1025 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1027 #ifndef CURL_DISABLE_HTTP
1028 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1029 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1032 multistate(easy, CURLM_STATE_WAITCONNECT);
1039 case CURLM_STATE_WAITRESOLVE:
1040 /* awaiting an asynch name resolve to complete */
1042 struct Curl_dns_entry *dns = NULL;
1044 /* check if we have the name resolved by now */
1045 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1047 /* Update sockets here, because the socket(s) may have been
1048 closed and the application thus needs to be told, even if it
1049 is likely that the same socket(s) will again be used further
1050 down. If the name has not yet been resolved, it is likely
1051 that new sockets have been opened in an attempt to contact
1052 another resolver. */
1053 singlesocket(multi, easy);
1056 /* Perform the next step in the connection phase, and then move on
1057 to the WAITCONNECT state */
1058 easy->result = Curl_async_resolved(easy->easy_conn,
1061 if(CURLE_OK != easy->result)
1062 /* if Curl_async_resolved() returns failure, the connection struct
1063 is already freed and gone */
1064 easy->easy_conn = NULL; /* no more connection */
1066 /* call again please so that we get the next socket setup */
1067 result = CURLM_CALL_MULTI_PERFORM;
1068 if(protocol_connect)
1069 multistate(easy, multi->pipelining_enabled?
1070 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1072 #ifndef CURL_DISABLE_HTTP
1073 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1074 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1077 multistate(easy, CURLM_STATE_WAITCONNECT);
1082 if(CURLE_OK != easy->result) {
1083 /* failure detected */
1084 disconnect_conn = TRUE;
1090 #ifndef CURL_DISABLE_HTTP
1091 case CURLM_STATE_WAITPROXYCONNECT:
1092 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1093 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1095 if(easy->easy_conn->bits.proxy_connect_closed) {
1096 /* reset the error buffer */
1097 if(data->set.errorbuffer)
1098 data->set.errorbuffer[0] = '\0';
1099 data->state.errorbuf = FALSE;
1101 easy->result = CURLE_OK;
1102 result = CURLM_CALL_MULTI_PERFORM;
1103 multistate(easy, CURLM_STATE_CONNECT);
1105 else if(CURLE_OK == easy->result) {
1106 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1107 multistate(easy, CURLM_STATE_WAITCONNECT);
1112 case CURLM_STATE_WAITCONNECT:
1113 /* awaiting a completion of an asynch connect */
1114 easy->result = Curl_is_connected(easy->easy_conn,
1120 /* if everything is still fine we do the protocol-specific connect
1122 easy->result = Curl_protocol_connect(easy->easy_conn,
1126 if(CURLE_OK != easy->result) {
1127 /* failure detected */
1128 /* Just break, the cleaning up is handled all in one place */
1129 disconnect_conn = TRUE;
1134 if(!protocol_connect) {
1135 /* We have a TCP connection, but 'protocol_connect' may be false
1136 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1137 connect is TRUE, we move on to STATE_DO.
1138 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1140 #ifndef CURL_DISABLE_HTTP
1141 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1142 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1145 multistate(easy, CURLM_STATE_PROTOCONNECT);
1149 /* after the connect has completed, go WAITDO or DO */
1150 multistate(easy, multi->pipelining_enabled?
1151 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1153 result = CURLM_CALL_MULTI_PERFORM;
1157 case CURLM_STATE_PROTOCONNECT:
1158 /* protocol-specific connect phase */
1159 easy->result = Curl_protocol_connecting(easy->easy_conn,
1161 if((easy->result == CURLE_OK) && protocol_connect) {
1162 /* after the connect has completed, go WAITDO or DO */
1163 multistate(easy, multi->pipelining_enabled?
1164 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1165 result = CURLM_CALL_MULTI_PERFORM;
1167 else if(easy->result) {
1168 /* failure detected */
1169 Curl_posttransfer(data);
1170 Curl_done(&easy->easy_conn, easy->result, TRUE);
1171 disconnect_conn = TRUE;
1175 case CURLM_STATE_WAITDO:
1176 /* Wait for our turn to DO when we're pipelining requests */
1178 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
1179 easy->easy_conn->connection_id,
1180 easy->easy_conn->send_pipe->size,
1181 easy->easy_conn->writechannel_inuse?1:0,
1182 isHandleAtHead(data,
1183 easy->easy_conn->send_pipe)?1:0);
1185 if(!easy->easy_conn->writechannel_inuse &&
1186 isHandleAtHead(data,
1187 easy->easy_conn->send_pipe)) {
1188 /* Grab the channel */
1189 easy->easy_conn->writechannel_inuse = TRUE;
1190 multistate(easy, CURLM_STATE_DO);
1191 result = CURLM_CALL_MULTI_PERFORM;
1195 case CURLM_STATE_DO:
1196 if(data->set.connect_only) {
1197 /* keep connection open for application to use the socket */
1198 easy->easy_conn->bits.close = FALSE;
1199 multistate(easy, CURLM_STATE_DONE);
1200 easy->result = CURLE_OK;
1201 result = CURLM_CALL_MULTI_PERFORM;
1204 /* Perform the protocol's DO action */
1205 easy->result = Curl_do(&easy->easy_conn,
1208 if(CURLE_OK == easy->result) {
1210 /* some steps needed for wildcard matching */
1211 if(data->set.wildcardmatch) {
1212 struct WildcardData *wc = &data->wildcard;
1213 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1214 /* skip some states if it is important */
1215 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1216 multistate(easy, CURLM_STATE_DONE);
1217 result = CURLM_CALL_MULTI_PERFORM;
1221 /* DO was not completed in one function call, we must continue
1223 multistate(easy, CURLM_STATE_DOING);
1227 /* after DO, go DO_DONE... or DO_MORE */
1228 else if(easy->easy_conn->bits.do_more) {
1229 /* we're supposed to do more, but we need to sit down, relax
1230 and wait a little while first */
1231 multistate(easy, CURLM_STATE_DO_MORE);
1235 /* we're done with the DO, now DO_DONE */
1236 multistate(easy, CURLM_STATE_DO_DONE);
1237 result = CURLM_CALL_MULTI_PERFORM;
1240 else if((CURLE_SEND_ERROR == easy->result) &&
1241 easy->easy_conn->bits.reuse) {
1243 * In this situation, a connection that we were trying to use
1244 * may have unexpectedly died. If possible, send the connection
1245 * back to the CONNECT phase so we can try again.
1247 char *newurl = NULL;
1248 followtype follow=FOLLOW_NONE;
1252 drc = Curl_retry_request(easy->easy_conn, &newurl);
1254 /* a failure here pretty much implies an out of memory */
1256 disconnect_conn = TRUE;
1259 retry = (newurl)?TRUE:FALSE;
1261 Curl_posttransfer(data);
1262 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1264 /* When set to retry the connection, we must to go back to
1265 * the CONNECT state */
1267 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1268 follow = FOLLOW_RETRY;
1269 drc = Curl_follow(data, newurl, follow);
1270 if(drc == CURLE_OK) {
1271 multistate(easy, CURLM_STATE_CONNECT);
1272 result = CURLM_CALL_MULTI_PERFORM;
1273 easy->result = CURLE_OK;
1282 /* done didn't return OK or SEND_ERROR */
1288 /* Have error handler disconnect conn if we can't retry */
1289 disconnect_conn = TRUE;
1293 /* failure detected */
1294 Curl_posttransfer(data);
1295 Curl_done(&easy->easy_conn, easy->result, FALSE);
1296 disconnect_conn = TRUE;
1301 case CURLM_STATE_DOING:
1302 /* we continue DOING until the DO phase is complete */
1303 easy->result = Curl_protocol_doing(easy->easy_conn,
1305 if(CURLE_OK == easy->result) {
1307 /* after DO, go DO_DONE or DO_MORE */
1308 multistate(easy, easy->easy_conn->bits.do_more?
1309 CURLM_STATE_DO_MORE:
1310 CURLM_STATE_DO_DONE);
1311 result = CURLM_CALL_MULTI_PERFORM;
1312 } /* dophase_done */
1315 /* failure detected */
1316 Curl_posttransfer(data);
1317 Curl_done(&easy->easy_conn, easy->result, FALSE);
1318 disconnect_conn = TRUE;
1322 case CURLM_STATE_DO_MORE:
1324 * When we are connected, DO MORE and then go DO_DONE
1326 easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1328 /* No need to remove this handle from the send pipeline here since that
1329 is done in Curl_done() */
1330 if(CURLE_OK == easy->result) {
1332 multistate(easy, CURLM_STATE_DO_DONE);
1333 result = CURLM_CALL_MULTI_PERFORM;
1336 /* stay in DO_MORE */
1340 /* failure detected */
1341 Curl_posttransfer(data);
1342 Curl_done(&easy->easy_conn, easy->result, FALSE);
1343 disconnect_conn = TRUE;
1347 case CURLM_STATE_DO_DONE:
1348 /* Move ourselves from the send to recv pipeline */
1349 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1350 /* Check if we can move pending requests to send pipe */
1351 checkPendPipeline(easy->easy_conn);
1352 multistate(easy, CURLM_STATE_WAITPERFORM);
1353 result = CURLM_CALL_MULTI_PERFORM;
1356 case CURLM_STATE_WAITPERFORM:
1357 /* Wait for our turn to PERFORM */
1358 if(!easy->easy_conn->readchannel_inuse &&
1359 isHandleAtHead(data,
1360 easy->easy_conn->recv_pipe)) {
1361 /* Grab the channel */
1362 easy->easy_conn->readchannel_inuse = TRUE;
1363 multistate(easy, CURLM_STATE_PERFORM);
1364 result = CURLM_CALL_MULTI_PERFORM;
1368 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
1369 easy->easy_conn->connection_id,
1370 easy->easy_conn->recv_pipe->size,
1371 easy->easy_conn->readchannel_inuse?1:0,
1372 isHandleAtHead(data,
1373 easy->easy_conn->recv_pipe)?1:0);
1378 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1379 /* if both rates are within spec, resume transfer */
1380 if(Curl_pgrsUpdate(easy->easy_conn))
1381 easy->result = CURLE_ABORTED_BY_CALLBACK;
1383 easy->result = Curl_speedcheck(data, now);
1385 if(( (data->set.max_send_speed == 0) ||
1386 (data->progress.ulspeed < data->set.max_send_speed )) &&
1387 ( (data->set.max_recv_speed == 0) ||
1388 (data->progress.dlspeed < data->set.max_recv_speed)))
1389 multistate(easy, CURLM_STATE_PERFORM);
1392 case CURLM_STATE_PERFORM:
1394 char *newurl = NULL;
1397 /* check if over send speed */
1398 if((data->set.max_send_speed > 0) &&
1399 (data->progress.ulspeed > data->set.max_send_speed)) {
1402 multistate(easy, CURLM_STATE_TOOFAST);
1404 /* calculate upload rate-limitation timeout. */
1405 buffersize = (int)(data->set.buffer_size ?
1406 data->set.buffer_size : BUFSIZE);
1407 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1408 data->progress.ulspeed, buffersize);
1409 Curl_expire(data, timeout_ms);
1413 /* check if over recv speed */
1414 if((data->set.max_recv_speed > 0) &&
1415 (data->progress.dlspeed > data->set.max_recv_speed)) {
1418 multistate(easy, CURLM_STATE_TOOFAST);
1420 /* Calculate download rate-limitation timeout. */
1421 buffersize = (int)(data->set.buffer_size ?
1422 data->set.buffer_size : BUFSIZE);
1423 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1424 data->progress.dlspeed, buffersize);
1425 Curl_expire(data, timeout_ms);
1429 /* read/write data if it is ready to do so */
1430 easy->result = Curl_readwrite(easy->easy_conn, &done);
1434 if(!(k->keepon & KEEP_RECV)) {
1435 /* We're done receiving */
1436 easy->easy_conn->readchannel_inuse = FALSE;
1439 if(!(k->keepon & KEEP_SEND)) {
1440 /* We're done sending */
1441 easy->easy_conn->writechannel_inuse = FALSE;
1444 if(done || (easy->result == CURLE_RECV_ERROR)) {
1445 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1446 * condition and the server closed the re-used connection exactly when
1447 * we wanted to use it, so figure out if that is indeed the case.
1449 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1451 retry = (newurl)?TRUE:FALSE;
1454 /* if we are to retry, set the result to OK and consider the
1456 easy->result = CURLE_OK;
1463 * The transfer phase returned error, we mark the connection to get
1464 * closed to prevent being re-used. This is because we can't possibly
1465 * know if the connection is in a good shape or not now. Unless it is
1466 * a protocol which uses two "channels" like FTP, as then the error
1467 * happened in the data connection.
1470 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1471 easy->easy_conn->bits.close = TRUE;
1473 Curl_posttransfer(data);
1474 Curl_done(&easy->easy_conn, easy->result, FALSE);
1477 followtype follow=FOLLOW_NONE;
1479 /* call this even if the readwrite function returned error */
1480 Curl_posttransfer(data);
1482 /* we're no longer receiving */
1483 moveHandleFromRecvToDonePipeline(data,
1486 /* expire the new receiving pipeline head */
1487 if(easy->easy_conn->recv_pipe->head)
1488 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1490 /* Check if we can move pending requests to send pipe */
1491 checkPendPipeline(easy->easy_conn);
1493 /* When we follow redirects or is set to retry the connection, we must
1494 to go back to the CONNECT state */
1495 if(data->req.newurl || retry) {
1497 /* if the URL is a follow-location and not just a retried request
1498 then figure out the URL here */
1499 newurl = data->req.newurl;
1500 data->req.newurl = NULL;
1501 follow = FOLLOW_REDIR;
1504 follow = FOLLOW_RETRY;
1505 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1506 if(easy->result == CURLE_OK)
1507 easy->result = Curl_follow(data, newurl, follow);
1508 if(CURLE_OK == easy->result) {
1509 multistate(easy, CURLM_STATE_CONNECT);
1510 result = CURLM_CALL_MULTI_PERFORM;
1511 newurl = NULL; /* handed over the memory ownership to
1512 Curl_follow(), make sure we don't free() it
1517 /* after the transfer is done, go DONE */
1519 /* but first check to see if we got a location info even though we're
1520 not following redirects */
1521 if(data->req.location) {
1524 newurl = data->req.location;
1525 data->req.location = NULL;
1526 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1527 if(CURLE_OK == easy->result)
1528 newurl = NULL; /* allocation was handed over Curl_follow() */
1530 disconnect_conn = TRUE;
1533 multistate(easy, CURLM_STATE_DONE);
1534 result = CURLM_CALL_MULTI_PERFORM;
1543 case CURLM_STATE_DONE:
1545 if(easy->easy_conn) {
1546 /* Remove ourselves from the receive and done pipelines. Handle
1547 should be on one of these lists, depending upon how we got here. */
1548 Curl_removeHandleFromPipeline(data,
1549 easy->easy_conn->recv_pipe);
1550 Curl_removeHandleFromPipeline(data,
1551 easy->easy_conn->done_pipe);
1552 /* Check if we can move pending requests to send pipe */
1553 checkPendPipeline(easy->easy_conn);
1555 if(easy->easy_conn->bits.stream_was_rewound) {
1556 /* This request read past its response boundary so we quickly let
1557 the other requests consume those bytes since there is no
1558 guarantee that the socket will become active again */
1559 result = CURLM_CALL_MULTI_PERFORM;
1562 /* post-transfer command */
1563 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1565 * If there are other handles on the pipeline, Curl_done won't set
1566 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1567 * access free'd data, if the connection is free'd and the handle
1568 * removed before we perform the processing in CURLM_STATE_COMPLETED
1571 easy->easy_conn = NULL;
1574 if(data->set.wildcardmatch) {
1575 if(data->wildcard.state != CURLWC_DONE) {
1576 /* if a wildcard is set and we are not ending -> lets start again
1577 with CURLM_STATE_INIT */
1578 result = CURLM_CALL_MULTI_PERFORM;
1579 multistate(easy, CURLM_STATE_INIT);
1584 /* after we have DONE what we're supposed to do, go COMPLETED, and
1585 it doesn't matter what the Curl_done() returned! */
1586 multistate(easy, CURLM_STATE_COMPLETED);
1590 case CURLM_STATE_COMPLETED:
1591 /* this is a completed transfer, it is likely to still be connected */
1593 /* This node should be delinked from the list now and we should post
1594 an information message that we are complete. */
1596 /* Important: reset the conn pointer so that we don't point to memory
1597 that could be freed anytime */
1598 easy->easy_conn = NULL;
1600 Curl_expire(data, 0); /* stop all timers */
1603 case CURLM_STATE_MSGSENT:
1604 return CURLM_OK; /* do nothing */
1607 return CURLM_INTERNAL_ERROR;
1610 if(easy->state < CURLM_STATE_COMPLETED) {
1611 if(CURLE_OK != easy->result) {
1613 * If an error was returned, and we aren't in completed state now,
1614 * then we go to completed and consider this transfer aborted.
1617 /* NOTE: no attempt to disconnect connections must be made
1618 in the case blocks above - cleanup happens only here */
1620 data->state.pipe_broke = FALSE;
1622 if(easy->easy_conn) {
1623 /* if this has a connection, unsubscribe from the pipelines */
1624 easy->easy_conn->writechannel_inuse = FALSE;
1625 easy->easy_conn->readchannel_inuse = FALSE;
1626 Curl_removeHandleFromPipeline(data,
1627 easy->easy_conn->send_pipe);
1628 Curl_removeHandleFromPipeline(data,
1629 easy->easy_conn->recv_pipe);
1630 Curl_removeHandleFromPipeline(data,
1631 easy->easy_conn->done_pipe);
1632 /* Check if we can move pending requests to send pipe */
1633 checkPendPipeline(easy->easy_conn);
1635 if(disconnect_conn) {
1636 /* disconnect properly */
1637 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1639 /* This is where we make sure that the easy_conn pointer is reset.
1640 We don't have to do this in every case block above where a
1641 failure is detected */
1642 easy->easy_conn = NULL;
1645 else if(easy->state == CURLM_STATE_CONNECT) {
1646 /* Curl_connect() failed */
1647 (void)Curl_posttransfer(data);
1650 multistate(easy, CURLM_STATE_COMPLETED);
1652 /* if there's still a connection to use, call the progress function */
1653 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1654 /* aborted due to progress callback return code must close the
1656 easy->easy_conn->bits.close = TRUE;
1658 /* if not yet in DONE state, go there, otherwise COMPLETED */
1659 multistate(easy, (easy->state < CURLM_STATE_DONE)?
1660 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1661 result = CURLM_CALL_MULTI_PERFORM;
1664 } WHILE_FALSE; /* just to break out from! */
1666 if(CURLM_STATE_COMPLETED == easy->state) {
1667 /* now fill in the Curl_message with this info */
1670 msg->extmsg.msg = CURLMSG_DONE;
1671 msg->extmsg.easy_handle = data;
1672 msg->extmsg.data.result = easy->result;
1674 result = multi_addmsg(multi, msg);
1676 multistate(easy, CURLM_STATE_MSGSENT);
1683 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1685 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1686 struct Curl_one_easy *easy;
1687 CURLMcode returncode=CURLM_OK;
1688 struct Curl_tree *t;
1689 struct timeval now = Curl_tvnow();
1691 if(!GOOD_MULTI_HANDLE(multi))
1692 return CURLM_BAD_HANDLE;
1694 easy=multi->easy.next;
1695 while(easy != &multi->easy) {
1697 struct WildcardData *wc = &easy->easy_handle->wildcard;
1699 if(easy->easy_handle->set.wildcardmatch) {
1701 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1703 return CURLM_OUT_OF_MEMORY;
1708 result = multi_runsingle(multi, now, easy);
1709 while(CURLM_CALL_MULTI_PERFORM == result);
1711 if(easy->easy_handle->set.wildcardmatch) {
1712 /* destruct wildcard structures if it is needed */
1713 if(wc->state == CURLWC_DONE || result)
1714 Curl_wildcard_dtor(wc);
1718 returncode = result;
1720 easy = easy->next; /* operate on next handle */
1724 * Simply remove all expired timers from the splay since handles are dealt
1725 * with unconditionally by this function and curl_multi_timeout() requires
1726 * that already passed/handled expire times are removed from the splay.
1728 * It is important that the 'now' value is set at the entry of this function
1729 * and not for the current time as it may have ticked a little while since
1730 * then and then we risk this loop to remove timers that actually have not
1734 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1736 /* the removed may have another timeout in queue */
1737 (void)add_next_timeout(now, multi, t->payload);
1741 *running_handles = multi->num_alive;
1743 if(CURLM_OK >= returncode)
1744 update_timer(multi);
1749 static void close_all_connections(struct Curl_multi *multi)
1751 struct connectdata *conn;
1753 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1755 conn->data = multi->closure_handle;
1757 /* This will remove the connection from the cache */
1758 (void)Curl_disconnect(conn, FALSE);
1760 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1764 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1766 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1767 struct Curl_one_easy *easy;
1768 struct Curl_one_easy *nexteasy;
1770 if(GOOD_MULTI_HANDLE(multi)) {
1771 multi->type = 0; /* not good anymore */
1773 /* Close all the connections in the connection cache */
1774 close_all_connections(multi);
1776 multi->closure_handle->dns.hostcache = multi->hostcache;
1777 Curl_hostcache_clean(multi->closure_handle);
1779 Curl_close(multi->closure_handle);
1780 multi->closure_handle = NULL;
1782 Curl_hash_destroy(multi->sockhash);
1783 multi->sockhash = NULL;
1785 Curl_conncache_destroy(multi->conn_cache);
1786 multi->conn_cache = NULL;
1788 /* remove the pending list of messages */
1789 Curl_llist_destroy(multi->msglist, NULL);
1790 multi->msglist = NULL;
1792 /* remove all easy handles */
1793 easy = multi->easy.next;
1794 while(easy != &multi->easy) {
1795 nexteasy=easy->next;
1796 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1797 /* clear out the usage of the shared DNS cache */
1798 Curl_hostcache_clean(easy->easy_handle);
1799 easy->easy_handle->dns.hostcache = NULL;
1800 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1803 /* Clear the pointer to the connection cache */
1804 easy->easy_handle->state.conn_cache = NULL;
1806 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1812 Curl_hash_destroy(multi->hostcache);
1813 multi->hostcache = NULL;
1820 return CURLM_BAD_HANDLE;
1824 * curl_multi_info_read()
1826 * This function is the primary way for a multi/multi_socket application to
1827 * figure out if a transfer has ended. We MUST make this function as fast as
1828 * possible as it will be polled frequently and we MUST NOT scan any lists in
1829 * here to figure out things. We must scale fine to thousands of handles and
1830 * beyond. The current design is fully O(1).
1833 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1835 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1836 struct Curl_message *msg;
1838 *msgs_in_queue = 0; /* default to none */
1840 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1841 /* there is one or more messages in the list */
1842 struct curl_llist_element *e;
1844 /* extract the head of the list to return */
1845 e = multi->msglist->head;
1849 /* remove the extracted entry */
1850 Curl_llist_remove(multi->msglist, e, NULL);
1852 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1854 return &msg->extmsg;
1861 * singlesocket() checks what sockets we deal with and their "action state"
1862 * and if we have a different state in any of those sockets from last time we
1863 * call the callback accordingly.
1865 static void singlesocket(struct Curl_multi *multi,
1866 struct Curl_one_easy *easy)
1868 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1870 struct Curl_sh_entry *entry;
1873 unsigned int curraction;
1874 struct Curl_one_easy *easy_by_hash;
1875 bool remove_sock_from_hash;
1877 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1878 socks[i] = CURL_SOCKET_BAD;
1880 /* Fill in the 'current' struct with the state as it is now: what sockets to
1881 supervise and for what actions */
1882 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1884 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1885 sockets we should have from now on. Detect the differences, remove no
1886 longer supervised ones and add new ones */
1888 /* walk over the sockets we got right now */
1889 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1890 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1892 int action = CURL_POLL_NONE;
1896 /* get it from the hash */
1897 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1899 if(curraction & GETSOCK_READSOCK(i))
1900 action |= CURL_POLL_IN;
1901 if(curraction & GETSOCK_WRITESOCK(i))
1902 action |= CURL_POLL_OUT;
1905 /* yeps, already present so check if it has the same action set */
1906 if(entry->action == action)
1907 /* same, continue */
1911 /* this is a socket we didn't have before, add it! */
1912 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1918 /* we know (entry != NULL) at this point, see the logic above */
1919 if(multi->socket_cb)
1920 multi->socket_cb(easy->easy_handle,
1923 multi->socket_userp,
1926 entry->action = action; /* store the current action state */
1929 num = i; /* number of sockets */
1931 /* when we've walked over all the sockets we should have right now, we must
1932 make sure to detect sockets that are removed */
1933 for(i=0; i< easy->numsocks; i++) {
1935 s = easy->sockets[i];
1936 for(j=0; j<num; j++) {
1938 /* this is still supervised */
1939 s = CURL_SOCKET_BAD;
1943 if(s != CURL_SOCKET_BAD) {
1945 /* this socket has been removed. Tell the app to remove it */
1946 remove_sock_from_hash = TRUE;
1948 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1950 /* check if the socket to be removed serves a connection which has
1951 other easy-s in a pipeline. In this case the socket should not be
1953 struct connectdata *easy_conn;
1955 easy_by_hash = entry->easy->multi_pos;
1956 easy_conn = easy_by_hash->easy_conn;
1958 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1959 /* the handle should not be removed from the pipe yet */
1960 remove_sock_from_hash = FALSE;
1962 /* Update the sockhash entry to instead point to the next in line
1963 for the recv_pipe, or the first (in case this particular easy
1965 if(entry->easy == easy->easy_handle) {
1966 if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
1967 entry->easy = easy_conn->recv_pipe->head->next->ptr;
1969 entry->easy = easy_conn->recv_pipe->head->ptr;
1972 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1973 /* the handle should not be removed from the pipe yet */
1974 remove_sock_from_hash = FALSE;
1976 /* Update the sockhash entry to instead point to the next in line
1977 for the send_pipe, or the first (in case this particular easy
1979 if(entry->easy == easy->easy_handle) {
1980 if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
1981 entry->easy = easy_conn->send_pipe->head->next->ptr;
1983 entry->easy = easy_conn->send_pipe->head->ptr;
1986 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
1987 when action will be asked on the socket (see multi_socket()), the
1988 head of the correct pipe will be taken according to the
1993 /* just a precaution, this socket really SHOULD be in the hash already
1994 but in case it isn't, we don't have to tell the app to remove it
1995 either since it never got to know about it */
1996 remove_sock_from_hash = FALSE;
1998 if(remove_sock_from_hash) {
1999 /* in this case 'entry' is always non-NULL */
2000 if(multi->socket_cb)
2001 multi->socket_cb(easy->easy_handle,
2004 multi->socket_userp,
2006 sh_delentry(multi->sockhash, s);
2012 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2013 easy->numsocks = num;
2017 * add_next_timeout()
2019 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2020 * when it has just been removed from the splay tree because the timeout has
2021 * expired. This function is then to advance in the list to pick the next
2022 * timeout to use (skip the already expired ones) and add this node back to
2023 * the splay tree again.
2025 * The splay tree only has each sessionhandle as a single node and the nearest
2026 * timeout is used to sort it on.
2028 static CURLMcode add_next_timeout(struct timeval now,
2029 struct Curl_multi *multi,
2030 struct SessionHandle *d)
2032 struct timeval *tv = &d->state.expiretime;
2033 struct curl_llist *list = d->state.timeoutlist;
2034 struct curl_llist_element *e;
2036 /* move over the timeout list for this specific handle and remove all
2037 timeouts that are now passed tense and store the next pending
2039 for(e = list->head; e; ) {
2040 struct curl_llist_element *n = e->next;
2041 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2043 /* remove outdated entry */
2044 Curl_llist_remove(list, e, NULL);
2046 /* the list is sorted so get out on the first mismatch */
2052 /* clear the expire times within the handles that we remove from the
2058 /* copy the first entry to 'tv' */
2059 memcpy(tv, e->ptr, sizeof(*tv));
2061 /* remove first entry from list */
2062 Curl_llist_remove(list, e, NULL);
2064 /* insert this node again into the splay */
2065 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2066 &d->state.timenode);
2072 static CURLMcode multi_socket(struct Curl_multi *multi,
2076 int *running_handles)
2078 CURLMcode result = CURLM_OK;
2079 struct SessionHandle *data = NULL;
2080 struct Curl_tree *t;
2081 struct timeval now = Curl_tvnow();
2084 struct Curl_one_easy *easyp;
2085 /* *perform() deals with running_handles on its own */
2086 result = curl_multi_perform(multi, running_handles);
2088 /* walk through each easy handle and do the socket state change magic
2090 easyp=multi->easy.next;
2091 while(easyp != &multi->easy) {
2092 singlesocket(multi, easyp);
2093 easyp = easyp->next;
2096 /* or should we fall-through and do the timer-based stuff? */
2099 else if(s != CURL_SOCKET_TIMEOUT) {
2101 struct Curl_sh_entry *entry =
2102 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2105 /* Unmatched socket, we can't act on it but we ignore this fact. In
2106 real-world tests it has been proved that libevent can in fact give
2107 the application actions even though the socket was just previously
2108 asked to get removed, so thus we better survive stray socket actions
2109 and just move on. */
2114 if(data->magic != CURLEASY_MAGIC_NUMBER)
2115 /* bad bad bad bad bad bad bad */
2116 return CURLM_INTERNAL_ERROR;
2118 /* If the pipeline is enabled, take the handle which is in the head of
2119 the pipeline. If we should write into the socket, take the send_pipe
2120 head. If we should read from the socket, take the recv_pipe head. */
2121 if(data->set.one_easy->easy_conn) {
2122 if((ev_bitmask & CURL_POLL_OUT) &&
2123 data->set.one_easy->easy_conn->send_pipe &&
2124 data->set.one_easy->easy_conn->send_pipe->head)
2125 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2126 else if((ev_bitmask & CURL_POLL_IN) &&
2127 data->set.one_easy->easy_conn->recv_pipe &&
2128 data->set.one_easy->easy_conn->recv_pipe->head)
2129 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2132 if(data->set.one_easy->easy_conn &&
2133 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2134 /* set socket event bitmask if they're not locked */
2135 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2138 result = multi_runsingle(multi, now, data->set.one_easy);
2139 while(CURLM_CALL_MULTI_PERFORM == result);
2141 if(data->set.one_easy->easy_conn &&
2142 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2143 /* clear the bitmask only if not locked */
2144 data->set.one_easy->easy_conn->cselect_bits = 0;
2146 if(CURLM_OK >= result)
2147 /* get the socket(s) and check if the state has been changed since
2149 singlesocket(multi, data->set.one_easy);
2151 /* Now we fall-through and do the timer-based stuff, since we don't want
2152 to force the user to have to deal with timeouts as long as at least
2153 one connection in fact has traffic. */
2155 data = NULL; /* set data to NULL again to avoid calling
2156 multi_runsingle() in case there's no need to */
2160 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2161 triggered too early */
2162 if(now.tv_usec >= 1000000) {
2164 now.tv_usec -= 1000000;
2168 * The loop following here will go on as long as there are expire-times left
2169 * to process in the splay and 'data' will be re-assigned for every expired
2170 * handle we deal with.
2173 /* the first loop lap 'data' can be NULL */
2176 result = multi_runsingle(multi, now, data->set.one_easy);
2177 while(CURLM_CALL_MULTI_PERFORM == result);
2179 if(CURLM_OK >= result)
2180 /* get the socket(s) and check if the state has been changed since
2182 singlesocket(multi, data->set.one_easy);
2185 /* Check if there's one (more) expired timer to deal with! This function
2186 extracts a matching node if there is one */
2188 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2190 data = t->payload; /* assign this for next loop */
2191 (void)add_next_timeout(now, multi, t->payload);
2196 *running_handles = multi->num_alive;
2200 #undef curl_multi_setopt
2201 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2202 CURLMoption option, ...)
2204 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2205 CURLMcode res = CURLM_OK;
2208 if(!GOOD_MULTI_HANDLE(multi))
2209 return CURLM_BAD_HANDLE;
2211 va_start(param, option);
2214 case CURLMOPT_SOCKETFUNCTION:
2215 multi->socket_cb = va_arg(param, curl_socket_callback);
2217 case CURLMOPT_SOCKETDATA:
2218 multi->socket_userp = va_arg(param, void *);
2220 case CURLMOPT_PIPELINING:
2221 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2223 case CURLMOPT_TIMERFUNCTION:
2224 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2226 case CURLMOPT_TIMERDATA:
2227 multi->timer_userp = va_arg(param, void *);
2229 case CURLMOPT_MAXCONNECTS:
2230 multi->maxconnects = va_arg(param, long);
2233 res = CURLM_UNKNOWN_OPTION;
2240 /* we define curl_multi_socket() in the public multi.h header */
2241 #undef curl_multi_socket
2243 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2244 int *running_handles)
2246 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2247 0, running_handles);
2248 if(CURLM_OK >= result)
2249 update_timer((struct Curl_multi *)multi_handle);
2253 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2254 int ev_bitmask, int *running_handles)
2256 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2257 ev_bitmask, running_handles);
2258 if(CURLM_OK >= result)
2259 update_timer((struct Curl_multi *)multi_handle);
2263 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2266 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2267 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2268 if(CURLM_OK >= result)
2269 update_timer((struct Curl_multi *)multi_handle);
2273 static CURLMcode multi_timeout(struct Curl_multi *multi,
2276 static struct timeval tv_zero = {0,0};
2278 if(multi->timetree) {
2279 /* we have a tree of expire times */
2280 struct timeval now = Curl_tvnow();
2282 /* splay the lowest to the bottom */
2283 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2285 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2286 /* some time left before expiration */
2287 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2290 * Since we only provide millisecond resolution on the returned value
2291 * and the diff might be less than one millisecond here, we don't
2292 * return zero as that may cause short bursts of busyloops on fast
2293 * processors while the diff is still present but less than one
2294 * millisecond! instead we return 1 until the time is ripe.
2299 /* 0 means immediately */
2308 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2311 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2313 /* First, make some basic checks that the CURLM handle is a good handle */
2314 if(!GOOD_MULTI_HANDLE(multi))
2315 return CURLM_BAD_HANDLE;
2317 return multi_timeout(multi, timeout_ms);
2321 * Tell the application it should update its timers, if it subscribes to the
2322 * update timer callback.
2324 static int update_timer(struct Curl_multi *multi)
2328 if(!multi->timer_cb)
2330 if(multi_timeout(multi, &timeout_ms)) {
2333 if(timeout_ms < 0) {
2334 static const struct timeval none={0,0};
2335 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2336 multi->timer_lastcall = none;
2337 /* there's no timeout now but there was one previously, tell the app to
2339 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2344 /* When multi_timeout() is done, multi->timetree points to the node with the
2345 * timeout we got the (relative) time-out time for. We can thus easily check
2346 * if this is the same (fixed) time as we got in a previous call and then
2347 * avoid calling the callback again. */
2348 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2351 multi->timer_lastcall = multi->timetree->key;
2353 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2356 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2357 struct connectdata *conn)
2359 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2360 struct curl_llist_element *sendhead = conn->send_pipe->head;
2361 struct curl_llist *pipeline;
2364 if(!Curl_isPipeliningEnabled(handle) ||
2366 pipeline = conn->send_pipe;
2368 if(conn->server_supports_pipelining &&
2369 pipeLen < MAX_PIPELINE_LENGTH)
2370 pipeline = conn->send_pipe;
2372 pipeline = conn->pend_pipe;
2375 rc = Curl_addHandleToPipeline(handle, pipeline);
2377 if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2378 /* this is a new one as head, expire it */
2379 conn->writechannel_inuse = FALSE; /* not in use yet */
2381 infof(conn->data, "%p is at send pipe head!\n",
2382 conn->send_pipe->head->ptr);
2384 Curl_expire(conn->send_pipe->head->ptr, 1);
2390 static int checkPendPipeline(struct connectdata *conn)
2393 struct curl_llist_element *sendhead = conn->send_pipe->head;
2395 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2396 if(conn->server_supports_pipelining || pipeLen == 0) {
2397 struct curl_llist_element *curr = conn->pend_pipe->head;
2398 const size_t maxPipeLen =
2399 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2401 while(pipeLen < maxPipeLen && curr) {
2402 Curl_llist_move(conn->pend_pipe, curr,
2403 conn->send_pipe, conn->send_pipe->tail);
2404 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2405 ++result; /* count how many handles we moved */
2406 curr = conn->pend_pipe->head;
2412 conn->now = Curl_tvnow();
2413 /* something moved, check for a new send pipeline leader */
2414 if(sendhead != conn->send_pipe->head) {
2415 /* this is a new one as head, expire it */
2416 conn->writechannel_inuse = FALSE; /* not in use yet */
2418 infof(conn->data, "%p is at send pipe head!\n",
2419 conn->send_pipe->head->ptr);
2421 Curl_expire(conn->send_pipe->head->ptr, 1);
2428 /* Move this transfer from the sending list to the receiving list.
2430 Pay special attention to the new sending list "leader" as it needs to get
2431 checked to update what sockets it acts on.
2434 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2435 struct connectdata *conn)
2437 struct curl_llist_element *curr;
2439 curr = conn->send_pipe->head;
2441 if(curr->ptr == handle) {
2442 Curl_llist_move(conn->send_pipe, curr,
2443 conn->recv_pipe, conn->recv_pipe->tail);
2445 if(conn->send_pipe->head) {
2446 /* Since there's a new easy handle at the start of the send pipeline,
2447 set its timeout value to 1ms to make it trigger instantly */
2448 conn->writechannel_inuse = FALSE; /* not used now */
2450 infof(conn->data, "%p is at send pipe head B!\n",
2451 conn->send_pipe->head->ptr);
2453 Curl_expire(conn->send_pipe->head->ptr, 1);
2456 /* The receiver's list is not really interesting here since either this
2457 handle is now first in the list and we'll deal with it soon, or
2458 another handle is already first and thus is already taken care of */
2460 break; /* we're done! */
2466 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2467 struct connectdata *conn)
2469 struct curl_llist_element *curr;
2471 curr = conn->recv_pipe->head;
2473 if(curr->ptr == handle) {
2474 Curl_llist_move(conn->recv_pipe, curr,
2475 conn->done_pipe, conn->done_pipe->tail);
2481 static bool isHandleAtHead(struct SessionHandle *handle,
2482 struct curl_llist *pipeline)
2484 struct curl_llist_element *curr = pipeline->head;
2486 return (curr->ptr == handle) ? TRUE : FALSE;
2492 * multi_freetimeout()
2494 * Callback used by the llist system when a single timeout list entry is
2497 static void multi_freetimeout(void *user, void *entryptr)
2501 /* the entry was plain malloc()'ed */
2506 * multi_addtimeout()
2508 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2509 * of list is always the timeout nearest in time.
2513 multi_addtimeout(struct curl_llist *timeoutlist,
2514 struct timeval *stamp)
2516 struct curl_llist_element *e;
2517 struct timeval *timedup;
2518 struct curl_llist_element *prev = NULL;
2520 timedup = malloc(sizeof(*timedup));
2522 return CURLM_OUT_OF_MEMORY;
2524 /* copy the timestamp */
2525 memcpy(timedup, stamp, sizeof(*timedup));
2527 if(Curl_llist_count(timeoutlist)) {
2528 /* find the correct spot in the list */
2529 for(e = timeoutlist->head; e; e = e->next) {
2530 struct timeval *checktime = e->ptr;
2531 long diff = curlx_tvdiff(*checktime, *timedup);
2539 this is the first timeout on the list */
2541 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2543 return CURLM_OUT_OF_MEMORY;
2552 * given a number of milliseconds from now to use to set the 'act before
2553 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2555 * Note that the timeout will be added to a queue of timeouts if it defines a
2556 * moment in time that is later than the current head of queue.
2558 * Pass zero to clear all timeout values for this handle.
2560 void Curl_expire(struct SessionHandle *data, long milli)
2562 struct Curl_multi *multi = data->multi;
2563 struct timeval *nowp = &data->state.expiretime;
2566 /* this is only interesting for multi-interface using libcurl, and only
2567 while there is still a multi interface struct remaining! */
2572 /* No timeout, clear the time data. */
2573 if(nowp->tv_sec || nowp->tv_usec) {
2574 /* Since this is an cleared time, we must remove the previous entry from
2576 struct curl_llist *list = data->state.timeoutlist;
2578 rc = Curl_splayremovebyaddr(multi->timetree,
2579 &data->state.timenode,
2582 infof(data, "Internal error clearing splay node = %d\n", rc);
2584 /* flush the timeout list too */
2585 while(list->size > 0)
2586 Curl_llist_remove(list, list->tail, NULL);
2589 infof(data, "Expire cleared\n");
2599 set.tv_sec += milli/1000;
2600 set.tv_usec += (milli%1000)*1000;
2602 if(set.tv_usec >= 1000000) {
2604 set.tv_usec -= 1000000;
2607 if(nowp->tv_sec || nowp->tv_usec) {
2608 /* This means that the struct is added as a node in the splay tree.
2609 Compare if the new time is earlier, and only remove-old/add-new if it
2611 long diff = curlx_tvdiff(set, *nowp);
2613 /* the new expire time was later so just add it to the queue
2615 multi_addtimeout(data->state.timeoutlist, &set);
2619 /* the new time is newer than the presently set one, so add the current
2620 to the queue and update the head */
2621 multi_addtimeout(data->state.timeoutlist, nowp);
2623 /* Since this is an updated time, we must remove the previous entry from
2624 the splay tree first and then re-add the new value */
2625 rc = Curl_splayremovebyaddr(multi->timetree,
2626 &data->state.timenode,
2629 infof(data, "Internal error removing splay node = %d\n", rc);
2633 data->state.timenode.payload = data;
2634 multi->timetree = Curl_splayinsert(*nowp,
2636 &data->state.timenode);
2639 Curl_splayprint(multi->timetree, 0, TRUE);
2643 CURLMcode curl_multi_assign(CURLM *multi_handle,
2644 curl_socket_t s, void *hashp)
2646 struct Curl_sh_entry *there = NULL;
2647 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2649 if(s != CURL_SOCKET_BAD)
2650 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2653 return CURLM_BAD_SOCKET;
2655 there->socketp = hashp;
2661 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2663 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2664 struct Curl_one_easy *easy;
2666 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2667 multi->num_easy, multi->num_alive);
2668 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2669 if(easy->state < CURLM_STATE_COMPLETED) {
2670 /* only display handles that are not completed */
2671 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2672 (void *)easy->easy_handle,
2673 statename[easy->state], easy->numsocks);
2674 for(i=0; i < easy->numsocks; i++) {
2675 curl_socket_t s = easy->sockets[i];
2676 struct Curl_sh_entry *entry =
2677 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2679 fprintf(stderr, "%d ", (int)s);
2681 fprintf(stderr, "INTERNAL CONFUSION\n");
2684 fprintf(stderr, "[%s %s] ",
2685 entry->action&CURL_POLL_IN?"RECVING":"",
2686 entry->action&CURL_POLL_OUT?"SENDING":"");
2689 fprintf(stderr, "\n");