1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, 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 ***************************************************************************/
25 #include <curl/curl.h>
39 #include "speedcheck.h"
40 #include "conncache.h"
43 #define _MPRINTF_REPLACE /* use our functions only */
44 #include <curl/mprintf.h>
46 #include "curl_memory.h"
47 /* The last #include file should be: */
51 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
52 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
53 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
55 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
56 #define CURL_SOCKET_HASH_TABLE_SIZE 911
60 /* the 'CURLMsg' is the part that is visible to the external user */
61 struct CURLMsg extmsg;
64 /* NOTE: if you add a state here, add the name to the statename[] array as
68 CURLM_STATE_INIT, /* 0 - start in this state */
69 CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */
70 CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
71 CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
72 CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
73 CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
75 CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */
76 CURLM_STATE_DO, /* 7 - start send off the request (part 1) */
77 CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */
78 CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */
79 CURLM_STATE_DO_DONE, /* 10 - done sending off request */
80 CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
81 CURLM_STATE_PERFORM, /* 12 - transfer data */
82 CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
83 CURLM_STATE_DONE, /* 14 - post data transfer operation */
84 CURLM_STATE_COMPLETED, /* 15 - operation complete */
85 CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
86 CURLM_STATE_LAST /* 17 - not a true state, never use this */
89 /* we support N sockets per easy handle. Set the corresponding bit to what
90 action we should wait for */
91 #define MAX_SOCKSPEREASYHANDLE 5
92 #define GETSOCK_READABLE (0x00ff)
93 #define GETSOCK_WRITABLE (0xff00)
95 struct Curl_one_easy {
96 /* first, two fields for the linked list of these */
97 struct Curl_one_easy *next;
98 struct Curl_one_easy *prev;
100 struct SessionHandle *easy_handle; /* the easy handle for this unit */
101 struct connectdata *easy_conn; /* the "unit's" connection */
103 CURLMstate state; /* the handle's state */
104 CURLcode result; /* previous result */
106 struct Curl_message msg; /* A single posted message. */
108 /* Array with the plain socket numbers this handle takes care of, in no
109 particular order. Note that all sockets are added to the sockhash, where
110 the state etc are also kept. This array is mostly used to detect when a
111 socket is to be removed from the hash. See singlesocket(). */
112 curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
116 #define CURL_MULTI_HANDLE 0x000bab1e
118 #define GOOD_MULTI_HANDLE(x) \
119 ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
120 #define GOOD_EASY_HANDLE(x) \
121 ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
123 /* This is the struct known as CURLM on the outside */
125 /* First a simple identifier to easier detect if a user mix up
126 this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
129 /* We have a doubly-linked circular list with easy handles */
130 struct Curl_one_easy easy;
132 int num_easy; /* amount of entries in the linked list above. */
133 int num_alive; /* amount of easy handles that are added but have not yet
134 reached COMPLETE state */
136 struct curl_llist *msglist; /* a list of messages from completed transfers */
138 /* callback function and user data pointer for the *socket() API */
139 curl_socket_callback socket_cb;
143 struct curl_hash *hostcache;
145 /* timetree points to the splay-tree of time nodes to figure out expire
146 times of all currently set timers */
147 struct Curl_tree *timetree;
149 /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
150 the pluralis form, there can be more than one easy handle waiting on the
151 same actual socket) */
152 struct curl_hash *sockhash;
154 /* Whether pipelining is enabled for this multi handle */
155 bool pipelining_enabled;
157 /* Shared connection cache (bundles)*/
158 struct conncache *conn_cache;
160 /* This handle will be used for closing the cached connections in
161 curl_multi_cleanup() */
162 struct SessionHandle *closure_handle;
164 long maxconnects; /* if >0, a fixed limit of the maximum number of entries
165 we're allowed to grow the connection cache to */
167 /* timer callback and user data pointer for the *socket() API */
168 curl_multi_timer_callback timer_cb;
170 struct timeval timer_lastcall; /* the fixed time for the timeout for the
174 static void singlesocket(struct Curl_multi *multi,
175 struct Curl_one_easy *easy);
176 static int update_timer(struct Curl_multi *multi);
178 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
179 struct connectdata *conn);
180 static int checkPendPipeline(struct connectdata *conn);
181 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
182 struct connectdata *conn);
183 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
184 struct connectdata *conn);
185 static bool isHandleAtHead(struct SessionHandle *handle,
186 struct curl_llist *pipeline);
187 static CURLMcode add_next_timeout(struct timeval now,
188 struct Curl_multi *multi,
189 struct SessionHandle *d);
192 static const char * const statename[]={
213 static void multi_freetimeout(void *a, void *b);
215 /* always use this function to change state, to make debugging easier */
216 static void multistate(struct Curl_one_easy *easy, CURLMstate state)
219 long connection_id = -5000;
221 CURLMstate oldstate = easy->state;
223 if(oldstate == state)
224 /* don't bother when the new state is the same as the old state */
230 if(easy->easy_conn) {
231 if(easy->state > CURLM_STATE_CONNECT &&
232 easy->state < CURLM_STATE_COMPLETED)
233 connection_id = easy->easy_conn->connection_id;
235 infof(easy->easy_handle,
236 "STATE: %s => %s handle %p; (connection #%ld) \n",
237 statename[oldstate], statename[easy->state],
238 (char *)easy, connection_id);
241 if(state == CURLM_STATE_COMPLETED)
242 /* changing to COMPLETED means there's one less easy handle 'alive' */
243 easy->easy_handle->multi->num_alive--;
247 * We add one of these structs to the sockhash for a particular socket
250 struct Curl_sh_entry {
251 struct SessionHandle *easy;
253 int action; /* what action READ/WRITE this socket waits for */
254 curl_socket_t socket; /* mainly to ease debugging */
255 void *socketp; /* settable by users with curl_multi_assign() */
257 /* bits for 'action' having no bits means this socket is not expecting any
262 /* make sure this socket is present in the hash for this handle */
263 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
265 struct SessionHandle *data)
267 struct Curl_sh_entry *there =
268 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
269 struct Curl_sh_entry *check;
272 /* it is present, return fine */
275 /* not present, add it */
276 check = calloc(1, sizeof(struct Curl_sh_entry));
278 return NULL; /* major failure */
282 /* make/add new hash entry */
283 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
285 return NULL; /* major failure */
288 return check; /* things are good in sockhash land */
292 /* delete the given socket + handle from the hash */
293 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
295 struct Curl_sh_entry *there =
296 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
299 /* this socket is in the hash */
300 /* We remove the hash entry. (This'll end up in a call to
302 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
307 * free a sockhash entry
309 static void sh_freeentry(void *freethis)
311 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
317 static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
319 (void) k1_len; (void) k2_len;
321 return (*((int* ) k1)) == (*((int* ) k2));
324 static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
326 int fd = * ((int* ) key);
329 return (fd % (int)slots_num);
333 * sh_init() creates a new socket hash and returns the handle for it.
335 * Quote from README.multi_socket:
337 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
338 * is somewhat of a bottle neck. Its current implementation may be a bit too
339 * limiting. It simply has a fixed-size array, and on each entry in the array
340 * it has a linked list with entries. So the hash only checks which list to
341 * scan through. The code I had used so for used a list with merely 7 slots
342 * (as that is what the DNS hash uses) but with 7000 connections that would
343 * make an average of 1000 nodes in each list to run through. I upped that to
344 * 97 slots (I believe a prime is suitable) and noticed a significant speed
345 * increase. I need to reconsider the hash implementation or use a rather
346 * large default value like this. At 9000 connections I was still below 10us
350 static struct curl_hash *sh_init(void)
352 return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
359 * Called when a transfer is completed. Adds the given msg pointer to
360 * the list kept in the multi handle.
362 static CURLMcode multi_addmsg(struct Curl_multi *multi,
363 struct Curl_message *msg)
365 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
366 return CURLM_OUT_OF_MEMORY;
374 * Callback used by the llist system when a single list entry is destroyed.
376 static void multi_freeamsg(void *a, void *b)
382 CURLM *curl_multi_init(void)
384 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
389 multi->type = CURL_MULTI_HANDLE;
391 multi->hostcache = Curl_mk_dnscache();
392 if(!multi->hostcache)
395 multi->sockhash = sh_init();
399 multi->conn_cache = Curl_conncache_init(CONNCACHE_MULTI);
400 if(!multi->conn_cache)
403 multi->msglist = Curl_llist_alloc(multi_freeamsg);
407 /* Let's make the doubly-linked list a circular list. This makes
408 the linked list code simpler and allows inserting at the end
409 with less work (we didn't keep a tail pointer before). */
410 multi->easy.next = &multi->easy;
411 multi->easy.prev = &multi->easy;
413 return (CURLM *) multi;
417 Curl_hash_destroy(multi->sockhash);
418 multi->sockhash = NULL;
419 Curl_hash_destroy(multi->hostcache);
420 multi->hostcache = NULL;
421 Curl_conncache_destroy(multi->conn_cache);
422 multi->conn_cache = NULL;
428 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
431 struct curl_llist *timeoutlist;
432 struct Curl_one_easy *easy;
433 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
434 struct SessionHandle *data = (struct SessionHandle *)easy_handle;
435 struct SessionHandle *new_closure = NULL;
437 /* First, make some basic checks that the CURLM handle is a good handle */
438 if(!GOOD_MULTI_HANDLE(multi))
439 return CURLM_BAD_HANDLE;
441 /* Verify that we got a somewhat good easy handle too */
442 if(!GOOD_EASY_HANDLE(easy_handle))
443 return CURLM_BAD_EASY_HANDLE;
445 /* Prevent users from adding same easy handle more than
446 once and prevent adding to more than one multi stack */
448 /* possibly we should create a new unique error code for this condition */
449 return CURLM_BAD_EASY_HANDLE;
451 /* Allocate and initialize timeout list for easy handle */
452 timeoutlist = Curl_llist_alloc(multi_freetimeout);
454 return CURLM_OUT_OF_MEMORY;
456 /* Allocate new node for the doubly-linked circular list of
457 Curl_one_easy structs that holds pointers to easy handles */
458 easy = calloc(1, sizeof(struct Curl_one_easy));
460 Curl_llist_destroy(timeoutlist, NULL);
461 return CURLM_OUT_OF_MEMORY;
464 /* In case multi handle has no closure_handle yet, allocate
465 a new easy handle to use when closing cached connections */
466 if(!multi->closure_handle) {
467 new_closure = (struct SessionHandle *)curl_easy_init();
470 Curl_llist_destroy(timeoutlist, NULL);
471 return CURLM_OUT_OF_MEMORY;
476 ** No failure allowed in this function beyond this point. And
477 ** no modification of easy nor multi handle allowed before this
478 ** except for potential multi's connection cache growing which
479 ** won't be undone in this function no matter what.
482 /* In case a new closure handle has been initialized above, it
483 is associated now with the multi handle which lacked one. */
485 multi->closure_handle = new_closure;
486 Curl_easy_addmulti(multi->closure_handle, multi_handle);
487 multi->closure_handle->state.conn_cache = multi->conn_cache;
490 /* Make easy handle use timeout list initialized above */
491 data->state.timeoutlist = timeoutlist;
494 /* set the easy handle */
495 easy->easy_handle = data;
496 multistate(easy, CURLM_STATE_INIT);
498 /* set the back pointer to one_easy to assist in removal */
499 easy->easy_handle->multi_pos = easy;
501 /* for multi interface connections, we share DNS cache automatically if the
502 easy handle's one is currently private. */
503 if(easy->easy_handle->dns.hostcache &&
504 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
505 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
506 easy->easy_handle->dns.hostcache = NULL;
507 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
510 if(!easy->easy_handle->dns.hostcache ||
511 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
512 easy->easy_handle->dns.hostcache = multi->hostcache;
513 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
516 /* On a multi stack the connection cache, owned by the multi handle,
517 is shared between all easy handles within the multi handle.
518 Therefore we free the private connection cache if there is one */
519 if(easy->easy_handle->state.conn_cache &&
520 easy->easy_handle->state.conn_cache->type == CONNCACHE_PRIVATE) {
521 Curl_conncache_destroy(easy->easy_handle->state.conn_cache);
524 /* Point now to this multi's connection cache */
525 easy->easy_handle->state.conn_cache = multi->conn_cache;
527 /* This adds the new entry at the 'end' of the doubly-linked circular
528 list of Curl_one_easy structs to try and maintain a FIFO queue so
529 the pipelined requests are in order. */
531 /* We add this new entry last in the list. We make our 'next' point to the
532 'first' struct and our 'prev' point to the previous 'prev' */
533 easy->next = &multi->easy;
534 easy->prev = multi->easy.prev;
536 /* make 'easy' the last node in the chain */
537 multi->easy.prev = easy;
539 /* if there was a prev node, make sure its 'next' pointer links to
541 easy->prev->next = easy;
543 /* make the SessionHandle refer back to this multi handle */
544 Curl_easy_addmulti(easy_handle, multi_handle);
546 /* make the SessionHandle struct refer back to this struct */
547 easy->easy_handle->set.one_easy = easy;
549 /* Set the timeout for this handle to expire really soon so that it will
550 be taken care of even when this handle is added in the midst of operation
551 when only the curl_multi_socket() API is used. During that flow, only
552 sockets that time-out or have actions will be dealt with. Since this
553 handle has no action yet, we make sure it times out to get things to
555 Curl_expire(easy->easy_handle, 1);
557 /* increase the node-counter */
560 /* increase the alive-counter */
563 /* A somewhat crude work-around for a little glitch in update_timer() that
564 happens if the lastcall time is set to the same time when the handle is
565 removed as when the next handle is added, as then the check in
566 update_timer() that prevents calling the application multiple times with
567 the same timer infor will not trigger and then the new handle's timeout
568 will not be notified to the app.
570 The work-around is thus simply to clear the 'lastcall' variable to force
571 update_timer() to always trigger a callback to the app when a new easy
573 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
580 /* Debug-function, used like this:
582 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
584 * Enable the hash print function first by editing hash.c
586 static void debug_print_sock_hash(void *p)
588 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
590 fprintf(stderr, " [easy %p/magic %x/socket %d]",
591 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
595 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
598 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
599 struct Curl_one_easy *easy;
600 struct SessionHandle *data = curl_handle;
602 /* First, make some basic checks that the CURLM handle is a good handle */
603 if(!GOOD_MULTI_HANDLE(multi))
604 return CURLM_BAD_HANDLE;
606 /* Verify that we got a somewhat good easy handle too */
607 if(!GOOD_EASY_HANDLE(curl_handle))
608 return CURLM_BAD_EASY_HANDLE;
610 /* pick-up from the 'curl_handle' the kept position in the list */
611 easy = data->multi_pos;
614 bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
615 bool easy_owns_conn = (easy->easy_conn &&
616 (easy->easy_conn->data == easy->easy_handle)) ?
619 /* If the 'state' is not INIT or COMPLETED, we might need to do something
620 nice to put the easy_handle in a good known state when this returns. */
622 /* this handle is "alive" so we need to count down the total number of
623 alive connections when this is removed */
626 if(easy->easy_conn &&
627 (easy->easy_conn->send_pipe->size +
628 easy->easy_conn->recv_pipe->size > 1) &&
629 easy->state > CURLM_STATE_WAITDO &&
630 easy->state < CURLM_STATE_COMPLETED) {
631 /* If the handle is in a pipeline and has started sending off its
632 request but not received its response yet, we need to close
634 easy->easy_conn->bits.close = TRUE;
635 /* Set connection owner so that Curl_done() closes it.
636 We can sefely do this here since connection is killed. */
637 easy->easy_conn->data = easy->easy_handle;
640 /* The timer must be shut down before easy->multi is set to NULL,
641 else the timenode will remain in the splay tree after
642 curl_easy_cleanup is called. */
643 Curl_expire(easy->easy_handle, 0);
645 /* destroy the timeout list that is held in the easy handle */
646 if(data->state.timeoutlist) {
647 Curl_llist_destroy(data->state.timeoutlist, NULL);
648 data->state.timeoutlist = NULL;
651 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
652 if(multi->num_easy == 1) {
653 Curl_hostcache_destroy(easy->easy_handle);
654 multi->hostcache = NULL;
656 /* clear out the usage of the shared DNS cache */
657 easy->easy_handle->dns.hostcache = NULL;
658 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
661 if(easy->easy_conn) {
663 /* we must call Curl_done() here (if we still "own it") so that we don't
664 leave a half-baked one around */
667 /* Curl_done() clears the conn->data field to lose the association
668 between the easy handle and the connection
670 Note that this ignores the return code simply because there's
671 nothing really useful to do with it anyway! */
672 (void)Curl_done(&easy->easy_conn, easy->result, premature);
675 /* Clear connection pipelines, if Curl_done above was not called */
676 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
679 if(easy->easy_handle->state.conn_cache->type == CONNCACHE_MULTI) {
680 /* if this was using the shared connection cache we clear the pointer
681 to that since we're not part of that handle anymore */
682 easy->easy_handle->state.conn_cache = NULL;
683 easy->easy_handle->state.lastconnect = NULL;
686 /* change state without using multistate(), only to make singlesocket() do
688 easy->state = CURLM_STATE_COMPLETED;
689 singlesocket(multi, easy); /* to let the application know what sockets
690 that vanish with this handle */
692 /* Remove the association between the connection and the handle */
693 if(easy->easy_conn) {
694 easy->easy_conn->data = NULL;
695 easy->easy_conn = NULL;
698 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
699 to this multi handle */
702 /* make sure there's no pending message in the queue sent from this easy
704 struct curl_llist_element *e;
706 for(e = multi->msglist->head; e; e = e->next) {
707 struct Curl_message *msg = e->ptr;
709 if(msg->extmsg.easy_handle == easy->easy_handle) {
710 Curl_llist_remove(multi->msglist, e, NULL);
711 /* there can only be one from this specific handle */
717 /* make the previous node point to our next */
719 easy->prev->next = easy->next;
720 /* make our next point to our previous node */
722 easy->next->prev = easy->prev;
724 easy->easy_handle->set.one_easy = NULL; /* detached */
726 /* Null the position in the controlling structure */
727 easy->easy_handle->multi_pos = NULL;
730 We do not touch the easy handle here! */
733 multi->num_easy--; /* one less to care about now */
739 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
742 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
744 return multi->pipelining_enabled;
747 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
749 struct Curl_one_easy *one_easy = data->set.one_easy;
752 one_easy->easy_conn = NULL;
755 static int waitconnect_getsock(struct connectdata *conn,
760 return GETSOCK_BLANK;
762 sock[0] = conn->sock[FIRSTSOCKET];
764 /* when we've sent a CONNECT to a proxy, we should rather wait for the
765 socket to become readable to be able to get the response headers */
766 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
767 return GETSOCK_READSOCK(0);
769 return GETSOCK_WRITESOCK(0);
772 static int domore_getsock(struct connectdata *conn,
773 curl_socket_t *socks,
776 if(conn && conn->handler->domore_getsock)
777 return conn->handler->domore_getsock(conn, socks, numsocks);
778 return GETSOCK_BLANK;
781 /* returns bitmapped flags for this handle and its sockets */
782 static int multi_getsock(struct Curl_one_easy *easy,
783 curl_socket_t *socks, /* points to numsocks number
787 /* If the pipe broke, or if there's no connection left for this easy handle,
788 then we MUST bail out now with no bitmask set. The no connection case can
789 happen when this is called from curl_multi_remove_handle() =>
790 singlesocket() => multi_getsock().
792 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
795 if(easy->state > CURLM_STATE_CONNECT &&
796 easy->state < CURLM_STATE_COMPLETED) {
797 /* Set up ownership correctly */
798 easy->easy_conn->data = easy->easy_handle;
801 switch(easy->state) {
803 #if 0 /* switch back on these cases to get the compiler to check for all enums
805 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
806 case CURLM_STATE_COMPLETED:
807 case CURLM_STATE_MSGSENT:
808 case CURLM_STATE_INIT:
809 case CURLM_STATE_CONNECT:
810 case CURLM_STATE_WAITDO:
811 case CURLM_STATE_DONE:
812 case CURLM_STATE_LAST:
813 /* this will get called with CURLM_STATE_COMPLETED when a handle is
818 case CURLM_STATE_WAITRESOLVE:
819 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
821 case CURLM_STATE_PROTOCONNECT:
822 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
825 case CURLM_STATE_DOING:
826 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
828 case CURLM_STATE_WAITPROXYCONNECT:
829 case CURLM_STATE_WAITCONNECT:
830 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
832 case CURLM_STATE_DO_MORE:
833 return domore_getsock(easy->easy_conn, socks, numsocks);
835 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
836 to waiting for the same as the *PERFORM
838 case CURLM_STATE_PERFORM:
839 case CURLM_STATE_WAITPERFORM:
840 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
845 CURLMcode curl_multi_fdset(CURLM *multi_handle,
846 fd_set *read_fd_set, fd_set *write_fd_set,
847 fd_set *exc_fd_set, int *max_fd)
849 /* Scan through all the easy handles to get the file descriptors set.
850 Some easy handles may not have connected to the remote host yet,
851 and then we must make sure that is done. */
852 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
853 struct Curl_one_easy *easy;
855 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
858 (void)exc_fd_set; /* not used */
860 if(!GOOD_MULTI_HANDLE(multi))
861 return CURLM_BAD_HANDLE;
863 easy=multi->easy.next;
864 while(easy != &multi->easy) {
865 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
867 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
868 curl_socket_t s = CURL_SOCKET_BAD;
870 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
871 FD_SET(sockbunch[i], read_fd_set);
874 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
875 FD_SET(sockbunch[i], write_fd_set);
878 if(s == CURL_SOCKET_BAD)
879 /* this socket is unused, break out of loop */
882 if((int)s > this_max_fd)
883 this_max_fd = (int)s;
887 easy = easy->next; /* check next handle */
890 *max_fd = this_max_fd;
895 CURLMcode curl_multi_wait(CURLM *multi_handle,
896 struct curl_waitfd extra_fds[],
897 unsigned int extra_nfds,
901 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
902 struct Curl_one_easy *easy;
903 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
906 unsigned int nfds = extra_nfds;
907 struct pollfd *ufds = NULL;
909 if(!GOOD_MULTI_HANDLE(multi))
910 return CURLM_BAD_HANDLE;
912 /* Count up how many fds we have from the multi handle */
913 easy=multi->easy.next;
914 while(easy != &multi->easy) {
915 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
917 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
918 curl_socket_t s = CURL_SOCKET_BAD;
920 if(bitmap & GETSOCK_READSOCK(i)) {
924 if(bitmap & GETSOCK_WRITESOCK(i)) {
928 if(s == CURL_SOCKET_BAD) {
933 easy = easy->next; /* check next handle */
937 ufds = malloc(nfds * sizeof(struct pollfd));
939 return CURLM_OUT_OF_MEMORY;
943 /* Add the curl handles to our pollfds first */
944 easy=multi->easy.next;
945 while(easy != &multi->easy) {
946 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
948 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
949 curl_socket_t s = CURL_SOCKET_BAD;
951 if(bitmap & GETSOCK_READSOCK(i)) {
952 ufds[nfds].fd = sockbunch[i];
953 ufds[nfds].events = POLLIN;
957 if(bitmap & GETSOCK_WRITESOCK(i)) {
958 ufds[nfds].fd = sockbunch[i];
959 ufds[nfds].events = POLLOUT;
963 if(s == CURL_SOCKET_BAD) {
968 easy = easy->next; /* check next handle */
971 /* Add external file descriptions from poll-like struct curl_waitfd */
972 for(i = 0; i < extra_nfds; i++) {
973 ufds[nfds].fd = extra_fds[i].fd;
974 ufds[nfds].events = 0;
975 if(extra_fds[i].events & CURL_WAIT_POLLIN)
976 ufds[nfds].events |= POLLIN;
977 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
978 ufds[nfds].events |= POLLPRI;
979 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
980 ufds[nfds].events |= POLLOUT;
986 i = Curl_poll(ufds, nfds, timeout_ms);
996 static CURLMcode multi_runsingle(struct Curl_multi *multi,
998 struct Curl_one_easy *easy)
1000 struct Curl_message *msg = NULL;
1003 bool protocol_connect = FALSE;
1006 CURLMcode result = CURLM_OK;
1007 struct SingleRequest *k;
1008 struct SessionHandle *data;
1011 if(!GOOD_EASY_HANDLE(easy->easy_handle))
1012 return CURLM_BAD_EASY_HANDLE;
1014 data = easy->easy_handle;
1017 /* this is a single-iteration do-while loop just to allow a
1018 break to skip to the end of it */
1019 bool disconnect_conn = FALSE;
1021 /* Handle the case when the pipe breaks, i.e., the connection
1022 we're using gets cleaned up and we're left with nothing. */
1023 if(data->state.pipe_broke) {
1024 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
1025 easy, data->state.path);
1027 if(easy->state < CURLM_STATE_COMPLETED) {
1028 /* Head back to the CONNECT state */
1029 multistate(easy, CURLM_STATE_CONNECT);
1030 result = CURLM_CALL_MULTI_PERFORM;
1031 easy->result = CURLE_OK;
1034 data->state.pipe_broke = FALSE;
1035 easy->easy_conn = NULL;
1039 if(!easy->easy_conn &&
1040 easy->state > CURLM_STATE_CONNECT &&
1041 easy->state < CURLM_STATE_DONE) {
1042 /* In all these states, the code will blindly access 'easy->easy_conn'
1043 so this is precaution that it isn't NULL. And it silences static
1045 failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
1046 return CURLM_INTERNAL_ERROR;
1049 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
1050 easy->state < CURLM_STATE_COMPLETED)
1051 /* Make sure we set the connection's current owner */
1052 easy->easy_conn->data = data;
1054 if(easy->easy_conn &&
1055 (easy->state >= CURLM_STATE_CONNECT) &&
1056 (easy->state < CURLM_STATE_COMPLETED)) {
1057 /* we need to wait for the connect state as only then is the start time
1058 stored, but we must not check already completed handles */
1060 timeout_ms = Curl_timeleft(data, &now,
1061 (easy->state <= CURLM_STATE_WAITDO)?
1064 if(timeout_ms < 0) {
1065 /* Handle timed out */
1066 if(easy->state == CURLM_STATE_WAITRESOLVE)
1067 failf(data, "Resolving timed out after %ld milliseconds",
1068 Curl_tvdiff(now, data->progress.t_startsingle));
1069 else if(easy->state == CURLM_STATE_WAITCONNECT)
1070 failf(data, "Connection timed out after %ld milliseconds",
1071 Curl_tvdiff(now, data->progress.t_startsingle));
1074 failf(data, "Operation timed out after %ld milliseconds with %"
1075 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1076 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1080 /* Force the connection closed because the server could continue to
1081 send us stuff at any time. (The disconnect_conn logic used below
1082 doesn't work at this point). */
1083 easy->easy_conn->bits.close = TRUE;
1084 easy->result = CURLE_OPERATION_TIMEDOUT;
1085 multistate(easy, CURLM_STATE_COMPLETED);
1090 switch(easy->state) {
1091 case CURLM_STATE_INIT:
1092 /* init this transfer. */
1093 easy->result=Curl_pretransfer(data);
1095 if(CURLE_OK == easy->result) {
1096 /* after init, go CONNECT */
1097 multistate(easy, CURLM_STATE_CONNECT);
1098 result = CURLM_CALL_MULTI_PERFORM;
1100 data->state.used_interface = Curl_if_multi;
1104 case CURLM_STATE_CONNECT:
1105 /* Connect. We get a connection identifier filled in. */
1106 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1107 easy->result = Curl_connect(data, &easy->easy_conn,
1108 &async, &protocol_connect);
1110 if(CURLE_OK == easy->result) {
1111 /* Add this handle to the send or pend pipeline */
1112 easy->result = addHandleToSendOrPendPipeline(data,
1114 if(CURLE_OK != easy->result)
1115 disconnect_conn = TRUE;
1118 /* We're now waiting for an asynchronous name lookup */
1119 multistate(easy, CURLM_STATE_WAITRESOLVE);
1121 /* after the connect has been sent off, go WAITCONNECT unless the
1122 protocol connect is already done and we can go directly to
1124 result = CURLM_CALL_MULTI_PERFORM;
1126 if(protocol_connect)
1127 multistate(easy, multi->pipelining_enabled?
1128 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1130 #ifndef CURL_DISABLE_HTTP
1131 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1132 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1135 multistate(easy, CURLM_STATE_WAITCONNECT);
1142 case CURLM_STATE_WAITRESOLVE:
1143 /* awaiting an asynch name resolve to complete */
1145 struct Curl_dns_entry *dns = NULL;
1147 /* check if we have the name resolved by now */
1148 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1150 /* Update sockets here, because the socket(s) may have been
1151 closed and the application thus needs to be told, even if it
1152 is likely that the same socket(s) will again be used further
1153 down. If the name has not yet been resolved, it is likely
1154 that new sockets have been opened in an attempt to contact
1155 another resolver. */
1156 singlesocket(multi, easy);
1159 /* Perform the next step in the connection phase, and then move on
1160 to the WAITCONNECT state */
1161 easy->result = Curl_async_resolved(easy->easy_conn,
1164 if(CURLE_OK != easy->result)
1165 /* if Curl_async_resolved() returns failure, the connection struct
1166 is already freed and gone */
1167 easy->easy_conn = NULL; /* no more connection */
1169 /* call again please so that we get the next socket setup */
1170 result = CURLM_CALL_MULTI_PERFORM;
1171 if(protocol_connect)
1172 multistate(easy, multi->pipelining_enabled?
1173 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1175 #ifndef CURL_DISABLE_HTTP
1176 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1177 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1180 multistate(easy, CURLM_STATE_WAITCONNECT);
1185 if(CURLE_OK != easy->result) {
1186 /* failure detected */
1187 disconnect_conn = TRUE;
1193 #ifndef CURL_DISABLE_HTTP
1194 case CURLM_STATE_WAITPROXYCONNECT:
1195 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1196 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1198 if(easy->easy_conn->bits.proxy_connect_closed) {
1199 /* reset the error buffer */
1200 if(data->set.errorbuffer)
1201 data->set.errorbuffer[0] = '\0';
1202 data->state.errorbuf = FALSE;
1204 easy->result = CURLE_OK;
1205 result = CURLM_CALL_MULTI_PERFORM;
1206 multistate(easy, CURLM_STATE_CONNECT);
1208 else if(CURLE_OK == easy->result) {
1209 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1210 multistate(easy, CURLM_STATE_WAITCONNECT);
1215 case CURLM_STATE_WAITCONNECT:
1216 /* awaiting a completion of an asynch connect */
1217 easy->result = Curl_is_connected(easy->easy_conn,
1223 /* if everything is still fine we do the protocol-specific connect
1225 easy->result = Curl_protocol_connect(easy->easy_conn,
1229 if(CURLE_OK != easy->result) {
1230 /* failure detected */
1231 /* Just break, the cleaning up is handled all in one place */
1232 disconnect_conn = TRUE;
1237 if(!protocol_connect) {
1238 /* We have a TCP connection, but 'protocol_connect' may be false
1239 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1240 connect is TRUE, we move on to STATE_DO.
1241 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1243 #ifndef CURL_DISABLE_HTTP
1244 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1245 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1248 multistate(easy, CURLM_STATE_PROTOCONNECT);
1252 /* after the connect has completed, go WAITDO or DO */
1253 multistate(easy, multi->pipelining_enabled?
1254 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1256 result = CURLM_CALL_MULTI_PERFORM;
1260 case CURLM_STATE_PROTOCONNECT:
1261 /* protocol-specific connect phase */
1262 easy->result = Curl_protocol_connecting(easy->easy_conn,
1264 if((easy->result == CURLE_OK) && protocol_connect) {
1265 /* after the connect has completed, go WAITDO or DO */
1266 multistate(easy, multi->pipelining_enabled?
1267 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1268 result = CURLM_CALL_MULTI_PERFORM;
1270 else if(easy->result) {
1271 /* failure detected */
1272 Curl_posttransfer(data);
1273 Curl_done(&easy->easy_conn, easy->result, TRUE);
1274 disconnect_conn = TRUE;
1278 case CURLM_STATE_WAITDO:
1279 /* Wait for our turn to DO when we're pipelining requests */
1281 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
1282 easy->easy_conn->connection_id,
1283 easy->easy_conn->send_pipe->size,
1284 easy->easy_conn->writechannel_inuse?1:0,
1285 isHandleAtHead(data,
1286 easy->easy_conn->send_pipe)?1:0);
1288 if(!easy->easy_conn->writechannel_inuse &&
1289 isHandleAtHead(data,
1290 easy->easy_conn->send_pipe)) {
1291 /* Grab the channel */
1292 easy->easy_conn->writechannel_inuse = TRUE;
1293 multistate(easy, CURLM_STATE_DO);
1294 result = CURLM_CALL_MULTI_PERFORM;
1298 case CURLM_STATE_DO:
1299 if(data->set.connect_only) {
1300 /* keep connection open for application to use the socket */
1301 easy->easy_conn->bits.close = FALSE;
1302 multistate(easy, CURLM_STATE_DONE);
1303 easy->result = CURLE_OK;
1304 result = CURLM_CALL_MULTI_PERFORM;
1307 /* Perform the protocol's DO action */
1308 easy->result = Curl_do(&easy->easy_conn,
1311 if(CURLE_OK == easy->result) {
1313 /* some steps needed for wildcard matching */
1314 if(data->set.wildcardmatch) {
1315 struct WildcardData *wc = &data->wildcard;
1316 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1317 /* skip some states if it is important */
1318 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1319 multistate(easy, CURLM_STATE_DONE);
1320 result = CURLM_CALL_MULTI_PERFORM;
1324 /* DO was not completed in one function call, we must continue
1326 multistate(easy, CURLM_STATE_DOING);
1330 /* after DO, go DO_DONE... or DO_MORE */
1331 else if(easy->easy_conn->bits.do_more) {
1332 /* we're supposed to do more, but we need to sit down, relax
1333 and wait a little while first */
1334 multistate(easy, CURLM_STATE_DO_MORE);
1338 /* we're done with the DO, now DO_DONE */
1339 multistate(easy, CURLM_STATE_DO_DONE);
1340 result = CURLM_CALL_MULTI_PERFORM;
1343 else if((CURLE_SEND_ERROR == easy->result) &&
1344 easy->easy_conn->bits.reuse) {
1346 * In this situation, a connection that we were trying to use
1347 * may have unexpectedly died. If possible, send the connection
1348 * back to the CONNECT phase so we can try again.
1350 char *newurl = NULL;
1351 followtype follow=FOLLOW_NONE;
1355 drc = Curl_retry_request(easy->easy_conn, &newurl);
1357 /* a failure here pretty much implies an out of memory */
1359 disconnect_conn = TRUE;
1362 retry = (newurl)?TRUE:FALSE;
1364 Curl_posttransfer(data);
1365 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1367 /* When set to retry the connection, we must to go back to
1368 * the CONNECT state */
1370 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1371 follow = FOLLOW_RETRY;
1372 drc = Curl_follow(data, newurl, follow);
1373 if(drc == CURLE_OK) {
1374 multistate(easy, CURLM_STATE_CONNECT);
1375 result = CURLM_CALL_MULTI_PERFORM;
1376 easy->result = CURLE_OK;
1385 /* done didn't return OK or SEND_ERROR */
1391 /* Have error handler disconnect conn if we can't retry */
1392 disconnect_conn = TRUE;
1396 /* failure detected */
1397 Curl_posttransfer(data);
1398 Curl_done(&easy->easy_conn, easy->result, FALSE);
1399 disconnect_conn = TRUE;
1404 case CURLM_STATE_DOING:
1405 /* we continue DOING until the DO phase is complete */
1406 easy->result = Curl_protocol_doing(easy->easy_conn,
1408 if(CURLE_OK == easy->result) {
1410 /* after DO, go DO_DONE or DO_MORE */
1411 multistate(easy, easy->easy_conn->bits.do_more?
1412 CURLM_STATE_DO_MORE:
1413 CURLM_STATE_DO_DONE);
1414 result = CURLM_CALL_MULTI_PERFORM;
1415 } /* dophase_done */
1418 /* failure detected */
1419 Curl_posttransfer(data);
1420 Curl_done(&easy->easy_conn, easy->result, FALSE);
1421 disconnect_conn = TRUE;
1425 case CURLM_STATE_DO_MORE:
1427 * When we are connected, DO MORE and then go DO_DONE
1429 easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1431 /* No need to remove this handle from the send pipeline here since that
1432 is done in Curl_done() */
1433 if(CURLE_OK == easy->result) {
1435 multistate(easy, CURLM_STATE_DO_DONE);
1436 result = CURLM_CALL_MULTI_PERFORM;
1439 /* stay in DO_MORE */
1443 /* failure detected */
1444 Curl_posttransfer(data);
1445 Curl_done(&easy->easy_conn, easy->result, FALSE);
1446 disconnect_conn = TRUE;
1450 case CURLM_STATE_DO_DONE:
1451 /* Move ourselves from the send to recv pipeline */
1452 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1453 /* Check if we can move pending requests to send pipe */
1454 checkPendPipeline(easy->easy_conn);
1455 multistate(easy, CURLM_STATE_WAITPERFORM);
1456 result = CURLM_CALL_MULTI_PERFORM;
1459 case CURLM_STATE_WAITPERFORM:
1460 /* Wait for our turn to PERFORM */
1461 if(!easy->easy_conn->readchannel_inuse &&
1462 isHandleAtHead(data,
1463 easy->easy_conn->recv_pipe)) {
1464 /* Grab the channel */
1465 easy->easy_conn->readchannel_inuse = TRUE;
1466 multistate(easy, CURLM_STATE_PERFORM);
1467 result = CURLM_CALL_MULTI_PERFORM;
1471 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
1472 easy->easy_conn->connection_id,
1473 easy->easy_conn->recv_pipe->size,
1474 easy->easy_conn->readchannel_inuse?1:0,
1475 isHandleAtHead(data,
1476 easy->easy_conn->recv_pipe)?1:0);
1481 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1482 /* if both rates are within spec, resume transfer */
1483 if(Curl_pgrsUpdate(easy->easy_conn))
1484 easy->result = CURLE_ABORTED_BY_CALLBACK;
1486 easy->result = Curl_speedcheck(data, now);
1488 if(( (data->set.max_send_speed == 0) ||
1489 (data->progress.ulspeed < data->set.max_send_speed )) &&
1490 ( (data->set.max_recv_speed == 0) ||
1491 (data->progress.dlspeed < data->set.max_recv_speed)))
1492 multistate(easy, CURLM_STATE_PERFORM);
1495 case CURLM_STATE_PERFORM:
1497 char *newurl = NULL;
1500 /* check if over send speed */
1501 if((data->set.max_send_speed > 0) &&
1502 (data->progress.ulspeed > data->set.max_send_speed)) {
1505 multistate(easy, CURLM_STATE_TOOFAST);
1507 /* calculate upload rate-limitation timeout. */
1508 buffersize = (int)(data->set.buffer_size ?
1509 data->set.buffer_size : BUFSIZE);
1510 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1511 data->progress.ulspeed, buffersize);
1512 Curl_expire(data, timeout_ms);
1516 /* check if over recv speed */
1517 if((data->set.max_recv_speed > 0) &&
1518 (data->progress.dlspeed > data->set.max_recv_speed)) {
1521 multistate(easy, CURLM_STATE_TOOFAST);
1523 /* Calculate download rate-limitation timeout. */
1524 buffersize = (int)(data->set.buffer_size ?
1525 data->set.buffer_size : BUFSIZE);
1526 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1527 data->progress.dlspeed, buffersize);
1528 Curl_expire(data, timeout_ms);
1532 /* read/write data if it is ready to do so */
1533 easy->result = Curl_readwrite(easy->easy_conn, &done);
1537 if(!(k->keepon & KEEP_RECV)) {
1538 /* We're done receiving */
1539 easy->easy_conn->readchannel_inuse = FALSE;
1542 if(!(k->keepon & KEEP_SEND)) {
1543 /* We're done sending */
1544 easy->easy_conn->writechannel_inuse = FALSE;
1547 if(done || (easy->result == CURLE_RECV_ERROR)) {
1548 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1549 * condition and the server closed the re-used connection exactly when
1550 * we wanted to use it, so figure out if that is indeed the case.
1552 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1554 retry = (newurl)?TRUE:FALSE;
1557 /* if we are to retry, set the result to OK */
1558 easy->result = CURLE_OK;
1563 * The transfer phase returned error, we mark the connection to get
1564 * closed to prevent being re-used. This is because we can't possibly
1565 * know if the connection is in a good shape or not now. Unless it is
1566 * a protocol which uses two "channels" like FTP, as then the error
1567 * happened in the data connection.
1570 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1571 easy->easy_conn->bits.close = TRUE;
1573 Curl_posttransfer(data);
1574 Curl_done(&easy->easy_conn, easy->result, FALSE);
1577 followtype follow=FOLLOW_NONE;
1579 /* call this even if the readwrite function returned error */
1580 Curl_posttransfer(data);
1582 /* we're no longer receiving */
1583 moveHandleFromRecvToDonePipeline(data,
1586 /* expire the new receiving pipeline head */
1587 if(easy->easy_conn->recv_pipe->head)
1588 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1590 /* Check if we can move pending requests to send pipe */
1591 checkPendPipeline(easy->easy_conn);
1593 /* When we follow redirects or is set to retry the connection, we must
1594 to go back to the CONNECT state */
1595 if(data->req.newurl || retry) {
1597 /* if the URL is a follow-location and not just a retried request
1598 then figure out the URL here */
1599 newurl = data->req.newurl;
1600 data->req.newurl = NULL;
1601 follow = FOLLOW_REDIR;
1604 follow = FOLLOW_RETRY;
1605 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1606 if(easy->result == CURLE_OK)
1607 easy->result = Curl_follow(data, newurl, follow);
1608 if(CURLE_OK == easy->result) {
1609 multistate(easy, CURLM_STATE_CONNECT);
1610 result = CURLM_CALL_MULTI_PERFORM;
1611 newurl = NULL; /* handed over the memory ownership to
1612 Curl_follow(), make sure we don't free() it
1617 /* after the transfer is done, go DONE */
1619 /* but first check to see if we got a location info even though we're
1620 not following redirects */
1621 if(data->req.location) {
1624 newurl = data->req.location;
1625 data->req.location = NULL;
1626 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1627 if(CURLE_OK == easy->result)
1628 newurl = NULL; /* allocation was handed over Curl_follow() */
1630 disconnect_conn = TRUE;
1633 multistate(easy, CURLM_STATE_DONE);
1634 result = CURLM_CALL_MULTI_PERFORM;
1643 case CURLM_STATE_DONE:
1645 if(easy->easy_conn) {
1646 /* Remove ourselves from the receive and done pipelines. Handle
1647 should be on one of these lists, depending upon how we got here. */
1648 Curl_removeHandleFromPipeline(data,
1649 easy->easy_conn->recv_pipe);
1650 Curl_removeHandleFromPipeline(data,
1651 easy->easy_conn->done_pipe);
1652 /* Check if we can move pending requests to send pipe */
1653 checkPendPipeline(easy->easy_conn);
1655 if(easy->easy_conn->bits.stream_was_rewound) {
1656 /* This request read past its response boundary so we quickly let
1657 the other requests consume those bytes since there is no
1658 guarantee that the socket will become active again */
1659 result = CURLM_CALL_MULTI_PERFORM;
1662 /* post-transfer command */
1663 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1665 * If there are other handles on the pipeline, Curl_done won't set
1666 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1667 * access free'd data, if the connection is free'd and the handle
1668 * removed before we perform the processing in CURLM_STATE_COMPLETED
1671 easy->easy_conn = NULL;
1674 if(data->set.wildcardmatch) {
1675 if(data->wildcard.state != CURLWC_DONE) {
1676 /* if a wildcard is set and we are not ending -> lets start again
1677 with CURLM_STATE_INIT */
1678 result = CURLM_CALL_MULTI_PERFORM;
1679 multistate(easy, CURLM_STATE_INIT);
1684 /* after we have DONE what we're supposed to do, go COMPLETED, and
1685 it doesn't matter what the Curl_done() returned! */
1686 multistate(easy, CURLM_STATE_COMPLETED);
1690 case CURLM_STATE_COMPLETED:
1691 /* this is a completed transfer, it is likely to still be connected */
1693 /* This node should be delinked from the list now and we should post
1694 an information message that we are complete. */
1696 /* Important: reset the conn pointer so that we don't point to memory
1697 that could be freed anytime */
1698 easy->easy_conn = NULL;
1700 Curl_expire(data, 0); /* stop all timers */
1703 case CURLM_STATE_MSGSENT:
1704 return CURLM_OK; /* do nothing */
1707 return CURLM_INTERNAL_ERROR;
1710 if(easy->state < CURLM_STATE_COMPLETED) {
1711 if(CURLE_OK != easy->result) {
1713 * If an error was returned, and we aren't in completed state now,
1714 * then we go to completed and consider this transfer aborted.
1717 /* NOTE: no attempt to disconnect connections must be made
1718 in the case blocks above - cleanup happens only here */
1720 data->state.pipe_broke = FALSE;
1722 if(easy->easy_conn) {
1723 /* if this has a connection, unsubscribe from the pipelines */
1724 easy->easy_conn->writechannel_inuse = FALSE;
1725 easy->easy_conn->readchannel_inuse = FALSE;
1726 Curl_removeHandleFromPipeline(data,
1727 easy->easy_conn->send_pipe);
1728 Curl_removeHandleFromPipeline(data,
1729 easy->easy_conn->recv_pipe);
1730 Curl_removeHandleFromPipeline(data,
1731 easy->easy_conn->done_pipe);
1732 /* Check if we can move pending requests to send pipe */
1733 checkPendPipeline(easy->easy_conn);
1735 if(disconnect_conn) {
1736 /* disconnect properly */
1737 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1739 /* This is where we make sure that the easy_conn pointer is reset.
1740 We don't have to do this in every case block above where a
1741 failure is detected */
1742 easy->easy_conn = NULL;
1745 else if(easy->state == CURLM_STATE_CONNECT) {
1746 /* Curl_connect() failed */
1747 (void)Curl_posttransfer(data);
1750 multistate(easy, CURLM_STATE_COMPLETED);
1752 /* if there's still a connection to use, call the progress function */
1753 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1754 /* aborted due to progress callback return code must close the
1756 easy->easy_conn->bits.close = TRUE;
1758 /* if not yet in DONE state, go there, otherwise COMPLETED */
1759 multistate(easy, (easy->state < CURLM_STATE_DONE)?
1760 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1761 result = CURLM_CALL_MULTI_PERFORM;
1764 } WHILE_FALSE; /* just to break out from! */
1766 if(CURLM_STATE_COMPLETED == easy->state) {
1767 /* now fill in the Curl_message with this info */
1770 msg->extmsg.msg = CURLMSG_DONE;
1771 msg->extmsg.easy_handle = data;
1772 msg->extmsg.data.result = easy->result;
1774 result = multi_addmsg(multi, msg);
1776 multistate(easy, CURLM_STATE_MSGSENT);
1783 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1785 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1786 struct Curl_one_easy *easy;
1787 CURLMcode returncode=CURLM_OK;
1788 struct Curl_tree *t;
1789 struct timeval now = Curl_tvnow();
1791 if(!GOOD_MULTI_HANDLE(multi))
1792 return CURLM_BAD_HANDLE;
1794 easy=multi->easy.next;
1795 while(easy != &multi->easy) {
1797 struct WildcardData *wc = &easy->easy_handle->wildcard;
1799 if(easy->easy_handle->set.wildcardmatch) {
1801 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1803 return CURLM_OUT_OF_MEMORY;
1808 result = multi_runsingle(multi, now, easy);
1809 while(CURLM_CALL_MULTI_PERFORM == result);
1811 if(easy->easy_handle->set.wildcardmatch) {
1812 /* destruct wildcard structures if it is needed */
1813 if(wc->state == CURLWC_DONE || result)
1814 Curl_wildcard_dtor(wc);
1818 returncode = result;
1820 easy = easy->next; /* operate on next handle */
1824 * Simply remove all expired timers from the splay since handles are dealt
1825 * with unconditionally by this function and curl_multi_timeout() requires
1826 * that already passed/handled expire times are removed from the splay.
1828 * It is important that the 'now' value is set at the entry of this function
1829 * and not for the current time as it may have ticked a little while since
1830 * then and then we risk this loop to remove timers that actually have not
1834 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1836 /* the removed may have another timeout in queue */
1837 (void)add_next_timeout(now, multi, t->payload);
1841 *running_handles = multi->num_alive;
1843 if(CURLM_OK >= returncode)
1844 update_timer(multi);
1849 static void close_all_connections(struct Curl_multi *multi)
1851 struct connectdata *conn;
1853 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1855 conn->data = multi->closure_handle;
1857 /* This will remove the connection from the cache */
1858 (void)Curl_disconnect(conn, FALSE);
1860 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1864 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1866 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1867 struct Curl_one_easy *easy;
1868 struct Curl_one_easy *nexteasy;
1870 if(GOOD_MULTI_HANDLE(multi)) {
1871 multi->type = 0; /* not good anymore */
1873 /* Close all the connections in the connection cache */
1874 close_all_connections(multi);
1876 Curl_close(multi->closure_handle);
1877 multi->closure_handle = NULL;
1879 Curl_hash_destroy(multi->sockhash);
1880 multi->sockhash = NULL;
1882 Curl_conncache_destroy(multi->conn_cache);
1883 multi->conn_cache = NULL;
1885 /* remove the pending list of messages */
1886 Curl_llist_destroy(multi->msglist, NULL);
1887 multi->msglist = NULL;
1889 /* remove all easy handles */
1890 easy = multi->easy.next;
1891 while(easy != &multi->easy) {
1892 nexteasy=easy->next;
1893 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1894 /* clear out the usage of the shared DNS cache */
1895 Curl_hostcache_clean(easy->easy_handle);
1896 easy->easy_handle->dns.hostcache = NULL;
1897 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1900 /* Clear the pointer to the connection cache */
1901 easy->easy_handle->state.conn_cache = NULL;
1903 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1909 Curl_hash_destroy(multi->hostcache);
1910 multi->hostcache = NULL;
1917 return CURLM_BAD_HANDLE;
1921 * curl_multi_info_read()
1923 * This function is the primary way for a multi/multi_socket application to
1924 * figure out if a transfer has ended. We MUST make this function as fast as
1925 * possible as it will be polled frequently and we MUST NOT scan any lists in
1926 * here to figure out things. We must scale fine to thousands of handles and
1927 * beyond. The current design is fully O(1).
1930 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1932 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1933 struct Curl_message *msg;
1935 *msgs_in_queue = 0; /* default to none */
1937 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1938 /* there is one or more messages in the list */
1939 struct curl_llist_element *e;
1941 /* extract the head of the list to return */
1942 e = multi->msglist->head;
1946 /* remove the extracted entry */
1947 Curl_llist_remove(multi->msglist, e, NULL);
1949 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1951 return &msg->extmsg;
1958 * singlesocket() checks what sockets we deal with and their "action state"
1959 * and if we have a different state in any of those sockets from last time we
1960 * call the callback accordingly.
1962 static void singlesocket(struct Curl_multi *multi,
1963 struct Curl_one_easy *easy)
1965 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1967 struct Curl_sh_entry *entry;
1970 unsigned int curraction;
1971 struct Curl_one_easy *easy_by_hash;
1972 bool remove_sock_from_hash;
1974 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1975 socks[i] = CURL_SOCKET_BAD;
1977 /* Fill in the 'current' struct with the state as it is now: what sockets to
1978 supervise and for what actions */
1979 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1981 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1982 sockets we should have from now on. Detect the differences, remove no
1983 longer supervised ones and add new ones */
1985 /* walk over the sockets we got right now */
1986 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1987 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1989 int action = CURL_POLL_NONE;
1993 /* get it from the hash */
1994 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1996 if(curraction & GETSOCK_READSOCK(i))
1997 action |= CURL_POLL_IN;
1998 if(curraction & GETSOCK_WRITESOCK(i))
1999 action |= CURL_POLL_OUT;
2002 /* yeps, already present so check if it has the same action set */
2003 if(entry->action == action)
2004 /* same, continue */
2008 /* this is a socket we didn't have before, add it! */
2009 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
2015 /* we know (entry != NULL) at this point, see the logic above */
2016 if(multi->socket_cb)
2017 multi->socket_cb(easy->easy_handle,
2020 multi->socket_userp,
2023 entry->action = action; /* store the current action state */
2026 num = i; /* number of sockets */
2028 /* when we've walked over all the sockets we should have right now, we must
2029 make sure to detect sockets that are removed */
2030 for(i=0; i< easy->numsocks; i++) {
2032 s = easy->sockets[i];
2033 for(j=0; j<num; j++) {
2035 /* this is still supervised */
2036 s = CURL_SOCKET_BAD;
2040 if(s != CURL_SOCKET_BAD) {
2042 /* this socket has been removed. Tell the app to remove it */
2043 remove_sock_from_hash = TRUE;
2045 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2047 /* check if the socket to be removed serves a connection which has
2048 other easy-s in a pipeline. In this case the socket should not be
2050 struct connectdata *easy_conn;
2052 easy_by_hash = entry->easy->multi_pos;
2053 easy_conn = easy_by_hash->easy_conn;
2055 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2056 /* the handle should not be removed from the pipe yet */
2057 remove_sock_from_hash = FALSE;
2059 /* Update the sockhash entry to instead point to the next in line
2060 for the recv_pipe, or the first (in case this particular easy
2062 if(entry->easy == easy->easy_handle) {
2063 if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
2064 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2066 entry->easy = easy_conn->recv_pipe->head->ptr;
2069 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2070 /* the handle should not be removed from the pipe yet */
2071 remove_sock_from_hash = FALSE;
2073 /* Update the sockhash entry to instead point to the next in line
2074 for the send_pipe, or the first (in case this particular easy
2076 if(entry->easy == easy->easy_handle) {
2077 if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
2078 entry->easy = easy_conn->send_pipe->head->next->ptr;
2080 entry->easy = easy_conn->send_pipe->head->ptr;
2083 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2084 when action will be asked on the socket (see multi_socket()), the
2085 head of the correct pipe will be taken according to the
2090 /* just a precaution, this socket really SHOULD be in the hash already
2091 but in case it isn't, we don't have to tell the app to remove it
2092 either since it never got to know about it */
2093 remove_sock_from_hash = FALSE;
2095 if(remove_sock_from_hash) {
2096 /* in this case 'entry' is always non-NULL */
2097 if(multi->socket_cb)
2098 multi->socket_cb(easy->easy_handle,
2101 multi->socket_userp,
2103 sh_delentry(multi->sockhash, s);
2109 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2110 easy->numsocks = num;
2114 * add_next_timeout()
2116 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2117 * when it has just been removed from the splay tree because the timeout has
2118 * expired. This function is then to advance in the list to pick the next
2119 * timeout to use (skip the already expired ones) and add this node back to
2120 * the splay tree again.
2122 * The splay tree only has each sessionhandle as a single node and the nearest
2123 * timeout is used to sort it on.
2125 static CURLMcode add_next_timeout(struct timeval now,
2126 struct Curl_multi *multi,
2127 struct SessionHandle *d)
2129 struct timeval *tv = &d->state.expiretime;
2130 struct curl_llist *list = d->state.timeoutlist;
2131 struct curl_llist_element *e;
2133 /* move over the timeout list for this specific handle and remove all
2134 timeouts that are now passed tense and store the next pending
2136 for(e = list->head; e; ) {
2137 struct curl_llist_element *n = e->next;
2138 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2140 /* remove outdated entry */
2141 Curl_llist_remove(list, e, NULL);
2143 /* the list is sorted so get out on the first mismatch */
2149 /* clear the expire times within the handles that we remove from the
2155 /* copy the first entry to 'tv' */
2156 memcpy(tv, e->ptr, sizeof(*tv));
2158 /* remove first entry from list */
2159 Curl_llist_remove(list, e, NULL);
2161 /* insert this node again into the splay */
2162 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2163 &d->state.timenode);
2169 static CURLMcode multi_socket(struct Curl_multi *multi,
2173 int *running_handles)
2175 CURLMcode result = CURLM_OK;
2176 struct SessionHandle *data = NULL;
2177 struct Curl_tree *t;
2178 struct timeval now = Curl_tvnow();
2181 struct Curl_one_easy *easyp;
2182 /* *perform() deals with running_handles on its own */
2183 result = curl_multi_perform(multi, running_handles);
2185 /* walk through each easy handle and do the socket state change magic
2187 easyp=multi->easy.next;
2188 while(easyp != &multi->easy) {
2189 singlesocket(multi, easyp);
2190 easyp = easyp->next;
2193 /* or should we fall-through and do the timer-based stuff? */
2196 else if(s != CURL_SOCKET_TIMEOUT) {
2198 struct Curl_sh_entry *entry =
2199 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2202 /* Unmatched socket, we can't act on it but we ignore this fact. In
2203 real-world tests it has been proved that libevent can in fact give
2204 the application actions even though the socket was just previously
2205 asked to get removed, so thus we better survive stray socket actions
2206 and just move on. */
2211 if(data->magic != CURLEASY_MAGIC_NUMBER)
2212 /* bad bad bad bad bad bad bad */
2213 return CURLM_INTERNAL_ERROR;
2215 /* If the pipeline is enabled, take the handle which is in the head of
2216 the pipeline. If we should write into the socket, take the send_pipe
2217 head. If we should read from the socket, take the recv_pipe head. */
2218 if(data->set.one_easy->easy_conn) {
2219 if((ev_bitmask & CURL_POLL_OUT) &&
2220 data->set.one_easy->easy_conn->send_pipe &&
2221 data->set.one_easy->easy_conn->send_pipe->head)
2222 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2223 else if((ev_bitmask & CURL_POLL_IN) &&
2224 data->set.one_easy->easy_conn->recv_pipe &&
2225 data->set.one_easy->easy_conn->recv_pipe->head)
2226 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2229 if(data->set.one_easy->easy_conn &&
2230 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2231 /* set socket event bitmask if they're not locked */
2232 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2235 result = multi_runsingle(multi, now, data->set.one_easy);
2236 while(CURLM_CALL_MULTI_PERFORM == result);
2238 if(data->set.one_easy->easy_conn &&
2239 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2240 /* clear the bitmask only if not locked */
2241 data->set.one_easy->easy_conn->cselect_bits = 0;
2243 if(CURLM_OK >= result)
2244 /* get the socket(s) and check if the state has been changed since
2246 singlesocket(multi, data->set.one_easy);
2248 /* Now we fall-through and do the timer-based stuff, since we don't want
2249 to force the user to have to deal with timeouts as long as at least
2250 one connection in fact has traffic. */
2252 data = NULL; /* set data to NULL again to avoid calling
2253 multi_runsingle() in case there's no need to */
2257 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2258 triggered too early */
2259 if(now.tv_usec >= 1000000) {
2261 now.tv_usec -= 1000000;
2265 * The loop following here will go on as long as there are expire-times left
2266 * to process in the splay and 'data' will be re-assigned for every expired
2267 * handle we deal with.
2270 /* the first loop lap 'data' can be NULL */
2273 result = multi_runsingle(multi, now, data->set.one_easy);
2274 while(CURLM_CALL_MULTI_PERFORM == result);
2276 if(CURLM_OK >= result)
2277 /* get the socket(s) and check if the state has been changed since
2279 singlesocket(multi, data->set.one_easy);
2282 /* Check if there's one (more) expired timer to deal with! This function
2283 extracts a matching node if there is one */
2285 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2287 data = t->payload; /* assign this for next loop */
2288 (void)add_next_timeout(now, multi, t->payload);
2293 *running_handles = multi->num_alive;
2297 #undef curl_multi_setopt
2298 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2299 CURLMoption option, ...)
2301 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2302 CURLMcode res = CURLM_OK;
2305 if(!GOOD_MULTI_HANDLE(multi))
2306 return CURLM_BAD_HANDLE;
2308 va_start(param, option);
2311 case CURLMOPT_SOCKETFUNCTION:
2312 multi->socket_cb = va_arg(param, curl_socket_callback);
2314 case CURLMOPT_SOCKETDATA:
2315 multi->socket_userp = va_arg(param, void *);
2317 case CURLMOPT_PIPELINING:
2318 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2320 case CURLMOPT_TIMERFUNCTION:
2321 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2323 case CURLMOPT_TIMERDATA:
2324 multi->timer_userp = va_arg(param, void *);
2326 case CURLMOPT_MAXCONNECTS:
2327 multi->maxconnects = va_arg(param, long);
2330 res = CURLM_UNKNOWN_OPTION;
2337 /* we define curl_multi_socket() in the public multi.h header */
2338 #undef curl_multi_socket
2340 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2341 int *running_handles)
2343 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2344 0, running_handles);
2345 if(CURLM_OK >= result)
2346 update_timer((struct Curl_multi *)multi_handle);
2350 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2351 int ev_bitmask, int *running_handles)
2353 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2354 ev_bitmask, running_handles);
2355 if(CURLM_OK >= result)
2356 update_timer((struct Curl_multi *)multi_handle);
2360 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2363 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2364 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2365 if(CURLM_OK >= result)
2366 update_timer((struct Curl_multi *)multi_handle);
2370 static CURLMcode multi_timeout(struct Curl_multi *multi,
2373 static struct timeval tv_zero = {0,0};
2375 if(multi->timetree) {
2376 /* we have a tree of expire times */
2377 struct timeval now = Curl_tvnow();
2379 /* splay the lowest to the bottom */
2380 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2382 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2383 /* some time left before expiration */
2384 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2387 * Since we only provide millisecond resolution on the returned value
2388 * and the diff might be less than one millisecond here, we don't
2389 * return zero as that may cause short bursts of busyloops on fast
2390 * processors while the diff is still present but less than one
2391 * millisecond! instead we return 1 until the time is ripe.
2396 /* 0 means immediately */
2405 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2408 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2410 /* First, make some basic checks that the CURLM handle is a good handle */
2411 if(!GOOD_MULTI_HANDLE(multi))
2412 return CURLM_BAD_HANDLE;
2414 return multi_timeout(multi, timeout_ms);
2418 * Tell the application it should update its timers, if it subscribes to the
2419 * update timer callback.
2421 static int update_timer(struct Curl_multi *multi)
2425 if(!multi->timer_cb)
2427 if(multi_timeout(multi, &timeout_ms)) {
2430 if(timeout_ms < 0) {
2431 static const struct timeval none={0,0};
2432 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2433 multi->timer_lastcall = none;
2434 /* there's no timeout now but there was one previously, tell the app to
2436 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2441 /* When multi_timeout() is done, multi->timetree points to the node with the
2442 * timeout we got the (relative) time-out time for. We can thus easily check
2443 * if this is the same (fixed) time as we got in a previous call and then
2444 * avoid calling the callback again. */
2445 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2448 multi->timer_lastcall = multi->timetree->key;
2450 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2453 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2454 struct connectdata *conn)
2456 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2457 struct curl_llist_element *sendhead = conn->send_pipe->head;
2458 struct curl_llist *pipeline;
2461 if(!Curl_isPipeliningEnabled(handle) ||
2463 pipeline = conn->send_pipe;
2465 if(conn->server_supports_pipelining &&
2466 pipeLen < MAX_PIPELINE_LENGTH)
2467 pipeline = conn->send_pipe;
2469 pipeline = conn->pend_pipe;
2472 rc = Curl_addHandleToPipeline(handle, pipeline);
2474 if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2475 /* this is a new one as head, expire it */
2476 conn->writechannel_inuse = FALSE; /* not in use yet */
2478 infof(conn->data, "%p is at send pipe head!\n",
2479 conn->send_pipe->head->ptr);
2481 Curl_expire(conn->send_pipe->head->ptr, 1);
2487 static int checkPendPipeline(struct connectdata *conn)
2490 struct curl_llist_element *sendhead = conn->send_pipe->head;
2492 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2493 if(conn->server_supports_pipelining || pipeLen == 0) {
2494 struct curl_llist_element *curr = conn->pend_pipe->head;
2495 const size_t maxPipeLen =
2496 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2498 while(pipeLen < maxPipeLen && curr) {
2499 Curl_llist_move(conn->pend_pipe, curr,
2500 conn->send_pipe, conn->send_pipe->tail);
2501 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2502 ++result; /* count how many handles we moved */
2503 curr = conn->pend_pipe->head;
2509 conn->now = Curl_tvnow();
2510 /* something moved, check for a new send pipeline leader */
2511 if(sendhead != conn->send_pipe->head) {
2512 /* this is a new one as head, expire it */
2513 conn->writechannel_inuse = FALSE; /* not in use yet */
2515 infof(conn->data, "%p is at send pipe head!\n",
2516 conn->send_pipe->head->ptr);
2518 Curl_expire(conn->send_pipe->head->ptr, 1);
2525 /* Move this transfer from the sending list to the receiving list.
2527 Pay special attention to the new sending list "leader" as it needs to get
2528 checked to update what sockets it acts on.
2531 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2532 struct connectdata *conn)
2534 struct curl_llist_element *curr;
2536 curr = conn->send_pipe->head;
2538 if(curr->ptr == handle) {
2539 Curl_llist_move(conn->send_pipe, curr,
2540 conn->recv_pipe, conn->recv_pipe->tail);
2542 if(conn->send_pipe->head) {
2543 /* Since there's a new easy handle at the start of the send pipeline,
2544 set its timeout value to 1ms to make it trigger instantly */
2545 conn->writechannel_inuse = FALSE; /* not used now */
2547 infof(conn->data, "%p is at send pipe head B!\n",
2548 conn->send_pipe->head->ptr);
2550 Curl_expire(conn->send_pipe->head->ptr, 1);
2553 /* The receiver's list is not really interesting here since either this
2554 handle is now first in the list and we'll deal with it soon, or
2555 another handle is already first and thus is already taken care of */
2557 break; /* we're done! */
2563 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2564 struct connectdata *conn)
2566 struct curl_llist_element *curr;
2568 curr = conn->recv_pipe->head;
2570 if(curr->ptr == handle) {
2571 Curl_llist_move(conn->recv_pipe, curr,
2572 conn->done_pipe, conn->done_pipe->tail);
2578 static bool isHandleAtHead(struct SessionHandle *handle,
2579 struct curl_llist *pipeline)
2581 struct curl_llist_element *curr = pipeline->head;
2583 return (curr->ptr == handle) ? TRUE : FALSE;
2589 * multi_freetimeout()
2591 * Callback used by the llist system when a single timeout list entry is
2594 static void multi_freetimeout(void *user, void *entryptr)
2598 /* the entry was plain malloc()'ed */
2603 * multi_addtimeout()
2605 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2606 * of list is always the timeout nearest in time.
2610 multi_addtimeout(struct curl_llist *timeoutlist,
2611 struct timeval *stamp)
2613 struct curl_llist_element *e;
2614 struct timeval *timedup;
2615 struct curl_llist_element *prev = NULL;
2617 timedup = malloc(sizeof(*timedup));
2619 return CURLM_OUT_OF_MEMORY;
2621 /* copy the timestamp */
2622 memcpy(timedup, stamp, sizeof(*timedup));
2624 if(Curl_llist_count(timeoutlist)) {
2625 /* find the correct spot in the list */
2626 for(e = timeoutlist->head; e; e = e->next) {
2627 struct timeval *checktime = e->ptr;
2628 long diff = curlx_tvdiff(*checktime, *timedup);
2636 this is the first timeout on the list */
2638 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2640 return CURLM_OUT_OF_MEMORY;
2649 * given a number of milliseconds from now to use to set the 'act before
2650 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2652 * Note that the timeout will be added to a queue of timeouts if it defines a
2653 * moment in time that is later than the current head of queue.
2655 * Pass zero to clear all timeout values for this handle.
2657 void Curl_expire(struct SessionHandle *data, long milli)
2659 struct Curl_multi *multi = data->multi;
2660 struct timeval *nowp = &data->state.expiretime;
2663 /* this is only interesting for multi-interface using libcurl, and only
2664 while there is still a multi interface struct remaining! */
2669 /* No timeout, clear the time data. */
2670 if(nowp->tv_sec || nowp->tv_usec) {
2671 /* Since this is an cleared time, we must remove the previous entry from
2673 struct curl_llist *list = data->state.timeoutlist;
2675 rc = Curl_splayremovebyaddr(multi->timetree,
2676 &data->state.timenode,
2679 infof(data, "Internal error clearing splay node = %d\n", rc);
2681 /* flush the timeout list too */
2682 while(list->size > 0)
2683 Curl_llist_remove(list, list->tail, NULL);
2686 infof(data, "Expire cleared\n");
2696 set.tv_sec += milli/1000;
2697 set.tv_usec += (milli%1000)*1000;
2699 if(set.tv_usec >= 1000000) {
2701 set.tv_usec -= 1000000;
2704 if(nowp->tv_sec || nowp->tv_usec) {
2705 /* This means that the struct is added as a node in the splay tree.
2706 Compare if the new time is earlier, and only remove-old/add-new if it
2708 long diff = curlx_tvdiff(set, *nowp);
2710 /* the new expire time was later so just add it to the queue
2712 multi_addtimeout(data->state.timeoutlist, &set);
2716 /* the new time is newer than the presently set one, so add the current
2717 to the queue and update the head */
2718 multi_addtimeout(data->state.timeoutlist, nowp);
2720 /* Since this is an updated time, we must remove the previous entry from
2721 the splay tree first and then re-add the new value */
2722 rc = Curl_splayremovebyaddr(multi->timetree,
2723 &data->state.timenode,
2726 infof(data, "Internal error removing splay node = %d\n", rc);
2730 data->state.timenode.payload = data;
2731 multi->timetree = Curl_splayinsert(*nowp,
2733 &data->state.timenode);
2736 Curl_splayprint(multi->timetree, 0, TRUE);
2740 CURLMcode curl_multi_assign(CURLM *multi_handle,
2741 curl_socket_t s, void *hashp)
2743 struct Curl_sh_entry *there = NULL;
2744 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2746 if(s != CURL_SOCKET_BAD)
2747 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2750 return CURLM_BAD_SOCKET;
2752 there->socketp = hashp;
2758 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2760 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2761 struct Curl_one_easy *easy;
2763 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2764 multi->num_easy, multi->num_alive);
2765 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2766 if(easy->state < CURLM_STATE_COMPLETED) {
2767 /* only display handles that are not completed */
2768 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2769 (void *)easy->easy_handle,
2770 statename[easy->state], easy->numsocks);
2771 for(i=0; i < easy->numsocks; i++) {
2772 curl_socket_t s = easy->sockets[i];
2773 struct Curl_sh_entry *entry =
2774 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2776 fprintf(stderr, "%d ", (int)s);
2778 fprintf(stderr, "INTERNAL CONFUSION\n");
2781 fprintf(stderr, "[%s %s] ",
2782 entry->action&CURL_POLL_IN?"RECVING":"",
2783 entry->action&CURL_POLL_OUT?"SENDING":"");
2786 fprintf(stderr, "\n");