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 SessionHandle *data);
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 SessionHandle *data, CURLMstate state
115 long connection_id = -5000;
117 CURLMstate oldstate = data->mstate;
119 if(oldstate == state)
120 /* don't bother when the new state is the same as the old state */
123 data->mstate = state;
126 if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
127 data->mstate < CURLM_STATE_COMPLETED) {
129 connection_id = data->easy_conn->connection_id;
132 "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
133 statename[oldstate], statename[data->mstate],
134 (void *)data, lineno, connection_id);
137 if(state == CURLM_STATE_COMPLETED)
138 /* changing to COMPLETED means there's one less easy handle 'alive' */
139 data->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 /* allocate a new easy handle to use when closing cached connections */
311 multi->closure_handle = curl_easy_init();
312 if(!multi->closure_handle)
315 multi->closure_handle->multi = multi;
316 multi->closure_handle->state.conn_cache = multi->conn_cache;
318 multi->max_pipeline_length = 5;
319 return (CURLM *) multi;
323 Curl_hash_destroy(multi->sockhash);
324 multi->sockhash = NULL;
325 Curl_hash_destroy(multi->hostcache);
326 multi->hostcache = NULL;
327 Curl_conncache_destroy(multi->conn_cache);
328 multi->conn_cache = NULL;
329 Curl_close(multi->closure_handle);
330 multi->closure_handle = NULL;
336 CURLM *curl_multi_init(void)
338 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
339 CURL_CONNECTION_HASH_SIZE);
342 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
345 struct curl_llist *timeoutlist;
346 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
347 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
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 once and prevent
358 adding to more than one multi stack */
360 return CURLM_ADDED_ALREADY;
362 /* Allocate and initialize timeout list for easy handle */
363 timeoutlist = Curl_llist_alloc(multi_freetimeout);
365 return CURLM_OUT_OF_MEMORY;
368 * No failure allowed in this function beyond this point. And no
369 * modification of easy nor multi handle allowed before this except for
370 * potential multi's connection cache growing which won't be undone in this
371 * function no matter what.
374 /* Make easy handle use timeout list initialized above */
375 data->state.timeoutlist = timeoutlist;
378 /* set the easy handle */
379 multistate(data, CURLM_STATE_INIT);
381 if((data->set.global_dns_cache) &&
382 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
383 /* global dns cache was requested but still isn't */
384 struct curl_hash *global = Curl_global_host_cache_init();
386 /* only do this if the global cache init works */
387 data->dns.hostcache = global;
388 data->dns.hostcachetype = HCACHE_GLOBAL;
391 /* for multi interface connections, we share DNS cache automatically if the
392 easy handle's one is currently not set. */
393 else if(!data->dns.hostcache ||
394 (data->dns.hostcachetype == HCACHE_NONE)) {
395 data->dns.hostcache = multi->hostcache;
396 data->dns.hostcachetype = HCACHE_MULTI;
399 /* Point to the multi's connection cache */
400 data->state.conn_cache = multi->conn_cache;
402 /* This adds the new entry at the 'end' of the doubly-linked circular
403 list of SessionHandle structs to try and maintain a FIFO queue so
404 the pipelined requests are in order. */
406 /* We add this new entry last in the list. */
408 data->next = NULL; /* end of the line */
410 struct SessionHandle *last = multi->easylp;
413 multi->easylp = data; /* the new last node */
416 /* first node, make both prev and next be NULL! */
419 multi->easylp = multi->easyp = data; /* both first and last */
422 /* make the SessionHandle refer back to this multi handle */
423 data->multi = multi_handle;
425 /* Set the timeout for this handle to expire really soon so that it will
426 be taken care of even when this handle is added in the midst of operation
427 when only the curl_multi_socket() API is used. During that flow, only
428 sockets that time-out or have actions will be dealt with. Since this
429 handle has no action yet, we make sure it times out to get things to
431 Curl_expire(data, 1);
433 /* increase the node-counter */
436 /* increase the alive-counter */
439 /* A somewhat crude work-around for a little glitch in update_timer() that
440 happens if the lastcall time is set to the same time when the handle is
441 removed as when the next handle is added, as then the check in
442 update_timer() that prevents calling the application multiple times with
443 the same timer infor will not trigger and then the new handle's timeout
444 will not be notified to the app.
446 The work-around is thus simply to clear the 'lastcall' variable to force
447 update_timer() to always trigger a callback to the app when a new easy
449 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
456 /* Debug-function, used like this:
458 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
460 * Enable the hash print function first by editing hash.c
462 static void debug_print_sock_hash(void *p)
464 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
466 fprintf(stderr, " [easy %p/magic %x/socket %d]",
467 (void *)sh->data, sh->data->magic, (int)sh->socket);
471 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
474 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
475 struct SessionHandle *easy = curl_handle;
476 struct SessionHandle *data = easy;
478 /* First, make some basic checks that the CURLM handle is a good handle */
479 if(!GOOD_MULTI_HANDLE(multi))
480 return CURLM_BAD_HANDLE;
482 /* Verify that we got a somewhat good easy handle too */
483 if(!GOOD_EASY_HANDLE(curl_handle))
484 return CURLM_BAD_EASY_HANDLE;
486 /* Prevent users from trying to remove same easy handle more than once */
488 return CURLM_OK; /* it is already removed so let's say it is fine! */
491 bool premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
492 bool easy_owns_conn = (data->easy_conn &&
493 (data->easy_conn->data == easy)) ?
496 /* If the 'state' is not INIT or COMPLETED, we might need to do something
497 nice to put the easy_handle in a good known state when this returns. */
499 /* this handle is "alive" so we need to count down the total number of
500 alive connections when this is removed */
503 if(data->easy_conn &&
504 (data->easy_conn->send_pipe->size +
505 data->easy_conn->recv_pipe->size > 1) &&
506 data->mstate > CURLM_STATE_WAITDO &&
507 data->mstate < CURLM_STATE_COMPLETED) {
508 /* If the handle is in a pipeline and has started sending off its
509 request but not received its response yet, we need to close
511 data->easy_conn->bits.close = TRUE;
512 /* Set connection owner so that Curl_done() closes it.
513 We can sefely do this here since connection is killed. */
514 data->easy_conn->data = easy;
517 /* The timer must be shut down before data->multi is set to NULL,
518 else the timenode will remain in the splay tree after
519 curl_easy_cleanup is called. */
520 Curl_expire(data, 0);
522 /* destroy the timeout list that is held in the easy handle */
523 if(data->state.timeoutlist) {
524 Curl_llist_destroy(data->state.timeoutlist, NULL);
525 data->state.timeoutlist = NULL;
528 if(data->dns.hostcachetype == HCACHE_MULTI) {
529 /* stop using the multi handle's DNS cache */
530 data->dns.hostcache = NULL;
531 data->dns.hostcachetype = HCACHE_NONE;
534 if(data->easy_conn) {
536 /* we must call Curl_done() here (if we still "own it") so that we don't
537 leave a half-baked one around */
540 /* Curl_done() clears the conn->data field to lose the association
541 between the easy handle and the connection
543 Note that this ignores the return code simply because there's
544 nothing really useful to do with it anyway! */
545 (void)Curl_done(&data->easy_conn, data->result, premature);
548 /* Clear connection pipelines, if Curl_done above was not called */
549 Curl_getoff_all_pipelines(data, data->easy_conn);
552 /* as this was using a shared connection cache we clear the pointer
553 to that since we're not part of that multi handle anymore */
554 data->state.conn_cache = NULL;
556 /* change state without using multistate(), only to make singlesocket() do
558 data->mstate = CURLM_STATE_COMPLETED;
559 singlesocket(multi, easy); /* to let the application know what sockets
560 that vanish with this handle */
562 /* Remove the association between the connection and the handle */
563 if(data->easy_conn) {
564 data->easy_conn->data = NULL;
565 data->easy_conn = NULL;
568 data->multi = NULL; /* clear the association to this multi handle */
571 /* make sure there's no pending message in the queue sent from this easy
573 struct curl_llist_element *e;
575 for(e = multi->msglist->head; e; e = e->next) {
576 struct Curl_message *msg = e->ptr;
578 if(msg->extmsg.easy_handle == easy) {
579 Curl_llist_remove(multi->msglist, e, NULL);
580 /* there can only be one from this specific handle */
586 /* make the previous node point to our next */
588 data->prev->next = data->next;
590 multi->easyp = data->next; /* point to first node */
592 /* make our next point to our previous node */
594 data->next->prev = data->prev;
596 multi->easylp = data->prev; /* point to last node */
599 We do not touch the easy handle here! */
601 multi->num_easy--; /* one less to care about now */
607 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
610 bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
612 return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
615 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
617 data->easy_conn = NULL;
620 static int waitconnect_getsock(struct connectdata *conn,
629 return GETSOCK_BLANK;
632 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
633 sock[s] = conn->tempsock[i];
634 rc |= GETSOCK_WRITESOCK(s++);
638 /* when we've sent a CONNECT to a proxy, we should rather wait for the
639 socket to become readable to be able to get the response headers */
640 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
641 return GETSOCK_READSOCK(0);
646 static int domore_getsock(struct connectdata *conn,
647 curl_socket_t *socks,
650 if(conn && conn->handler->domore_getsock)
651 return conn->handler->domore_getsock(conn, socks, numsocks);
652 return GETSOCK_BLANK;
655 /* returns bitmapped flags for this handle and its sockets */
656 static int multi_getsock(struct SessionHandle *data,
657 curl_socket_t *socks, /* points to numsocks number
661 /* If the pipe broke, or if there's no connection left for this easy handle,
662 then we MUST bail out now with no bitmask set. The no connection case can
663 happen when this is called from curl_multi_remove_handle() =>
664 singlesocket() => multi_getsock().
666 if(data->state.pipe_broke || !data->easy_conn)
669 if(data->mstate > CURLM_STATE_CONNECT &&
670 data->mstate < CURLM_STATE_COMPLETED) {
671 /* Set up ownership correctly */
672 data->easy_conn->data = data;
675 switch(data->mstate) {
677 #if 0 /* switch back on these cases to get the compiler to check for all enums
679 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
680 case CURLM_STATE_COMPLETED:
681 case CURLM_STATE_MSGSENT:
682 case CURLM_STATE_INIT:
683 case CURLM_STATE_CONNECT:
684 case CURLM_STATE_WAITDO:
685 case CURLM_STATE_DONE:
686 case CURLM_STATE_LAST:
687 /* this will get called with CURLM_STATE_COMPLETED when a handle is
692 case CURLM_STATE_WAITRESOLVE:
693 return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
695 case CURLM_STATE_PROTOCONNECT:
696 return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
699 case CURLM_STATE_DOING:
700 return Curl_doing_getsock(data->easy_conn, socks, numsocks);
702 case CURLM_STATE_WAITPROXYCONNECT:
703 case CURLM_STATE_WAITCONNECT:
704 return waitconnect_getsock(data->easy_conn, socks, numsocks);
706 case CURLM_STATE_DO_MORE:
707 return domore_getsock(data->easy_conn, socks, numsocks);
709 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
710 to waiting for the same as the *PERFORM
712 case CURLM_STATE_PERFORM:
713 case CURLM_STATE_WAITPERFORM:
714 return Curl_single_getsock(data->easy_conn, socks, numsocks);
719 CURLMcode curl_multi_fdset(CURLM *multi_handle,
720 fd_set *read_fd_set, fd_set *write_fd_set,
721 fd_set *exc_fd_set, int *max_fd)
723 /* Scan through all the easy handles to get the file descriptors set.
724 Some easy handles may not have connected to the remote host yet,
725 and then we must make sure that is done. */
726 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
727 struct SessionHandle *data;
729 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
732 (void)exc_fd_set; /* not used */
734 if(!GOOD_MULTI_HANDLE(multi))
735 return CURLM_BAD_HANDLE;
739 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
741 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
742 curl_socket_t s = CURL_SOCKET_BAD;
744 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
745 FD_SET(sockbunch[i], read_fd_set);
748 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
749 FD_SET(sockbunch[i], write_fd_set);
752 if(s == CURL_SOCKET_BAD)
753 /* this socket is unused, break out of loop */
756 if((int)s > this_max_fd)
757 this_max_fd = (int)s;
761 data = data->next; /* check next handle */
764 *max_fd = this_max_fd;
769 CURLMcode curl_multi_wait(CURLM *multi_handle,
770 struct curl_waitfd extra_fds[],
771 unsigned int extra_nfds,
775 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
776 struct SessionHandle *data;
777 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
780 unsigned int nfds = 0;
781 unsigned int curlfds;
782 struct pollfd *ufds = NULL;
783 long timeout_internal;
785 if(!GOOD_MULTI_HANDLE(multi))
786 return CURLM_BAD_HANDLE;
788 /* If the internally desired timeout is actually shorter than requested from
789 the outside, then use the shorter time! But only if the internal timer
790 is actually larger than 0! */
791 (void)multi_timeout(multi, &timeout_internal);
792 if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
793 timeout_ms = (int)timeout_internal;
795 /* Count up how many fds we have from the multi handle */
798 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
800 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
801 curl_socket_t s = CURL_SOCKET_BAD;
803 if(bitmap & GETSOCK_READSOCK(i)) {
807 if(bitmap & GETSOCK_WRITESOCK(i)) {
811 if(s == CURL_SOCKET_BAD) {
816 data = data->next; /* check next handle */
819 curlfds = nfds; /* number of internal file descriptors */
820 nfds += extra_nfds; /* add the externally provided ones */
823 ufds = malloc(nfds * sizeof(struct pollfd));
825 return CURLM_OUT_OF_MEMORY;
829 /* only do the second loop if we found descriptors in the first stage run
833 /* Add the curl handles to our pollfds first */
836 bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
838 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
839 curl_socket_t s = CURL_SOCKET_BAD;
841 if(bitmap & GETSOCK_READSOCK(i)) {
842 ufds[nfds].fd = sockbunch[i];
843 ufds[nfds].events = POLLIN;
847 if(bitmap & GETSOCK_WRITESOCK(i)) {
848 ufds[nfds].fd = sockbunch[i];
849 ufds[nfds].events = POLLOUT;
853 if(s == CURL_SOCKET_BAD) {
858 data = data->next; /* check next handle */
862 /* Add external file descriptions from poll-like struct curl_waitfd */
863 for(i = 0; i < extra_nfds; i++) {
864 ufds[nfds].fd = extra_fds[i].fd;
865 ufds[nfds].events = 0;
866 if(extra_fds[i].events & CURL_WAIT_POLLIN)
867 ufds[nfds].events |= POLLIN;
868 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
869 ufds[nfds].events |= POLLPRI;
870 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
871 ufds[nfds].events |= POLLOUT;
877 i = Curl_poll(ufds, nfds, timeout_ms);
881 /* copy revents results from the poll to the curl_multi_wait poll
882 struct, the bit values of the actual underlying poll() implementation
883 may not be the same as the ones in the public libcurl API! */
884 for(j = 0; j < extra_nfds; j++) {
885 unsigned short mask = 0;
886 unsigned r = ufds[curlfds + j].revents;
889 mask |= CURL_WAIT_POLLIN;
891 mask |= CURL_WAIT_POLLOUT;
893 mask |= CURL_WAIT_POLLPRI;
895 extra_fds[j].revents = mask;
908 static CURLMcode multi_runsingle(struct Curl_multi *multi,
910 struct SessionHandle *data)
912 struct Curl_message *msg = NULL;
915 bool protocol_connect = FALSE;
916 bool dophase_done = FALSE;
918 CURLMcode result = CURLM_OK;
919 struct SingleRequest *k;
923 if(!GOOD_EASY_HANDLE(data))
924 return CURLM_BAD_EASY_HANDLE;
927 /* this is a single-iteration do-while loop just to allow a
928 break to skip to the end of it */
929 bool disconnect_conn = FALSE;
931 /* Handle the case when the pipe breaks, i.e., the connection
932 we're using gets cleaned up and we're left with nothing. */
933 if(data->state.pipe_broke) {
934 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
935 (void *)data, data->state.path);
937 if(data->mstate < CURLM_STATE_COMPLETED) {
938 /* Head back to the CONNECT state */
939 multistate(data, CURLM_STATE_CONNECT);
940 result = CURLM_CALL_MULTI_PERFORM;
941 data->result = CURLE_OK;
944 data->state.pipe_broke = FALSE;
945 data->easy_conn = NULL;
949 if(!data->easy_conn &&
950 data->mstate > CURLM_STATE_CONNECT &&
951 data->mstate < CURLM_STATE_DONE) {
952 /* In all these states, the code will blindly access 'data->easy_conn'
953 so this is precaution that it isn't NULL. And it silences static
955 failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
956 return CURLM_INTERNAL_ERROR;
959 if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
960 data->mstate < CURLM_STATE_COMPLETED)
961 /* Make sure we set the connection's current owner */
962 data->easy_conn->data = data;
964 if(data->easy_conn &&
965 (data->mstate >= CURLM_STATE_CONNECT) &&
966 (data->mstate < CURLM_STATE_COMPLETED)) {
967 /* we need to wait for the connect state as only then is the start time
968 stored, but we must not check already completed handles */
970 timeout_ms = Curl_timeleft(data, &now,
971 (data->mstate <= CURLM_STATE_WAITDO)?
975 /* Handle timed out */
976 if(data->mstate == CURLM_STATE_WAITRESOLVE)
977 failf(data, "Resolving timed out after %ld milliseconds",
978 Curl_tvdiff(now, data->progress.t_startsingle));
979 else if(data->mstate == CURLM_STATE_WAITCONNECT)
980 failf(data, "Connection timed out after %ld milliseconds",
981 Curl_tvdiff(now, data->progress.t_startsingle));
984 failf(data, "Operation timed out after %ld milliseconds with %"
985 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
986 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
990 /* Force the connection closed because the server could continue to
991 send us stuff at any time. (The disconnect_conn logic used below
992 doesn't work at this point). */
993 data->easy_conn->bits.close = TRUE;
994 data->result = CURLE_OPERATION_TIMEDOUT;
995 multistate(data, CURLM_STATE_COMPLETED);
1000 switch(data->mstate) {
1001 case CURLM_STATE_INIT:
1002 /* init this transfer. */
1003 data->result=Curl_pretransfer(data);
1005 if(CURLE_OK == data->result) {
1006 /* after init, go CONNECT */
1007 multistate(data, CURLM_STATE_CONNECT);
1008 result = CURLM_CALL_MULTI_PERFORM;
1012 case CURLM_STATE_CONNECT_PEND:
1013 /* We will stay here until there is a connection available. Then
1014 we try again in the CURLM_STATE_CONNECT state. */
1017 case CURLM_STATE_CONNECT:
1018 /* Connect. We want to get a connection identifier filled in. */
1019 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1020 data->result = Curl_connect(data, &data->easy_conn,
1021 &async, &protocol_connect);
1022 if(CURLE_NO_CONNECTION_AVAILABLE == data->result) {
1023 /* There was no connection available. We will go to the pending
1024 state and wait for an available connection. */
1025 multistate(data, CURLM_STATE_CONNECT_PEND);
1026 data->result = CURLE_OK;
1030 if(CURLE_OK == data->result) {
1031 /* Add this handle to the send or pend pipeline */
1032 data->result = Curl_add_handle_to_pipeline(data, data->easy_conn);
1033 if(CURLE_OK != data->result)
1034 disconnect_conn = TRUE;
1037 /* We're now waiting for an asynchronous name lookup */
1038 multistate(data, CURLM_STATE_WAITRESOLVE);
1040 /* after the connect has been sent off, go WAITCONNECT unless the
1041 protocol connect is already done and we can go directly to
1043 result = CURLM_CALL_MULTI_PERFORM;
1045 if(protocol_connect)
1046 multistate(data, multi->pipelining_enabled?
1047 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1049 #ifndef CURL_DISABLE_HTTP
1050 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1051 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1054 multistate(data, CURLM_STATE_WAITCONNECT);
1061 case CURLM_STATE_WAITRESOLVE:
1062 /* awaiting an asynch name resolve to complete */
1064 struct Curl_dns_entry *dns = NULL;
1066 /* check if we have the name resolved by now */
1067 data->result = Curl_resolver_is_resolved(data->easy_conn, &dns);
1069 /* Update sockets here, because the socket(s) may have been
1070 closed and the application thus needs to be told, even if it
1071 is likely that the same socket(s) will again be used further
1072 down. If the name has not yet been resolved, it is likely
1073 that new sockets have been opened in an attempt to contact
1074 another resolver. */
1075 singlesocket(multi, data);
1078 /* Perform the next step in the connection phase, and then move on
1079 to the WAITCONNECT state */
1080 data->result = Curl_async_resolved(data->easy_conn,
1083 if(CURLE_OK != data->result)
1084 /* if Curl_async_resolved() returns failure, the connection struct
1085 is already freed and gone */
1086 data->easy_conn = NULL; /* no more connection */
1088 /* call again please so that we get the next socket setup */
1089 result = CURLM_CALL_MULTI_PERFORM;
1090 if(protocol_connect)
1091 multistate(data, multi->pipelining_enabled?
1092 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1094 #ifndef CURL_DISABLE_HTTP
1095 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1096 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1099 multistate(data, CURLM_STATE_WAITCONNECT);
1104 if(CURLE_OK != data->result) {
1105 /* failure detected */
1106 disconnect_conn = TRUE;
1112 #ifndef CURL_DISABLE_HTTP
1113 case CURLM_STATE_WAITPROXYCONNECT:
1114 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1115 data->result = Curl_http_connect(data->easy_conn, &protocol_connect);
1117 if(data->easy_conn->bits.proxy_connect_closed) {
1118 /* reset the error buffer */
1119 if(data->set.errorbuffer)
1120 data->set.errorbuffer[0] = '\0';
1121 data->state.errorbuf = FALSE;
1123 data->result = CURLE_OK;
1124 result = CURLM_CALL_MULTI_PERFORM;
1125 multistate(data, CURLM_STATE_CONNECT);
1127 else if(CURLE_OK == data->result) {
1128 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1129 multistate(data, CURLM_STATE_WAITCONNECT);
1134 case CURLM_STATE_WAITCONNECT:
1135 /* awaiting a completion of an asynch connect */
1136 data->result = Curl_is_connected(data->easy_conn,
1142 /* if everything is still fine we do the protocol-specific connect
1144 data->result = Curl_protocol_connect(data->easy_conn,
1148 if(CURLE_OK != data->result) {
1149 /* failure detected */
1150 /* Just break, the cleaning up is handled all in one place */
1151 disconnect_conn = TRUE;
1156 if(!protocol_connect) {
1157 /* We have a TCP connection, but 'protocol_connect' may be false
1158 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1159 connect is TRUE, we move on to STATE_DO.
1160 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1162 #ifndef CURL_DISABLE_HTTP
1163 if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1164 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1167 multistate(data, CURLM_STATE_PROTOCONNECT);
1171 /* after the connect has completed, go WAITDO or DO */
1172 multistate(data, multi->pipelining_enabled?
1173 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1175 result = CURLM_CALL_MULTI_PERFORM;
1179 case CURLM_STATE_PROTOCONNECT:
1180 /* protocol-specific connect phase */
1181 data->result = Curl_protocol_connecting(data->easy_conn,
1183 if((data->result == CURLE_OK) && protocol_connect) {
1184 /* after the connect has completed, go WAITDO or DO */
1185 multistate(data, multi->pipelining_enabled?
1186 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1187 result = CURLM_CALL_MULTI_PERFORM;
1189 else if(data->result) {
1190 /* failure detected */
1191 Curl_posttransfer(data);
1192 Curl_done(&data->easy_conn, data->result, TRUE);
1193 disconnect_conn = TRUE;
1197 case CURLM_STATE_WAITDO:
1198 /* Wait for our turn to DO when we're pipelining requests */
1200 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
1201 data->easy_conn->connection_id,
1202 data->easy_conn->send_pipe->size,
1203 data->easy_conn->writechannel_inuse?"TRUE":"FALSE",
1204 isHandleAtHead(data,
1205 data->easy_conn->send_pipe)?"TRUE":"FALSE");
1207 if(!data->easy_conn->writechannel_inuse &&
1208 isHandleAtHead(data,
1209 data->easy_conn->send_pipe)) {
1210 /* Grab the channel */
1211 data->easy_conn->writechannel_inuse = TRUE;
1212 multistate(data, CURLM_STATE_DO);
1213 result = CURLM_CALL_MULTI_PERFORM;
1217 case CURLM_STATE_DO:
1218 if(data->set.connect_only) {
1219 /* keep connection open for application to use the socket */
1220 data->easy_conn->bits.close = FALSE;
1221 multistate(data, CURLM_STATE_DONE);
1222 data->result = CURLE_OK;
1223 result = CURLM_CALL_MULTI_PERFORM;
1226 /* Perform the protocol's DO action */
1227 data->result = Curl_do(&data->easy_conn, &dophase_done);
1229 /* When Curl_do() returns failure, data->easy_conn might be NULL! */
1231 if(CURLE_OK == data->result) {
1233 /* some steps needed for wildcard matching */
1234 if(data->set.wildcardmatch) {
1235 struct WildcardData *wc = &data->wildcard;
1236 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1237 /* skip some states if it is important */
1238 Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1239 multistate(data, CURLM_STATE_DONE);
1240 result = CURLM_CALL_MULTI_PERFORM;
1244 /* DO was not completed in one function call, we must continue
1246 multistate(data, CURLM_STATE_DOING);
1250 /* after DO, go DO_DONE... or DO_MORE */
1251 else if(data->easy_conn->bits.do_more) {
1252 /* we're supposed to do more, but we need to sit down, relax
1253 and wait a little while first */
1254 multistate(data, CURLM_STATE_DO_MORE);
1258 /* we're done with the DO, now DO_DONE */
1259 multistate(data, CURLM_STATE_DO_DONE);
1260 result = CURLM_CALL_MULTI_PERFORM;
1263 else if((CURLE_SEND_ERROR == data->result) &&
1264 data->easy_conn->bits.reuse) {
1266 * In this situation, a connection that we were trying to use
1267 * may have unexpectedly died. If possible, send the connection
1268 * back to the CONNECT phase so we can try again.
1270 char *newurl = NULL;
1271 followtype follow=FOLLOW_NONE;
1275 drc = Curl_retry_request(data->easy_conn, &newurl);
1277 /* a failure here pretty much implies an out of memory */
1279 disconnect_conn = TRUE;
1282 retry = (newurl)?TRUE:FALSE;
1284 Curl_posttransfer(data);
1285 drc = Curl_done(&data->easy_conn, data->result, FALSE);
1287 /* When set to retry the connection, we must to go back to
1288 * the CONNECT state */
1290 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1291 follow = FOLLOW_RETRY;
1292 drc = Curl_follow(data, newurl, follow);
1293 if(drc == CURLE_OK) {
1294 multistate(data, CURLM_STATE_CONNECT);
1295 result = CURLM_CALL_MULTI_PERFORM;
1296 data->result = CURLE_OK;
1305 /* done didn't return OK or SEND_ERROR */
1311 /* Have error handler disconnect conn if we can't retry */
1312 disconnect_conn = TRUE;
1316 /* failure detected */
1317 Curl_posttransfer(data);
1319 Curl_done(&data->easy_conn, data->result, FALSE);
1320 disconnect_conn = TRUE;
1325 case CURLM_STATE_DOING:
1326 /* we continue DOING until the DO phase is complete */
1327 data->result = Curl_protocol_doing(data->easy_conn,
1329 if(CURLE_OK == data->result) {
1331 /* after DO, go DO_DONE or DO_MORE */
1332 multistate(data, data->easy_conn->bits.do_more?
1333 CURLM_STATE_DO_MORE:
1334 CURLM_STATE_DO_DONE);
1335 result = CURLM_CALL_MULTI_PERFORM;
1336 } /* dophase_done */
1339 /* failure detected */
1340 Curl_posttransfer(data);
1341 Curl_done(&data->easy_conn, data->result, FALSE);
1342 disconnect_conn = TRUE;
1346 case CURLM_STATE_DO_MORE:
1348 * When we are connected, DO MORE and then go DO_DONE
1350 data->result = Curl_do_more(data->easy_conn, &control);
1352 /* No need to remove this handle from the send pipeline here since that
1353 is done in Curl_done() */
1354 if(CURLE_OK == data->result) {
1356 /* if positive, advance to DO_DONE
1357 if negative, go back to DOING */
1358 multistate(data, control==1?
1359 CURLM_STATE_DO_DONE:
1361 result = CURLM_CALL_MULTI_PERFORM;
1364 /* stay in DO_MORE */
1368 /* failure detected */
1369 Curl_posttransfer(data);
1370 Curl_done(&data->easy_conn, data->result, FALSE);
1371 disconnect_conn = TRUE;
1375 case CURLM_STATE_DO_DONE:
1376 /* Move ourselves from the send to recv pipeline */
1377 Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
1378 /* Check if we can move pending requests to send pipe */
1379 Curl_multi_process_pending_handles(multi);
1380 multistate(data, CURLM_STATE_WAITPERFORM);
1381 result = CURLM_CALL_MULTI_PERFORM;
1384 case CURLM_STATE_WAITPERFORM:
1385 /* Wait for our turn to PERFORM */
1386 if(!data->easy_conn->readchannel_inuse &&
1387 isHandleAtHead(data,
1388 data->easy_conn->recv_pipe)) {
1389 /* Grab the channel */
1390 data->easy_conn->readchannel_inuse = TRUE;
1391 multistate(data, CURLM_STATE_PERFORM);
1392 result = CURLM_CALL_MULTI_PERFORM;
1396 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
1397 data->easy_conn->connection_id,
1398 data->easy_conn->recv_pipe->size,
1399 data->easy_conn->readchannel_inuse?"TRUE":"FALSE",
1400 isHandleAtHead(data,
1401 data->easy_conn->recv_pipe)?"TRUE":"FALSE");
1406 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1407 /* if both rates are within spec, resume transfer */
1408 if(Curl_pgrsUpdate(data->easy_conn))
1409 data->result = CURLE_ABORTED_BY_CALLBACK;
1411 data->result = Curl_speedcheck(data, now);
1413 if(( (data->set.max_send_speed == 0) ||
1414 (data->progress.ulspeed < data->set.max_send_speed )) &&
1415 ( (data->set.max_recv_speed == 0) ||
1416 (data->progress.dlspeed < data->set.max_recv_speed)))
1417 multistate(data, CURLM_STATE_PERFORM);
1420 case CURLM_STATE_PERFORM:
1422 char *newurl = NULL;
1425 /* check if over send speed */
1426 if((data->set.max_send_speed > 0) &&
1427 (data->progress.ulspeed > data->set.max_send_speed)) {
1430 multistate(data, CURLM_STATE_TOOFAST);
1432 /* calculate upload rate-limitation timeout. */
1433 buffersize = (int)(data->set.buffer_size ?
1434 data->set.buffer_size : BUFSIZE);
1435 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1436 data->progress.ulspeed, buffersize);
1437 Curl_expire(data, timeout_ms);
1441 /* check if over recv speed */
1442 if((data->set.max_recv_speed > 0) &&
1443 (data->progress.dlspeed > data->set.max_recv_speed)) {
1446 multistate(data, CURLM_STATE_TOOFAST);
1448 /* Calculate download rate-limitation timeout. */
1449 buffersize = (int)(data->set.buffer_size ?
1450 data->set.buffer_size : BUFSIZE);
1451 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1452 data->progress.dlspeed, buffersize);
1453 Curl_expire(data, timeout_ms);
1457 /* read/write data if it is ready to do so */
1458 data->result = Curl_readwrite(data->easy_conn, &done);
1462 if(!(k->keepon & KEEP_RECV)) {
1463 /* We're done receiving */
1464 data->easy_conn->readchannel_inuse = FALSE;
1467 if(!(k->keepon & KEEP_SEND)) {
1468 /* We're done sending */
1469 data->easy_conn->writechannel_inuse = FALSE;
1472 if(done || (data->result == CURLE_RECV_ERROR)) {
1473 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1474 * condition and the server closed the re-used connection exactly when
1475 * we wanted to use it, so figure out if that is indeed the case.
1477 CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
1479 retry = (newurl)?TRUE:FALSE;
1482 /* if we are to retry, set the result to OK and consider the
1484 data->result = CURLE_OK;
1491 * The transfer phase returned error, we mark the connection to get
1492 * closed to prevent being re-used. This is because we can't possibly
1493 * know if the connection is in a good shape or not now. Unless it is
1494 * a protocol which uses two "channels" like FTP, as then the error
1495 * happened in the data connection.
1498 if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
1499 data->easy_conn->bits.close = TRUE;
1501 Curl_posttransfer(data);
1502 Curl_done(&data->easy_conn, data->result, FALSE);
1505 followtype follow=FOLLOW_NONE;
1507 /* call this even if the readwrite function returned error */
1508 Curl_posttransfer(data);
1510 /* we're no longer receiving */
1511 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1513 /* expire the new receiving pipeline head */
1514 if(data->easy_conn->recv_pipe->head)
1515 Curl_expire(data->easy_conn->recv_pipe->head->ptr, 1);
1517 /* Check if we can move pending requests to send pipe */
1518 Curl_multi_process_pending_handles(multi);
1520 /* When we follow redirects or is set to retry the connection, we must
1521 to go back to the CONNECT state */
1522 if(data->req.newurl || retry) {
1524 /* if the URL is a follow-location and not just a retried request
1525 then figure out the URL here */
1526 newurl = data->req.newurl;
1527 data->req.newurl = NULL;
1528 follow = FOLLOW_REDIR;
1531 follow = FOLLOW_RETRY;
1532 data->result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1533 if(CURLE_OK == data->result) {
1534 data->result = Curl_follow(data, newurl, follow);
1535 if(CURLE_OK == data->result) {
1536 multistate(data, CURLM_STATE_CONNECT);
1537 result = CURLM_CALL_MULTI_PERFORM;
1538 newurl = NULL; /* handed over the memory ownership to
1539 Curl_follow(), make sure we don't free() it
1545 /* after the transfer is done, go DONE */
1547 /* but first check to see if we got a location info even though we're
1548 not following redirects */
1549 if(data->req.location) {
1552 newurl = data->req.location;
1553 data->req.location = NULL;
1554 data->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1555 if(CURLE_OK == data->result)
1556 newurl = NULL; /* allocation was handed over Curl_follow() */
1558 disconnect_conn = TRUE;
1561 multistate(data, CURLM_STATE_DONE);
1562 result = CURLM_CALL_MULTI_PERFORM;
1571 case CURLM_STATE_DONE:
1572 /* this state is highly transient, so run another loop after this */
1573 result = CURLM_CALL_MULTI_PERFORM;
1575 if(data->easy_conn) {
1576 /* Remove ourselves from the receive pipeline, if we are there. */
1577 Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
1578 /* Check if we can move pending requests to send pipe */
1579 Curl_multi_process_pending_handles(multi);
1581 /* post-transfer command */
1582 data->result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
1584 * If there are other handles on the pipeline, Curl_done won't set
1585 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1586 * access free'd data, if the connection is free'd and the handle
1587 * removed before we perform the processing in CURLM_STATE_COMPLETED
1590 data->easy_conn = NULL;
1593 if(data->set.wildcardmatch) {
1594 if(data->wildcard.state != CURLWC_DONE) {
1595 /* if a wildcard is set and we are not ending -> lets start again
1596 with CURLM_STATE_INIT */
1597 multistate(data, CURLM_STATE_INIT);
1602 /* after we have DONE what we're supposed to do, go COMPLETED, and
1603 it doesn't matter what the Curl_done() returned! */
1604 multistate(data, CURLM_STATE_COMPLETED);
1607 case CURLM_STATE_COMPLETED:
1608 /* this is a completed transfer, it is likely to still be connected */
1610 /* This node should be delinked from the list now and we should post
1611 an information message that we are complete. */
1613 /* Important: reset the conn pointer so that we don't point to memory
1614 that could be freed anytime */
1615 data->easy_conn = NULL;
1617 Curl_expire(data, 0); /* stop all timers */
1620 case CURLM_STATE_MSGSENT:
1621 return CURLM_OK; /* do nothing */
1624 return CURLM_INTERNAL_ERROR;
1627 if(data->mstate < CURLM_STATE_COMPLETED) {
1628 if(CURLE_OK != data->result) {
1630 * If an error was returned, and we aren't in completed state now,
1631 * then we go to completed and consider this transfer aborted.
1634 /* NOTE: no attempt to disconnect connections must be made
1635 in the case blocks above - cleanup happens only here */
1637 data->state.pipe_broke = FALSE;
1639 if(data->easy_conn) {
1640 /* if this has a connection, unsubscribe from the pipelines */
1641 data->easy_conn->writechannel_inuse = FALSE;
1642 data->easy_conn->readchannel_inuse = FALSE;
1643 Curl_removeHandleFromPipeline(data,
1644 data->easy_conn->send_pipe);
1645 Curl_removeHandleFromPipeline(data,
1646 data->easy_conn->recv_pipe);
1647 /* Check if we can move pending requests to send pipe */
1648 Curl_multi_process_pending_handles(multi);
1650 if(disconnect_conn) {
1651 /* disconnect properly */
1652 Curl_disconnect(data->easy_conn, /* dead_connection */ FALSE);
1654 /* This is where we make sure that the easy_conn pointer is reset.
1655 We don't have to do this in every case block above where a
1656 failure is detected */
1657 data->easy_conn = NULL;
1660 else if(data->mstate == CURLM_STATE_CONNECT) {
1661 /* Curl_connect() failed */
1662 (void)Curl_posttransfer(data);
1665 multistate(data, CURLM_STATE_COMPLETED);
1667 /* if there's still a connection to use, call the progress function */
1668 else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
1669 /* aborted due to progress callback return code must close the
1671 data->easy_conn->bits.close = TRUE;
1673 /* if not yet in DONE state, go there, otherwise COMPLETED */
1674 multistate(data, (data->mstate < CURLM_STATE_DONE)?
1675 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1676 result = CURLM_CALL_MULTI_PERFORM;
1679 } WHILE_FALSE; /* just to break out from! */
1681 if(CURLM_STATE_COMPLETED == data->mstate) {
1682 /* now fill in the Curl_message with this info */
1685 msg->extmsg.msg = CURLMSG_DONE;
1686 msg->extmsg.easy_handle = data;
1687 msg->extmsg.data.result = data->result;
1689 result = multi_addmsg(multi, msg);
1691 multistate(data, CURLM_STATE_MSGSENT);
1698 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1700 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1701 struct SessionHandle *data;
1702 CURLMcode returncode=CURLM_OK;
1703 struct Curl_tree *t;
1704 struct timeval now = Curl_tvnow();
1706 if(!GOOD_MULTI_HANDLE(multi))
1707 return CURLM_BAD_HANDLE;
1712 struct WildcardData *wc = &data->wildcard;
1714 if(data->set.wildcardmatch) {
1716 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1718 return CURLM_OUT_OF_MEMORY;
1723 result = multi_runsingle(multi, now, data);
1724 while(CURLM_CALL_MULTI_PERFORM == result);
1726 if(data->set.wildcardmatch) {
1727 /* destruct wildcard structures if it is needed */
1728 if(wc->state == CURLWC_DONE || result)
1729 Curl_wildcard_dtor(wc);
1733 returncode = result;
1735 data = data->next; /* operate on next handle */
1739 * Simply remove all expired timers from the splay since handles are dealt
1740 * with unconditionally by this function and curl_multi_timeout() requires
1741 * that already passed/handled expire times are removed from the splay.
1743 * It is important that the 'now' value is set at the entry of this function
1744 * and not for the current time as it may have ticked a little while since
1745 * then and then we risk this loop to remove timers that actually have not
1749 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1751 /* the removed may have another timeout in queue */
1752 (void)add_next_timeout(now, multi, t->payload);
1756 *running_handles = multi->num_alive;
1758 if(CURLM_OK >= returncode)
1759 update_timer(multi);
1764 static void close_all_connections(struct Curl_multi *multi)
1766 struct connectdata *conn;
1768 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1770 conn->data = multi->closure_handle;
1772 /* This will remove the connection from the cache */
1773 (void)Curl_disconnect(conn, FALSE);
1775 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1779 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1781 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1782 struct SessionHandle *data;
1783 struct SessionHandle *nextdata;
1785 if(GOOD_MULTI_HANDLE(multi)) {
1786 multi->type = 0; /* not good anymore */
1788 /* Close all the connections in the connection cache */
1789 close_all_connections(multi);
1791 if(multi->closure_handle) {
1792 multi->closure_handle->dns.hostcache = multi->hostcache;
1793 Curl_hostcache_clean(multi->closure_handle,
1794 multi->closure_handle->dns.hostcache);
1796 Curl_close(multi->closure_handle);
1797 multi->closure_handle = NULL;
1800 Curl_hash_destroy(multi->sockhash);
1801 multi->sockhash = NULL;
1803 Curl_conncache_destroy(multi->conn_cache);
1804 multi->conn_cache = NULL;
1806 /* remove the pending list of messages */
1807 Curl_llist_destroy(multi->msglist, NULL);
1808 multi->msglist = NULL;
1810 /* remove all easy handles */
1811 data = multi->easyp;
1813 nextdata=data->next;
1814 if(data->dns.hostcachetype == HCACHE_MULTI) {
1815 /* clear out the usage of the shared DNS cache */
1816 Curl_hostcache_clean(data, data->dns.hostcache);
1817 data->dns.hostcache = NULL;
1818 data->dns.hostcachetype = HCACHE_NONE;
1821 /* Clear the pointer to the connection cache */
1822 data->state.conn_cache = NULL;
1823 data->multi = NULL; /* clear the association */
1828 Curl_hash_destroy(multi->hostcache);
1829 multi->hostcache = NULL;
1831 /* Free the blacklists by setting them to NULL */
1832 Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
1833 Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
1840 return CURLM_BAD_HANDLE;
1844 * curl_multi_info_read()
1846 * This function is the primary way for a multi/multi_socket application to
1847 * figure out if a transfer has ended. We MUST make this function as fast as
1848 * possible as it will be polled frequently and we MUST NOT scan any lists in
1849 * here to figure out things. We must scale fine to thousands of handles and
1850 * beyond. The current design is fully O(1).
1853 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1855 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1856 struct Curl_message *msg;
1858 *msgs_in_queue = 0; /* default to none */
1860 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1861 /* there is one or more messages in the list */
1862 struct curl_llist_element *e;
1864 /* extract the head of the list to return */
1865 e = multi->msglist->head;
1869 /* remove the extracted entry */
1870 Curl_llist_remove(multi->msglist, e, NULL);
1872 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1874 return &msg->extmsg;
1881 * singlesocket() checks what sockets we deal with and their "action state"
1882 * and if we have a different state in any of those sockets from last time we
1883 * call the callback accordingly.
1885 static void singlesocket(struct Curl_multi *multi,
1886 struct SessionHandle *data)
1888 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1890 struct Curl_sh_entry *entry;
1893 unsigned int curraction;
1894 bool remove_sock_from_hash;
1896 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1897 socks[i] = CURL_SOCKET_BAD;
1899 /* Fill in the 'current' struct with the state as it is now: what sockets to
1900 supervise and for what actions */
1901 curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
1903 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1904 sockets we should have from now on. Detect the differences, remove no
1905 longer supervised ones and add new ones */
1907 /* walk over the sockets we got right now */
1908 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1909 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1911 int action = CURL_POLL_NONE;
1915 /* get it from the hash */
1916 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1918 if(curraction & GETSOCK_READSOCK(i))
1919 action |= CURL_POLL_IN;
1920 if(curraction & GETSOCK_WRITESOCK(i))
1921 action |= CURL_POLL_OUT;
1924 /* yeps, already present so check if it has the same action set */
1925 if(entry->action == action)
1926 /* same, continue */
1930 /* this is a socket we didn't have before, add it! */
1931 entry = sh_addentry(multi->sockhash, s, data);
1937 /* we know (entry != NULL) at this point, see the logic above */
1938 if(multi->socket_cb)
1939 multi->socket_cb(data,
1942 multi->socket_userp,
1945 entry->action = action; /* store the current action state */
1948 num = i; /* number of sockets */
1950 /* when we've walked over all the sockets we should have right now, we must
1951 make sure to detect sockets that are removed */
1952 for(i=0; i< data->numsocks; i++) {
1954 s = data->sockets[i];
1955 for(j=0; j<num; j++) {
1957 /* this is still supervised */
1958 s = CURL_SOCKET_BAD;
1962 if(s != CURL_SOCKET_BAD) {
1964 /* this socket has been removed. Tell the app to remove it */
1965 remove_sock_from_hash = TRUE;
1967 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1969 /* check if the socket to be removed serves a connection which has
1970 other easy-s in a pipeline. In this case the socket should not be
1972 struct connectdata *easy_conn = data->easy_conn;
1974 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1975 /* the handle should not be removed from the pipe yet */
1976 remove_sock_from_hash = FALSE;
1978 /* Update the sockhash entry to instead point to the next in line
1979 for the recv_pipe, or the first (in case this particular easy
1981 if(entry->easy == data) {
1982 if(isHandleAtHead(data, easy_conn->recv_pipe))
1983 entry->easy = easy_conn->recv_pipe->head->next->ptr;
1985 entry->easy = easy_conn->recv_pipe->head->ptr;
1988 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1989 /* the handle should not be removed from the pipe yet */
1990 remove_sock_from_hash = FALSE;
1992 /* Update the sockhash entry to instead point to the next in line
1993 for the send_pipe, or the first (in case this particular easy
1995 if(entry->easy == data) {
1996 if(isHandleAtHead(data, easy_conn->send_pipe))
1997 entry->easy = easy_conn->send_pipe->head->next->ptr;
1999 entry->easy = easy_conn->send_pipe->head->ptr;
2002 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2003 when action will be asked on the socket (see multi_socket()), the
2004 head of the correct pipe will be taken according to the
2009 /* just a precaution, this socket really SHOULD be in the hash already
2010 but in case it isn't, we don't have to tell the app to remove it
2011 either since it never got to know about it */
2012 remove_sock_from_hash = FALSE;
2014 if(remove_sock_from_hash) {
2015 /* in this case 'entry' is always non-NULL */
2016 if(multi->socket_cb)
2017 multi->socket_cb(data,
2020 multi->socket_userp,
2022 sh_delentry(multi->sockhash, s);
2028 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2029 data->numsocks = num;
2033 * Curl_multi_closed()
2035 * Used by the connect code to tell the multi_socket code that one of the
2036 * sockets we were using have just been closed. This function will then
2037 * remove it from the sockethash for this handle to make the multi_socket API
2038 * behave properly, especially for the case when libcurl will create another
2039 * socket again and it gets the same file descriptor number.
2042 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
2044 struct Curl_multi *multi = conn->data->multi;
2046 /* this is set if this connection is part of a handle that is added to
2047 a multi handle, and only then this is necessary */
2048 struct Curl_sh_entry *entry =
2049 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2052 if(multi->socket_cb)
2053 multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
2054 multi->socket_userp,
2057 /* now remove it from the socket hash */
2058 sh_delentry(multi->sockhash, s);
2066 * add_next_timeout()
2068 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2069 * when it has just been removed from the splay tree because the timeout has
2070 * expired. This function is then to advance in the list to pick the next
2071 * timeout to use (skip the already expired ones) and add this node back to
2072 * the splay tree again.
2074 * The splay tree only has each sessionhandle as a single node and the nearest
2075 * timeout is used to sort it on.
2077 static CURLMcode add_next_timeout(struct timeval now,
2078 struct Curl_multi *multi,
2079 struct SessionHandle *d)
2081 struct timeval *tv = &d->state.expiretime;
2082 struct curl_llist *list = d->state.timeoutlist;
2083 struct curl_llist_element *e;
2085 /* move over the timeout list for this specific handle and remove all
2086 timeouts that are now passed tense and store the next pending
2088 for(e = list->head; e; ) {
2089 struct curl_llist_element *n = e->next;
2090 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2092 /* remove outdated entry */
2093 Curl_llist_remove(list, e, NULL);
2095 /* the list is sorted so get out on the first mismatch */
2101 /* clear the expire times within the handles that we remove from the
2107 /* copy the first entry to 'tv' */
2108 memcpy(tv, e->ptr, sizeof(*tv));
2110 /* remove first entry from list */
2111 Curl_llist_remove(list, e, NULL);
2113 /* insert this node again into the splay */
2114 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2115 &d->state.timenode);
2120 static CURLMcode multi_socket(struct Curl_multi *multi,
2124 int *running_handles)
2126 CURLMcode result = CURLM_OK;
2127 struct SessionHandle *data = NULL;
2128 struct Curl_tree *t;
2129 struct timeval now = Curl_tvnow();
2132 /* *perform() deals with running_handles on its own */
2133 result = curl_multi_perform(multi, running_handles);
2135 /* walk through each easy handle and do the socket state change magic
2139 singlesocket(multi, data);
2143 /* or should we fall-through and do the timer-based stuff? */
2146 else if(s != CURL_SOCKET_TIMEOUT) {
2148 struct Curl_sh_entry *entry =
2149 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2152 /* Unmatched socket, we can't act on it but we ignore this fact. In
2153 real-world tests it has been proved that libevent can in fact give
2154 the application actions even though the socket was just previously
2155 asked to get removed, so thus we better survive stray socket actions
2156 and just move on. */
2161 if(data->magic != CURLEASY_MAGIC_NUMBER)
2162 /* bad bad bad bad bad bad bad */
2163 return CURLM_INTERNAL_ERROR;
2165 /* If the pipeline is enabled, take the handle which is in the head of
2166 the pipeline. If we should write into the socket, take the send_pipe
2167 head. If we should read from the socket, take the recv_pipe head. */
2168 if(data->easy_conn) {
2169 if((ev_bitmask & CURL_POLL_OUT) &&
2170 data->easy_conn->send_pipe &&
2171 data->easy_conn->send_pipe->head)
2172 data = data->easy_conn->send_pipe->head->ptr;
2173 else if((ev_bitmask & CURL_POLL_IN) &&
2174 data->easy_conn->recv_pipe &&
2175 data->easy_conn->recv_pipe->head)
2176 data = data->easy_conn->recv_pipe->head->ptr;
2179 if(data->easy_conn &&
2180 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2181 /* set socket event bitmask if they're not locked */
2182 data->easy_conn->cselect_bits = ev_bitmask;
2185 result = multi_runsingle(multi, now, data);
2186 while(CURLM_CALL_MULTI_PERFORM == result);
2188 if(data->easy_conn &&
2189 !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2190 /* clear the bitmask only if not locked */
2191 data->easy_conn->cselect_bits = 0;
2193 if(CURLM_OK >= result)
2194 /* get the socket(s) and check if the state has been changed since
2196 singlesocket(multi, data);
2198 /* Now we fall-through and do the timer-based stuff, since we don't want
2199 to force the user to have to deal with timeouts as long as at least
2200 one connection in fact has traffic. */
2202 data = NULL; /* set data to NULL again to avoid calling
2203 multi_runsingle() in case there's no need to */
2207 /* Compensate for bad precision timers that might've triggered too early.
2209 This precaution was added in commit 2c72732ebf3da5e as a result of bad
2210 resolution in the windows function use(d).
2212 The problematic case here is when using the multi_socket API and libcurl
2213 has told the application about a timeout, and that timeout is what fires
2214 off a bit early. As we don't have any IDs associated with the timeout we
2215 can't tell which timeout that fired off but we only have the times to use
2216 to check what to do. If it fires off too early, we don't run the correct
2217 actions and we don't tell the application again about the same timeout as
2218 was already first in the queue...
2220 Originally we made the timeouts run 40 milliseconds early on all systems,
2221 but now we have an #ifdef setup to provide a decent precaution inaccuracy
2225 now.tv_usec += MULTI_TIMEOUT_INACCURACY;
2226 if(now.tv_usec >= 1000000) {
2228 now.tv_usec -= 1000000;
2232 * The loop following here will go on as long as there are expire-times left
2233 * to process in the splay and 'data' will be re-assigned for every expired
2234 * handle we deal with.
2237 /* the first loop lap 'data' can be NULL */
2240 result = multi_runsingle(multi, now, data);
2241 while(CURLM_CALL_MULTI_PERFORM == result);
2243 if(CURLM_OK >= result)
2244 /* get the socket(s) and check if the state has been changed since
2246 singlesocket(multi, data);
2249 /* Check if there's one (more) expired timer to deal with! This function
2250 extracts a matching node if there is one */
2252 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2254 data = t->payload; /* assign this for next loop */
2255 (void)add_next_timeout(now, multi, t->payload);
2260 *running_handles = multi->num_alive;
2264 #undef curl_multi_setopt
2265 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2266 CURLMoption option, ...)
2268 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2269 CURLMcode res = CURLM_OK;
2272 if(!GOOD_MULTI_HANDLE(multi))
2273 return CURLM_BAD_HANDLE;
2275 va_start(param, option);
2278 case CURLMOPT_SOCKETFUNCTION:
2279 multi->socket_cb = va_arg(param, curl_socket_callback);
2281 case CURLMOPT_SOCKETDATA:
2282 multi->socket_userp = va_arg(param, void *);
2284 case CURLMOPT_PIPELINING:
2285 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2287 case CURLMOPT_TIMERFUNCTION:
2288 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2290 case CURLMOPT_TIMERDATA:
2291 multi->timer_userp = va_arg(param, void *);
2293 case CURLMOPT_MAXCONNECTS:
2294 multi->maxconnects = va_arg(param, long);
2296 case CURLMOPT_MAX_HOST_CONNECTIONS:
2297 multi->max_host_connections = va_arg(param, long);
2299 case CURLMOPT_MAX_PIPELINE_LENGTH:
2300 multi->max_pipeline_length = va_arg(param, long);
2302 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2303 multi->content_length_penalty_size = va_arg(param, long);
2305 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2306 multi->chunk_length_penalty_size = va_arg(param, long);
2308 case CURLMOPT_PIPELINING_SITE_BL:
2309 res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
2310 &multi->pipelining_site_bl);
2312 case CURLMOPT_PIPELINING_SERVER_BL:
2313 res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
2314 &multi->pipelining_server_bl);
2316 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2317 multi->max_total_connections = va_arg(param, long);
2320 res = CURLM_UNKNOWN_OPTION;
2327 /* we define curl_multi_socket() in the public multi.h header */
2328 #undef curl_multi_socket
2330 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2331 int *running_handles)
2333 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2334 0, running_handles);
2335 if(CURLM_OK >= result)
2336 update_timer((struct Curl_multi *)multi_handle);
2340 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2341 int ev_bitmask, int *running_handles)
2343 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2344 ev_bitmask, running_handles);
2345 if(CURLM_OK >= result)
2346 update_timer((struct Curl_multi *)multi_handle);
2350 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2353 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2354 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2355 if(CURLM_OK >= result)
2356 update_timer((struct Curl_multi *)multi_handle);
2360 static CURLMcode multi_timeout(struct Curl_multi *multi,
2363 static struct timeval tv_zero = {0,0};
2365 if(multi->timetree) {
2366 /* we have a tree of expire times */
2367 struct timeval now = Curl_tvnow();
2369 /* splay the lowest to the bottom */
2370 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2372 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2373 /* some time left before expiration */
2374 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2377 * Since we only provide millisecond resolution on the returned value
2378 * and the diff might be less than one millisecond here, we don't
2379 * return zero as that may cause short bursts of busyloops on fast
2380 * processors while the diff is still present but less than one
2381 * millisecond! instead we return 1 until the time is ripe.
2386 /* 0 means immediately */
2395 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2398 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2400 /* First, make some basic checks that the CURLM handle is a good handle */
2401 if(!GOOD_MULTI_HANDLE(multi))
2402 return CURLM_BAD_HANDLE;
2404 return multi_timeout(multi, timeout_ms);
2408 * Tell the application it should update its timers, if it subscribes to the
2409 * update timer callback.
2411 static int update_timer(struct Curl_multi *multi)
2415 if(!multi->timer_cb)
2417 if(multi_timeout(multi, &timeout_ms)) {
2420 if(timeout_ms < 0) {
2421 static const struct timeval none={0,0};
2422 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2423 multi->timer_lastcall = none;
2424 /* there's no timeout now but there was one previously, tell the app to
2426 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2431 /* When multi_timeout() is done, multi->timetree points to the node with the
2432 * timeout we got the (relative) time-out time for. We can thus easily check
2433 * if this is the same (fixed) time as we got in a previous call and then
2434 * avoid calling the callback again. */
2435 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2438 multi->timer_lastcall = multi->timetree->key;
2440 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2443 void Curl_multi_set_easy_connection(struct SessionHandle *handle,
2444 struct connectdata *conn)
2446 handle->easy_conn = conn;
2449 static bool isHandleAtHead(struct SessionHandle *handle,
2450 struct curl_llist *pipeline)
2452 struct curl_llist_element *curr = pipeline->head;
2454 return (curr->ptr == handle) ? TRUE : FALSE;
2460 * multi_freetimeout()
2462 * Callback used by the llist system when a single timeout list entry is
2465 static void multi_freetimeout(void *user, void *entryptr)
2469 /* the entry was plain malloc()'ed */
2474 * multi_addtimeout()
2476 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2477 * of list is always the timeout nearest in time.
2481 multi_addtimeout(struct curl_llist *timeoutlist,
2482 struct timeval *stamp)
2484 struct curl_llist_element *e;
2485 struct timeval *timedup;
2486 struct curl_llist_element *prev = NULL;
2488 timedup = malloc(sizeof(*timedup));
2490 return CURLM_OUT_OF_MEMORY;
2492 /* copy the timestamp */
2493 memcpy(timedup, stamp, sizeof(*timedup));
2495 if(Curl_llist_count(timeoutlist)) {
2496 /* find the correct spot in the list */
2497 for(e = timeoutlist->head; e; e = e->next) {
2498 struct timeval *checktime = e->ptr;
2499 long diff = curlx_tvdiff(*checktime, *timedup);
2507 this is the first timeout on the list */
2509 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2511 return CURLM_OUT_OF_MEMORY;
2520 * given a number of milliseconds from now to use to set the 'act before
2521 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2523 * Note that the timeout will be added to a queue of timeouts if it defines a
2524 * moment in time that is later than the current head of queue.
2526 * Pass zero to clear all timeout values for this handle.
2528 void Curl_expire(struct SessionHandle *data, long milli)
2530 struct Curl_multi *multi = data->multi;
2531 struct timeval *nowp = &data->state.expiretime;
2534 /* this is only interesting while there is still an associated multi struct
2540 /* No timeout, clear the time data. */
2541 if(nowp->tv_sec || nowp->tv_usec) {
2542 /* Since this is an cleared time, we must remove the previous entry from
2544 struct curl_llist *list = data->state.timeoutlist;
2546 rc = Curl_splayremovebyaddr(multi->timetree,
2547 &data->state.timenode,
2550 infof(data, "Internal error clearing splay node = %d\n", rc);
2552 /* flush the timeout list too */
2553 while(list->size > 0)
2554 Curl_llist_remove(list, list->tail, NULL);
2557 infof(data, "Expire cleared\n");
2567 set.tv_sec += milli/1000;
2568 set.tv_usec += (milli%1000)*1000;
2570 if(set.tv_usec >= 1000000) {
2572 set.tv_usec -= 1000000;
2575 if(nowp->tv_sec || nowp->tv_usec) {
2576 /* This means that the struct is added as a node in the splay tree.
2577 Compare if the new time is earlier, and only remove-old/add-new if it
2579 long diff = curlx_tvdiff(set, *nowp);
2581 /* the new expire time was later so just add it to the queue
2583 multi_addtimeout(data->state.timeoutlist, &set);
2587 /* the new time is newer than the presently set one, so add the current
2588 to the queue and update the head */
2589 multi_addtimeout(data->state.timeoutlist, nowp);
2591 /* Since this is an updated time, we must remove the previous entry from
2592 the splay tree first and then re-add the new value */
2593 rc = Curl_splayremovebyaddr(multi->timetree,
2594 &data->state.timenode,
2597 infof(data, "Internal error removing splay node = %d\n", rc);
2601 data->state.timenode.payload = data;
2602 multi->timetree = Curl_splayinsert(*nowp,
2604 &data->state.timenode);
2607 Curl_splayprint(multi->timetree, 0, TRUE);
2611 CURLMcode curl_multi_assign(CURLM *multi_handle,
2612 curl_socket_t s, void *hashp)
2614 struct Curl_sh_entry *there = NULL;
2615 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2617 if(s != CURL_SOCKET_BAD)
2618 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2621 return CURLM_BAD_SOCKET;
2623 there->socketp = hashp;
2628 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
2630 return multi ? multi->max_host_connections : 0;
2633 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
2635 return multi ? multi->max_total_connections : 0;
2638 size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
2640 return multi ? multi->max_pipeline_length : 0;
2643 curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
2645 return multi ? multi->content_length_penalty_size : 0;
2648 curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
2650 return multi ? multi->chunk_length_penalty_size : 0;
2653 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
2655 return multi->pipelining_site_bl;
2658 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
2660 return multi->pipelining_server_bl;
2663 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
2665 struct SessionHandle *data;
2669 if(data->mstate == CURLM_STATE_CONNECT_PEND) {
2670 multistate(data, CURLM_STATE_CONNECT);
2671 /* Make sure that the handle will be processed soonish. */
2672 Curl_expire(data, 1);
2674 data = data->next; /* operate on next handle */
2679 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2681 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2682 struct SessionHandle *data;
2684 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2685 multi->num_easy, multi->num_alive);
2686 for(data=multi->easyp; data; data = data->next) {
2687 if(data->mstate < CURLM_STATE_COMPLETED) {
2688 /* only display handles that are not completed */
2689 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2691 statename[data->mstate], data->numsocks);
2692 for(i=0; i < data->numsocks; i++) {
2693 curl_socket_t s = data->sockets[i];
2694 struct Curl_sh_entry *entry =
2695 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2697 fprintf(stderr, "%d ", (int)s);
2699 fprintf(stderr, "INTERNAL CONFUSION\n");
2702 fprintf(stderr, "[%s %s] ",
2703 entry->action&CURL_POLL_IN?"RECVING":"",
2704 entry->action&CURL_POLL_OUT?"SENDING":"");
2707 fprintf(stderr, "\n");