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;
436 struct curl_hash *hostcache = NULL;
438 /* First, make some basic checks that the CURLM handle is a good handle */
439 if(!GOOD_MULTI_HANDLE(multi))
440 return CURLM_BAD_HANDLE;
442 /* Verify that we got a somewhat good easy handle too */
443 if(!GOOD_EASY_HANDLE(easy_handle))
444 return CURLM_BAD_EASY_HANDLE;
446 /* Prevent users from adding same easy handle more than
447 once and prevent adding to more than one multi stack */
449 /* possibly we should create a new unique error code for this condition */
450 return CURLM_BAD_EASY_HANDLE;
452 /* Allocate and initialize timeout list for easy handle */
453 timeoutlist = Curl_llist_alloc(multi_freetimeout);
455 return CURLM_OUT_OF_MEMORY;
457 /* Allocate new node for the doubly-linked circular list of
458 Curl_one_easy structs that holds pointers to easy handles */
459 easy = calloc(1, sizeof(struct Curl_one_easy));
461 Curl_llist_destroy(timeoutlist, NULL);
462 return CURLM_OUT_OF_MEMORY;
465 /* In case multi handle has no hostcache yet, allocate one */
466 if(!multi->hostcache) {
467 hostcache = Curl_mk_dnscache();
470 Curl_llist_destroy(timeoutlist, NULL);
471 return CURLM_OUT_OF_MEMORY;
475 /* In case multi handle has no closure_handle yet, allocate
476 a new easy handle to use when closing cached connections */
477 if(!multi->closure_handle) {
478 new_closure = (struct SessionHandle *)curl_easy_init();
480 Curl_hash_destroy(hostcache);
482 Curl_llist_destroy(timeoutlist, NULL);
483 return CURLM_OUT_OF_MEMORY;
488 ** No failure allowed in this function beyond this point. And
489 ** no modification of easy nor multi handle allowed before this
490 ** except for potential multi's connection cache growing which
491 ** won't be undone in this function no matter what.
494 /* In case a new closure handle has been initialized above, it
495 is associated now with the multi handle which lacked one. */
497 multi->closure_handle = new_closure;
498 Curl_easy_addmulti(multi->closure_handle, multi_handle);
499 multi->closure_handle->state.conn_cache = multi->conn_cache;
502 /* In case hostcache has been allocated above,
503 it is associated now with the multi handle. */
505 multi->hostcache = hostcache;
507 /* Make easy handle use timeout list initialized above */
508 data->state.timeoutlist = timeoutlist;
511 /* set the easy handle */
512 easy->easy_handle = data;
513 multistate(easy, CURLM_STATE_INIT);
515 /* set the back pointer to one_easy to assist in removal */
516 easy->easy_handle->multi_pos = easy;
518 /* for multi interface connections, we share DNS cache automatically if the
519 easy handle's one is currently private. */
520 if(easy->easy_handle->dns.hostcache &&
521 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
522 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
523 easy->easy_handle->dns.hostcache = NULL;
524 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
527 if(!easy->easy_handle->dns.hostcache ||
528 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
529 easy->easy_handle->dns.hostcache = multi->hostcache;
530 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
533 /* On a multi stack the connection cache, owned by the multi handle,
534 is shared between all easy handles within the multi handle.
535 Therefore we free the private connection cache if there is one */
536 if(easy->easy_handle->state.conn_cache &&
537 easy->easy_handle->state.conn_cache->type == CONNCACHE_PRIVATE) {
538 Curl_conncache_destroy(easy->easy_handle->state.conn_cache);
541 /* Point now to this multi's connection cache */
542 easy->easy_handle->state.conn_cache = multi->conn_cache;
544 /* This adds the new entry at the 'end' of the doubly-linked circular
545 list of Curl_one_easy structs to try and maintain a FIFO queue so
546 the pipelined requests are in order. */
548 /* We add this new entry last in the list. We make our 'next' point to the
549 'first' struct and our 'prev' point to the previous 'prev' */
550 easy->next = &multi->easy;
551 easy->prev = multi->easy.prev;
553 /* make 'easy' the last node in the chain */
554 multi->easy.prev = easy;
556 /* if there was a prev node, make sure its 'next' pointer links to
558 easy->prev->next = easy;
560 /* make the SessionHandle refer back to this multi handle */
561 Curl_easy_addmulti(easy_handle, multi_handle);
563 /* make the SessionHandle struct refer back to this struct */
564 easy->easy_handle->set.one_easy = easy;
566 /* Set the timeout for this handle to expire really soon so that it will
567 be taken care of even when this handle is added in the midst of operation
568 when only the curl_multi_socket() API is used. During that flow, only
569 sockets that time-out or have actions will be dealt with. Since this
570 handle has no action yet, we make sure it times out to get things to
572 Curl_expire(easy->easy_handle, 1);
574 /* increase the node-counter */
577 /* increase the alive-counter */
580 /* A somewhat crude work-around for a little glitch in update_timer() that
581 happens if the lastcall time is set to the same time when the handle is
582 removed as when the next handle is added, as then the check in
583 update_timer() that prevents calling the application multiple times with
584 the same timer infor will not trigger and then the new handle's timeout
585 will not be notified to the app.
587 The work-around is thus simply to clear the 'lastcall' variable to force
588 update_timer() to always trigger a callback to the app when a new easy
590 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
597 /* Debug-function, used like this:
599 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
601 * Enable the hash print function first by editing hash.c
603 static void debug_print_sock_hash(void *p)
605 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
607 fprintf(stderr, " [easy %p/magic %x/socket %d]",
608 (void *)sh->easy, sh->easy->magic, (int)sh->socket);
612 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
615 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
616 struct Curl_one_easy *easy;
617 struct SessionHandle *data = curl_handle;
619 /* First, make some basic checks that the CURLM handle is a good handle */
620 if(!GOOD_MULTI_HANDLE(multi))
621 return CURLM_BAD_HANDLE;
623 /* Verify that we got a somewhat good easy handle too */
624 if(!GOOD_EASY_HANDLE(curl_handle))
625 return CURLM_BAD_EASY_HANDLE;
627 /* pick-up from the 'curl_handle' the kept position in the list */
628 easy = data->multi_pos;
631 bool premature = (easy->state < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
632 bool easy_owns_conn = (easy->easy_conn &&
633 (easy->easy_conn->data == easy->easy_handle)) ?
636 /* If the 'state' is not INIT or COMPLETED, we might need to do something
637 nice to put the easy_handle in a good known state when this returns. */
639 /* this handle is "alive" so we need to count down the total number of
640 alive connections when this is removed */
643 if(easy->easy_conn &&
644 (easy->easy_conn->send_pipe->size +
645 easy->easy_conn->recv_pipe->size > 1) &&
646 easy->state > CURLM_STATE_WAITDO &&
647 easy->state < CURLM_STATE_COMPLETED) {
648 /* If the handle is in a pipeline and has started sending off its
649 request but not received its response yet, we need to close
651 easy->easy_conn->bits.close = TRUE;
652 /* Set connection owner so that Curl_done() closes it.
653 We can sefely do this here since connection is killed. */
654 easy->easy_conn->data = easy->easy_handle;
657 /* The timer must be shut down before easy->multi is set to NULL,
658 else the timenode will remain in the splay tree after
659 curl_easy_cleanup is called. */
660 Curl_expire(easy->easy_handle, 0);
662 /* destroy the timeout list that is held in the easy handle */
663 if(data->state.timeoutlist) {
664 Curl_llist_destroy(data->state.timeoutlist, NULL);
665 data->state.timeoutlist = NULL;
668 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
669 if(multi->num_easy == 1) {
671 Curl_resolver_cancel(easy->easy_conn);
672 if(easy->easy_conn->dns_entry) {
673 Curl_resolv_unlock(easy->easy_handle, easy->easy_conn->dns_entry);
674 easy->easy_conn->dns_entry = NULL;
677 Curl_hostcache_destroy(easy->easy_handle);
678 multi->hostcache = NULL;
680 /* clear out the usage of the shared DNS cache */
681 easy->easy_handle->dns.hostcache = NULL;
682 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
685 if(easy->easy_conn) {
687 /* we must call Curl_done() here (if we still "own it") so that we don't
688 leave a half-baked one around */
691 /* Curl_done() clears the conn->data field to lose the association
692 between the easy handle and the connection
694 Note that this ignores the return code simply because there's
695 nothing really useful to do with it anyway! */
696 (void)Curl_done(&easy->easy_conn, easy->result, premature);
699 /* Clear connection pipelines, if Curl_done above was not called */
700 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
703 if(easy->easy_handle->state.conn_cache->type == CONNCACHE_MULTI) {
704 /* if this was using the shared connection cache we clear the pointer
705 to that since we're not part of that handle anymore */
706 easy->easy_handle->state.conn_cache = NULL;
707 easy->easy_handle->state.lastconnect = NULL;
710 /* change state without using multistate(), only to make singlesocket() do
712 easy->state = CURLM_STATE_COMPLETED;
713 singlesocket(multi, easy); /* to let the application know what sockets
714 that vanish with this handle */
716 /* Remove the association between the connection and the handle */
717 if(easy->easy_conn) {
718 easy->easy_conn->data = NULL;
719 easy->easy_conn = NULL;
722 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
723 to this multi handle */
726 /* make sure there's no pending message in the queue sent from this easy
728 struct curl_llist_element *e;
730 for(e = multi->msglist->head; e; e = e->next) {
731 struct Curl_message *msg = e->ptr;
733 if(msg->extmsg.easy_handle == easy->easy_handle) {
734 Curl_llist_remove(multi->msglist, e, NULL);
735 /* there can only be one from this specific handle */
741 /* make the previous node point to our next */
743 easy->prev->next = easy->next;
744 /* make our next point to our previous node */
746 easy->next->prev = easy->prev;
748 easy->easy_handle->set.one_easy = NULL; /* detached */
750 /* Null the position in the controlling structure */
751 easy->easy_handle->multi_pos = NULL;
754 We do not touch the easy handle here! */
757 multi->num_easy--; /* one less to care about now */
763 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
766 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
768 return multi->pipelining_enabled;
771 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
773 struct Curl_one_easy *one_easy = data->set.one_easy;
776 one_easy->easy_conn = NULL;
779 static int waitconnect_getsock(struct connectdata *conn,
784 return GETSOCK_BLANK;
786 sock[0] = conn->sock[FIRSTSOCKET];
788 /* when we've sent a CONNECT to a proxy, we should rather wait for the
789 socket to become readable to be able to get the response headers */
790 if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
791 return GETSOCK_READSOCK(0);
793 return GETSOCK_WRITESOCK(0);
796 static int domore_getsock(struct connectdata *conn,
797 curl_socket_t *socks,
800 if(conn && conn->handler->domore_getsock)
801 return conn->handler->domore_getsock(conn, socks, numsocks);
802 return GETSOCK_BLANK;
805 /* returns bitmapped flags for this handle and its sockets */
806 static int multi_getsock(struct Curl_one_easy *easy,
807 curl_socket_t *socks, /* points to numsocks number
811 /* If the pipe broke, or if there's no connection left for this easy handle,
812 then we MUST bail out now with no bitmask set. The no connection case can
813 happen when this is called from curl_multi_remove_handle() =>
814 singlesocket() => multi_getsock().
816 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
819 if(easy->state > CURLM_STATE_CONNECT &&
820 easy->state < CURLM_STATE_COMPLETED) {
821 /* Set up ownership correctly */
822 easy->easy_conn->data = easy->easy_handle;
825 switch(easy->state) {
827 #if 0 /* switch back on these cases to get the compiler to check for all enums
829 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
830 case CURLM_STATE_COMPLETED:
831 case CURLM_STATE_MSGSENT:
832 case CURLM_STATE_INIT:
833 case CURLM_STATE_CONNECT:
834 case CURLM_STATE_WAITDO:
835 case CURLM_STATE_DONE:
836 case CURLM_STATE_LAST:
837 /* this will get called with CURLM_STATE_COMPLETED when a handle is
842 case CURLM_STATE_WAITRESOLVE:
843 return Curl_resolver_getsock(easy->easy_conn, socks, numsocks);
845 case CURLM_STATE_PROTOCONNECT:
846 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
849 case CURLM_STATE_DOING:
850 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
852 case CURLM_STATE_WAITPROXYCONNECT:
853 case CURLM_STATE_WAITCONNECT:
854 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
856 case CURLM_STATE_DO_MORE:
857 return domore_getsock(easy->easy_conn, socks, numsocks);
859 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
860 to waiting for the same as the *PERFORM
862 case CURLM_STATE_PERFORM:
863 case CURLM_STATE_WAITPERFORM:
864 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
869 CURLMcode curl_multi_fdset(CURLM *multi_handle,
870 fd_set *read_fd_set, fd_set *write_fd_set,
871 fd_set *exc_fd_set, int *max_fd)
873 /* Scan through all the easy handles to get the file descriptors set.
874 Some easy handles may not have connected to the remote host yet,
875 and then we must make sure that is done. */
876 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
877 struct Curl_one_easy *easy;
879 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
882 (void)exc_fd_set; /* not used */
884 if(!GOOD_MULTI_HANDLE(multi))
885 return CURLM_BAD_HANDLE;
887 easy=multi->easy.next;
888 while(easy != &multi->easy) {
889 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
891 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
892 curl_socket_t s = CURL_SOCKET_BAD;
894 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
895 FD_SET(sockbunch[i], read_fd_set);
898 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
899 FD_SET(sockbunch[i], write_fd_set);
902 if(s == CURL_SOCKET_BAD)
903 /* this socket is unused, break out of loop */
906 if((int)s > this_max_fd)
907 this_max_fd = (int)s;
911 easy = easy->next; /* check next handle */
914 *max_fd = this_max_fd;
919 CURLMcode curl_multi_wait(CURLM *multi_handle,
920 struct curl_waitfd extra_fds[],
921 unsigned int extra_nfds,
925 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
926 struct Curl_one_easy *easy;
927 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
930 unsigned int nfds = extra_nfds;
931 struct pollfd *ufds = NULL;
933 if(!GOOD_MULTI_HANDLE(multi))
934 return CURLM_BAD_HANDLE;
936 /* Count up how many fds we have from the multi handle */
937 easy=multi->easy.next;
938 while(easy != &multi->easy) {
939 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
941 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
942 curl_socket_t s = CURL_SOCKET_BAD;
944 if(bitmap & GETSOCK_READSOCK(i)) {
948 if(bitmap & GETSOCK_WRITESOCK(i)) {
952 if(s == CURL_SOCKET_BAD) {
957 easy = easy->next; /* check next handle */
961 ufds = malloc(nfds * sizeof(struct pollfd));
963 return CURLM_OUT_OF_MEMORY;
967 /* Add the curl handles to our pollfds first */
968 easy=multi->easy.next;
969 while(easy != &multi->easy) {
970 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
972 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
973 curl_socket_t s = CURL_SOCKET_BAD;
975 if(bitmap & GETSOCK_READSOCK(i)) {
976 ufds[nfds].fd = sockbunch[i];
977 ufds[nfds].events = POLLIN;
981 if(bitmap & GETSOCK_WRITESOCK(i)) {
982 ufds[nfds].fd = sockbunch[i];
983 ufds[nfds].events = POLLOUT;
987 if(s == CURL_SOCKET_BAD) {
992 easy = easy->next; /* check next handle */
995 /* Add external file descriptions from poll-like struct curl_waitfd */
996 for(i = 0; i < extra_nfds; i++) {
997 ufds[nfds].fd = extra_fds[i].fd;
998 ufds[nfds].events = 0;
999 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1000 ufds[nfds].events |= POLLIN;
1001 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1002 ufds[nfds].events |= POLLPRI;
1003 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1004 ufds[nfds].events |= POLLOUT;
1010 i = Curl_poll(ufds, nfds, timeout_ms);
1014 Curl_safefree(ufds);
1020 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1022 struct Curl_one_easy *easy)
1024 struct Curl_message *msg = NULL;
1027 bool protocol_connect = FALSE;
1030 CURLMcode result = CURLM_OK;
1031 struct SingleRequest *k;
1032 struct SessionHandle *data;
1035 if(!GOOD_EASY_HANDLE(easy->easy_handle))
1036 return CURLM_BAD_EASY_HANDLE;
1038 data = easy->easy_handle;
1041 /* this is a single-iteration do-while loop just to allow a
1042 break to skip to the end of it */
1043 bool disconnect_conn = FALSE;
1045 /* Handle the case when the pipe breaks, i.e., the connection
1046 we're using gets cleaned up and we're left with nothing. */
1047 if(data->state.pipe_broke) {
1048 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
1049 easy, data->state.path);
1051 if(easy->state < CURLM_STATE_COMPLETED) {
1052 /* Head back to the CONNECT state */
1053 multistate(easy, CURLM_STATE_CONNECT);
1054 result = CURLM_CALL_MULTI_PERFORM;
1055 easy->result = CURLE_OK;
1058 data->state.pipe_broke = FALSE;
1059 easy->easy_conn = NULL;
1063 if(!easy->easy_conn &&
1064 easy->state > CURLM_STATE_CONNECT &&
1065 easy->state < CURLM_STATE_DONE) {
1066 /* In all these states, the code will blindly access 'easy->easy_conn'
1067 so this is precaution that it isn't NULL. And it silences static
1069 failf(data, "In state %d with no easy_conn, bail out!\n", easy->state);
1070 return CURLM_INTERNAL_ERROR;
1073 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
1074 easy->state < CURLM_STATE_COMPLETED)
1075 /* Make sure we set the connection's current owner */
1076 easy->easy_conn->data = data;
1078 if(easy->easy_conn &&
1079 (easy->state >= CURLM_STATE_CONNECT) &&
1080 (easy->state < CURLM_STATE_COMPLETED)) {
1081 /* we need to wait for the connect state as only then is the start time
1082 stored, but we must not check already completed handles */
1084 timeout_ms = Curl_timeleft(data, &now,
1085 (easy->state <= CURLM_STATE_WAITDO)?
1088 if(timeout_ms < 0) {
1089 /* Handle timed out */
1090 if(easy->state == CURLM_STATE_WAITRESOLVE)
1091 failf(data, "Resolving timed out after %ld milliseconds",
1092 Curl_tvdiff(now, data->progress.t_startsingle));
1093 else if(easy->state == CURLM_STATE_WAITCONNECT)
1094 failf(data, "Connection timed out after %ld milliseconds",
1095 Curl_tvdiff(now, data->progress.t_startsingle));
1098 failf(data, "Operation timed out after %ld milliseconds with %"
1099 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1100 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1104 /* Force the connection closed because the server could continue to
1105 send us stuff at any time. (The disconnect_conn logic used below
1106 doesn't work at this point). */
1107 easy->easy_conn->bits.close = TRUE;
1108 easy->result = CURLE_OPERATION_TIMEDOUT;
1109 multistate(easy, CURLM_STATE_COMPLETED);
1114 switch(easy->state) {
1115 case CURLM_STATE_INIT:
1116 /* init this transfer. */
1117 easy->result=Curl_pretransfer(data);
1119 if(CURLE_OK == easy->result) {
1120 /* after init, go CONNECT */
1121 multistate(easy, CURLM_STATE_CONNECT);
1122 result = CURLM_CALL_MULTI_PERFORM;
1124 data->state.used_interface = Curl_if_multi;
1128 case CURLM_STATE_CONNECT:
1129 /* Connect. We get a connection identifier filled in. */
1130 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1131 easy->result = Curl_connect(data, &easy->easy_conn,
1132 &async, &protocol_connect);
1134 if(CURLE_OK == easy->result) {
1135 /* Add this handle to the send or pend pipeline */
1136 easy->result = addHandleToSendOrPendPipeline(data,
1138 if(CURLE_OK != easy->result)
1139 disconnect_conn = TRUE;
1142 /* We're now waiting for an asynchronous name lookup */
1143 multistate(easy, CURLM_STATE_WAITRESOLVE);
1145 /* after the connect has been sent off, go WAITCONNECT unless the
1146 protocol connect is already done and we can go directly to
1148 result = CURLM_CALL_MULTI_PERFORM;
1150 if(protocol_connect)
1151 multistate(easy, multi->pipelining_enabled?
1152 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1154 #ifndef CURL_DISABLE_HTTP
1155 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1156 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1159 multistate(easy, CURLM_STATE_WAITCONNECT);
1166 case CURLM_STATE_WAITRESOLVE:
1167 /* awaiting an asynch name resolve to complete */
1169 struct Curl_dns_entry *dns = NULL;
1171 /* check if we have the name resolved by now */
1172 easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
1174 /* Update sockets here, because the socket(s) may have been
1175 closed and the application thus needs to be told, even if it
1176 is likely that the same socket(s) will again be used further
1177 down. If the name has not yet been resolved, it is likely
1178 that new sockets have been opened in an attempt to contact
1179 another resolver. */
1180 singlesocket(multi, easy);
1183 /* Perform the next step in the connection phase, and then move on
1184 to the WAITCONNECT state */
1185 easy->result = Curl_async_resolved(easy->easy_conn,
1188 if(CURLE_OK != easy->result)
1189 /* if Curl_async_resolved() returns failure, the connection struct
1190 is already freed and gone */
1191 easy->easy_conn = NULL; /* no more connection */
1193 /* call again please so that we get the next socket setup */
1194 result = CURLM_CALL_MULTI_PERFORM;
1195 if(protocol_connect)
1196 multistate(easy, multi->pipelining_enabled?
1197 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1199 #ifndef CURL_DISABLE_HTTP
1200 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1201 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1204 multistate(easy, CURLM_STATE_WAITCONNECT);
1209 if(CURLE_OK != easy->result) {
1210 /* failure detected */
1211 disconnect_conn = TRUE;
1217 #ifndef CURL_DISABLE_HTTP
1218 case CURLM_STATE_WAITPROXYCONNECT:
1219 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1220 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1222 if(easy->easy_conn->bits.proxy_connect_closed) {
1223 /* reset the error buffer */
1224 if(data->set.errorbuffer)
1225 data->set.errorbuffer[0] = '\0';
1226 data->state.errorbuf = FALSE;
1228 easy->result = CURLE_OK;
1229 result = CURLM_CALL_MULTI_PERFORM;
1230 multistate(easy, CURLM_STATE_CONNECT);
1232 else if(CURLE_OK == easy->result) {
1233 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
1234 multistate(easy, CURLM_STATE_WAITCONNECT);
1239 case CURLM_STATE_WAITCONNECT:
1240 /* awaiting a completion of an asynch connect */
1241 easy->result = Curl_is_connected(easy->easy_conn,
1247 /* if everything is still fine we do the protocol-specific connect
1249 easy->result = Curl_protocol_connect(easy->easy_conn,
1253 if(CURLE_OK != easy->result) {
1254 /* failure detected */
1255 /* Just break, the cleaning up is handled all in one place */
1256 disconnect_conn = TRUE;
1261 if(!protocol_connect) {
1262 /* We have a TCP connection, but 'protocol_connect' may be false
1263 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1264 connect is TRUE, we move on to STATE_DO.
1265 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1267 #ifndef CURL_DISABLE_HTTP
1268 if(easy->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
1269 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1272 multistate(easy, CURLM_STATE_PROTOCONNECT);
1276 /* after the connect has completed, go WAITDO or DO */
1277 multistate(easy, multi->pipelining_enabled?
1278 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1280 result = CURLM_CALL_MULTI_PERFORM;
1284 case CURLM_STATE_PROTOCONNECT:
1285 /* protocol-specific connect phase */
1286 easy->result = Curl_protocol_connecting(easy->easy_conn,
1288 if((easy->result == CURLE_OK) && protocol_connect) {
1289 /* after the connect has completed, go WAITDO or DO */
1290 multistate(easy, multi->pipelining_enabled?
1291 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1292 result = CURLM_CALL_MULTI_PERFORM;
1294 else if(easy->result) {
1295 /* failure detected */
1296 Curl_posttransfer(data);
1297 Curl_done(&easy->easy_conn, easy->result, TRUE);
1298 disconnect_conn = TRUE;
1302 case CURLM_STATE_WAITDO:
1303 /* Wait for our turn to DO when we're pipelining requests */
1305 infof(data, "WAITDO: Conn %ld send pipe %zu inuse %d athead %d\n",
1306 easy->easy_conn->connection_id,
1307 easy->easy_conn->send_pipe->size,
1308 easy->easy_conn->writechannel_inuse?1:0,
1309 isHandleAtHead(data,
1310 easy->easy_conn->send_pipe)?1:0);
1312 if(!easy->easy_conn->writechannel_inuse &&
1313 isHandleAtHead(data,
1314 easy->easy_conn->send_pipe)) {
1315 /* Grab the channel */
1316 easy->easy_conn->writechannel_inuse = TRUE;
1317 multistate(easy, CURLM_STATE_DO);
1318 result = CURLM_CALL_MULTI_PERFORM;
1322 case CURLM_STATE_DO:
1323 if(data->set.connect_only) {
1324 /* keep connection open for application to use the socket */
1325 easy->easy_conn->bits.close = FALSE;
1326 multistate(easy, CURLM_STATE_DONE);
1327 easy->result = CURLE_OK;
1328 result = CURLM_CALL_MULTI_PERFORM;
1331 /* Perform the protocol's DO action */
1332 easy->result = Curl_do(&easy->easy_conn,
1335 if(CURLE_OK == easy->result) {
1337 /* some steps needed for wildcard matching */
1338 if(data->set.wildcardmatch) {
1339 struct WildcardData *wc = &data->wildcard;
1340 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1341 /* skip some states if it is important */
1342 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1343 multistate(easy, CURLM_STATE_DONE);
1344 result = CURLM_CALL_MULTI_PERFORM;
1348 /* DO was not completed in one function call, we must continue
1350 multistate(easy, CURLM_STATE_DOING);
1354 /* after DO, go DO_DONE... or DO_MORE */
1355 else if(easy->easy_conn->bits.do_more) {
1356 /* we're supposed to do more, but we need to sit down, relax
1357 and wait a little while first */
1358 multistate(easy, CURLM_STATE_DO_MORE);
1362 /* we're done with the DO, now DO_DONE */
1363 multistate(easy, CURLM_STATE_DO_DONE);
1364 result = CURLM_CALL_MULTI_PERFORM;
1367 else if((CURLE_SEND_ERROR == easy->result) &&
1368 easy->easy_conn->bits.reuse) {
1370 * In this situation, a connection that we were trying to use
1371 * may have unexpectedly died. If possible, send the connection
1372 * back to the CONNECT phase so we can try again.
1374 char *newurl = NULL;
1375 followtype follow=FOLLOW_NONE;
1379 drc = Curl_retry_request(easy->easy_conn, &newurl);
1381 /* a failure here pretty much implies an out of memory */
1383 disconnect_conn = TRUE;
1386 retry = (newurl)?TRUE:FALSE;
1388 Curl_posttransfer(data);
1389 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1391 /* When set to retry the connection, we must to go back to
1392 * the CONNECT state */
1394 if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1395 follow = FOLLOW_RETRY;
1396 drc = Curl_follow(data, newurl, follow);
1397 if(drc == CURLE_OK) {
1398 multistate(easy, CURLM_STATE_CONNECT);
1399 result = CURLM_CALL_MULTI_PERFORM;
1400 easy->result = CURLE_OK;
1409 /* done didn't return OK or SEND_ERROR */
1415 /* Have error handler disconnect conn if we can't retry */
1416 disconnect_conn = TRUE;
1420 /* failure detected */
1421 Curl_posttransfer(data);
1422 Curl_done(&easy->easy_conn, easy->result, FALSE);
1423 disconnect_conn = TRUE;
1428 case CURLM_STATE_DOING:
1429 /* we continue DOING until the DO phase is complete */
1430 easy->result = Curl_protocol_doing(easy->easy_conn,
1432 if(CURLE_OK == easy->result) {
1434 /* after DO, go DO_DONE or DO_MORE */
1435 multistate(easy, easy->easy_conn->bits.do_more?
1436 CURLM_STATE_DO_MORE:
1437 CURLM_STATE_DO_DONE);
1438 result = CURLM_CALL_MULTI_PERFORM;
1439 } /* dophase_done */
1442 /* failure detected */
1443 Curl_posttransfer(data);
1444 Curl_done(&easy->easy_conn, easy->result, FALSE);
1445 disconnect_conn = TRUE;
1449 case CURLM_STATE_DO_MORE:
1451 * When we are connected, DO MORE and then go DO_DONE
1453 easy->result = Curl_do_more(easy->easy_conn, &dophase_done);
1455 /* No need to remove this handle from the send pipeline here since that
1456 is done in Curl_done() */
1457 if(CURLE_OK == easy->result) {
1459 multistate(easy, CURLM_STATE_DO_DONE);
1460 result = CURLM_CALL_MULTI_PERFORM;
1463 /* stay in DO_MORE */
1467 /* failure detected */
1468 Curl_posttransfer(data);
1469 Curl_done(&easy->easy_conn, easy->result, FALSE);
1470 disconnect_conn = TRUE;
1474 case CURLM_STATE_DO_DONE:
1475 /* Move ourselves from the send to recv pipeline */
1476 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1477 /* Check if we can move pending requests to send pipe */
1478 checkPendPipeline(easy->easy_conn);
1479 multistate(easy, CURLM_STATE_WAITPERFORM);
1480 result = CURLM_CALL_MULTI_PERFORM;
1483 case CURLM_STATE_WAITPERFORM:
1484 /* Wait for our turn to PERFORM */
1485 if(!easy->easy_conn->readchannel_inuse &&
1486 isHandleAtHead(data,
1487 easy->easy_conn->recv_pipe)) {
1488 /* Grab the channel */
1489 easy->easy_conn->readchannel_inuse = TRUE;
1490 multistate(easy, CURLM_STATE_PERFORM);
1491 result = CURLM_CALL_MULTI_PERFORM;
1495 infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %d athead %d\n",
1496 easy->easy_conn->connection_id,
1497 easy->easy_conn->recv_pipe->size,
1498 easy->easy_conn->readchannel_inuse?1:0,
1499 isHandleAtHead(data,
1500 easy->easy_conn->recv_pipe)?1:0);
1505 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1506 /* if both rates are within spec, resume transfer */
1507 if(Curl_pgrsUpdate(easy->easy_conn))
1508 easy->result = CURLE_ABORTED_BY_CALLBACK;
1510 easy->result = Curl_speedcheck(data, now);
1512 if(( (data->set.max_send_speed == 0) ||
1513 (data->progress.ulspeed < data->set.max_send_speed )) &&
1514 ( (data->set.max_recv_speed == 0) ||
1515 (data->progress.dlspeed < data->set.max_recv_speed)))
1516 multistate(easy, CURLM_STATE_PERFORM);
1519 case CURLM_STATE_PERFORM:
1521 char *newurl = NULL;
1524 /* check if over send speed */
1525 if((data->set.max_send_speed > 0) &&
1526 (data->progress.ulspeed > data->set.max_send_speed)) {
1529 multistate(easy, CURLM_STATE_TOOFAST);
1531 /* calculate upload rate-limitation timeout. */
1532 buffersize = (int)(data->set.buffer_size ?
1533 data->set.buffer_size : BUFSIZE);
1534 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1535 data->progress.ulspeed, buffersize);
1536 Curl_expire(data, timeout_ms);
1540 /* check if over recv speed */
1541 if((data->set.max_recv_speed > 0) &&
1542 (data->progress.dlspeed > data->set.max_recv_speed)) {
1545 multistate(easy, CURLM_STATE_TOOFAST);
1547 /* Calculate download rate-limitation timeout. */
1548 buffersize = (int)(data->set.buffer_size ?
1549 data->set.buffer_size : BUFSIZE);
1550 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1551 data->progress.dlspeed, buffersize);
1552 Curl_expire(data, timeout_ms);
1556 /* read/write data if it is ready to do so */
1557 easy->result = Curl_readwrite(easy->easy_conn, &done);
1561 if(!(k->keepon & KEEP_RECV)) {
1562 /* We're done receiving */
1563 easy->easy_conn->readchannel_inuse = FALSE;
1566 if(!(k->keepon & KEEP_SEND)) {
1567 /* We're done sending */
1568 easy->easy_conn->writechannel_inuse = FALSE;
1571 if(done || (easy->result == CURLE_RECV_ERROR)) {
1572 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1573 * condition and the server closed the re-used connection exactly when
1574 * we wanted to use it, so figure out if that is indeed the case.
1576 CURLcode ret = Curl_retry_request(easy->easy_conn, &newurl);
1578 retry = (newurl)?TRUE:FALSE;
1581 /* if we are to retry, set the result to OK */
1582 easy->result = CURLE_OK;
1587 * The transfer phase returned error, we mark the connection to get
1588 * closed to prevent being re-used. This is because we can't possibly
1589 * know if the connection is in a good shape or not now. Unless it is
1590 * a protocol which uses two "channels" like FTP, as then the error
1591 * happened in the data connection.
1594 if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL))
1595 easy->easy_conn->bits.close = TRUE;
1597 Curl_posttransfer(data);
1598 Curl_done(&easy->easy_conn, easy->result, FALSE);
1601 followtype follow=FOLLOW_NONE;
1603 /* call this even if the readwrite function returned error */
1604 Curl_posttransfer(data);
1606 /* we're no longer receiving */
1607 moveHandleFromRecvToDonePipeline(data,
1610 /* expire the new receiving pipeline head */
1611 if(easy->easy_conn->recv_pipe->head)
1612 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1614 /* Check if we can move pending requests to send pipe */
1615 checkPendPipeline(easy->easy_conn);
1617 /* When we follow redirects or is set to retry the connection, we must
1618 to go back to the CONNECT state */
1619 if(data->req.newurl || retry) {
1621 /* if the URL is a follow-location and not just a retried request
1622 then figure out the URL here */
1623 newurl = data->req.newurl;
1624 data->req.newurl = NULL;
1625 follow = FOLLOW_REDIR;
1628 follow = FOLLOW_RETRY;
1629 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1630 if(easy->result == CURLE_OK)
1631 easy->result = Curl_follow(data, newurl, follow);
1632 if(CURLE_OK == easy->result) {
1633 multistate(easy, CURLM_STATE_CONNECT);
1634 result = CURLM_CALL_MULTI_PERFORM;
1635 newurl = NULL; /* handed over the memory ownership to
1636 Curl_follow(), make sure we don't free() it
1641 /* after the transfer is done, go DONE */
1643 /* but first check to see if we got a location info even though we're
1644 not following redirects */
1645 if(data->req.location) {
1648 newurl = data->req.location;
1649 data->req.location = NULL;
1650 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1651 if(CURLE_OK == easy->result)
1652 newurl = NULL; /* allocation was handed over Curl_follow() */
1654 disconnect_conn = TRUE;
1657 multistate(easy, CURLM_STATE_DONE);
1658 result = CURLM_CALL_MULTI_PERFORM;
1667 case CURLM_STATE_DONE:
1669 if(easy->easy_conn) {
1670 /* Remove ourselves from the receive and done pipelines. Handle
1671 should be on one of these lists, depending upon how we got here. */
1672 Curl_removeHandleFromPipeline(data,
1673 easy->easy_conn->recv_pipe);
1674 Curl_removeHandleFromPipeline(data,
1675 easy->easy_conn->done_pipe);
1676 /* Check if we can move pending requests to send pipe */
1677 checkPendPipeline(easy->easy_conn);
1679 if(easy->easy_conn->bits.stream_was_rewound) {
1680 /* This request read past its response boundary so we quickly let
1681 the other requests consume those bytes since there is no
1682 guarantee that the socket will become active again */
1683 result = CURLM_CALL_MULTI_PERFORM;
1686 /* post-transfer command */
1687 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1689 * If there are other handles on the pipeline, Curl_done won't set
1690 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1691 * access free'd data, if the connection is free'd and the handle
1692 * removed before we perform the processing in CURLM_STATE_COMPLETED
1695 easy->easy_conn = NULL;
1698 if(data->set.wildcardmatch) {
1699 if(data->wildcard.state != CURLWC_DONE) {
1700 /* if a wildcard is set and we are not ending -> lets start again
1701 with CURLM_STATE_INIT */
1702 result = CURLM_CALL_MULTI_PERFORM;
1703 multistate(easy, CURLM_STATE_INIT);
1708 /* after we have DONE what we're supposed to do, go COMPLETED, and
1709 it doesn't matter what the Curl_done() returned! */
1710 multistate(easy, CURLM_STATE_COMPLETED);
1714 case CURLM_STATE_COMPLETED:
1715 /* this is a completed transfer, it is likely to still be connected */
1717 /* This node should be delinked from the list now and we should post
1718 an information message that we are complete. */
1720 /* Important: reset the conn pointer so that we don't point to memory
1721 that could be freed anytime */
1722 easy->easy_conn = NULL;
1724 Curl_expire(data, 0); /* stop all timers */
1727 case CURLM_STATE_MSGSENT:
1728 return CURLM_OK; /* do nothing */
1731 return CURLM_INTERNAL_ERROR;
1734 if(easy->state < CURLM_STATE_COMPLETED) {
1735 if(CURLE_OK != easy->result) {
1737 * If an error was returned, and we aren't in completed state now,
1738 * then we go to completed and consider this transfer aborted.
1741 /* NOTE: no attempt to disconnect connections must be made
1742 in the case blocks above - cleanup happens only here */
1744 data->state.pipe_broke = FALSE;
1746 if(easy->easy_conn) {
1747 /* if this has a connection, unsubscribe from the pipelines */
1748 easy->easy_conn->writechannel_inuse = FALSE;
1749 easy->easy_conn->readchannel_inuse = FALSE;
1750 Curl_removeHandleFromPipeline(data,
1751 easy->easy_conn->send_pipe);
1752 Curl_removeHandleFromPipeline(data,
1753 easy->easy_conn->recv_pipe);
1754 Curl_removeHandleFromPipeline(data,
1755 easy->easy_conn->done_pipe);
1756 /* Check if we can move pending requests to send pipe */
1757 checkPendPipeline(easy->easy_conn);
1759 if(disconnect_conn) {
1760 /* disconnect properly */
1761 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1763 /* This is where we make sure that the easy_conn pointer is reset.
1764 We don't have to do this in every case block above where a
1765 failure is detected */
1766 easy->easy_conn = NULL;
1769 else if(easy->state == CURLM_STATE_CONNECT) {
1770 /* Curl_connect() failed */
1771 (void)Curl_posttransfer(data);
1774 multistate(easy, CURLM_STATE_COMPLETED);
1776 /* if there's still a connection to use, call the progress function */
1777 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) {
1778 /* aborted due to progress callback return code must close the
1780 easy->easy_conn->bits.close = TRUE;
1782 /* if not yet in DONE state, go there, otherwise COMPLETED */
1783 multistate(easy, (easy->state < CURLM_STATE_DONE)?
1784 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
1785 result = CURLM_CALL_MULTI_PERFORM;
1788 } WHILE_FALSE; /* just to break out from! */
1790 if(CURLM_STATE_COMPLETED == easy->state) {
1791 /* now fill in the Curl_message with this info */
1794 msg->extmsg.msg = CURLMSG_DONE;
1795 msg->extmsg.easy_handle = data;
1796 msg->extmsg.data.result = easy->result;
1798 result = multi_addmsg(multi, msg);
1800 multistate(easy, CURLM_STATE_MSGSENT);
1807 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1809 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1810 struct Curl_one_easy *easy;
1811 CURLMcode returncode=CURLM_OK;
1812 struct Curl_tree *t;
1813 struct timeval now = Curl_tvnow();
1815 if(!GOOD_MULTI_HANDLE(multi))
1816 return CURLM_BAD_HANDLE;
1818 easy=multi->easy.next;
1819 while(easy != &multi->easy) {
1821 struct WildcardData *wc = &easy->easy_handle->wildcard;
1823 if(easy->easy_handle->set.wildcardmatch) {
1825 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1827 return CURLM_OUT_OF_MEMORY;
1832 result = multi_runsingle(multi, now, easy);
1833 while(CURLM_CALL_MULTI_PERFORM == result);
1835 if(easy->easy_handle->set.wildcardmatch) {
1836 /* destruct wildcard structures if it is needed */
1837 if(wc->state == CURLWC_DONE || result)
1838 Curl_wildcard_dtor(wc);
1842 returncode = result;
1844 easy = easy->next; /* operate on next handle */
1848 * Simply remove all expired timers from the splay since handles are dealt
1849 * with unconditionally by this function and curl_multi_timeout() requires
1850 * that already passed/handled expire times are removed from the splay.
1852 * It is important that the 'now' value is set at the entry of this function
1853 * and not for the current time as it may have ticked a little while since
1854 * then and then we risk this loop to remove timers that actually have not
1858 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1860 /* the removed may have another timeout in queue */
1861 (void)add_next_timeout(now, multi, t->payload);
1865 *running_handles = multi->num_alive;
1867 if(CURLM_OK >= returncode)
1868 update_timer(multi);
1873 static void close_all_connections(struct Curl_multi *multi)
1875 struct connectdata *conn;
1877 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1879 conn->data = multi->closure_handle;
1881 /* This will remove the connection from the cache */
1882 (void)Curl_disconnect(conn, FALSE);
1884 conn = Curl_conncache_find_first_connection(multi->conn_cache);
1888 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1890 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1891 struct Curl_one_easy *easy;
1892 struct Curl_one_easy *nexteasy;
1894 if(GOOD_MULTI_HANDLE(multi)) {
1895 multi->type = 0; /* not good anymore */
1897 /* Close all the connections in the connection cache */
1898 close_all_connections(multi);
1900 Curl_close(multi->closure_handle);
1901 multi->closure_handle = NULL;
1903 Curl_hash_destroy(multi->sockhash);
1904 multi->sockhash = NULL;
1906 Curl_conncache_destroy(multi->conn_cache);
1907 multi->conn_cache = NULL;
1909 /* remove the pending list of messages */
1910 Curl_llist_destroy(multi->msglist, NULL);
1911 multi->msglist = NULL;
1913 /* remove all easy handles */
1914 easy = multi->easy.next;
1915 while(easy != &multi->easy) {
1916 nexteasy=easy->next;
1917 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1918 /* clear out the usage of the shared DNS cache */
1919 Curl_hostcache_clean(easy->easy_handle);
1920 easy->easy_handle->dns.hostcache = NULL;
1921 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1924 /* Clear the pointer to the connection cache */
1925 easy->easy_handle->state.conn_cache = NULL;
1927 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1933 Curl_hash_destroy(multi->hostcache);
1934 multi->hostcache = NULL;
1941 return CURLM_BAD_HANDLE;
1945 * curl_multi_info_read()
1947 * This function is the primary way for a multi/multi_socket application to
1948 * figure out if a transfer has ended. We MUST make this function as fast as
1949 * possible as it will be polled frequently and we MUST NOT scan any lists in
1950 * here to figure out things. We must scale fine to thousands of handles and
1951 * beyond. The current design is fully O(1).
1954 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1956 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1957 struct Curl_message *msg;
1959 *msgs_in_queue = 0; /* default to none */
1961 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1962 /* there is one or more messages in the list */
1963 struct curl_llist_element *e;
1965 /* extract the head of the list to return */
1966 e = multi->msglist->head;
1970 /* remove the extracted entry */
1971 Curl_llist_remove(multi->msglist, e, NULL);
1973 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1975 return &msg->extmsg;
1982 * singlesocket() checks what sockets we deal with and their "action state"
1983 * and if we have a different state in any of those sockets from last time we
1984 * call the callback accordingly.
1986 static void singlesocket(struct Curl_multi *multi,
1987 struct Curl_one_easy *easy)
1989 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1991 struct Curl_sh_entry *entry;
1994 unsigned int curraction;
1995 struct Curl_one_easy *easy_by_hash;
1996 bool remove_sock_from_hash;
1998 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1999 socks[i] = CURL_SOCKET_BAD;
2001 /* Fill in the 'current' struct with the state as it is now: what sockets to
2002 supervise and for what actions */
2003 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
2005 /* We have 0 .. N sockets already and we get to know about the 0 .. M
2006 sockets we should have from now on. Detect the differences, remove no
2007 longer supervised ones and add new ones */
2009 /* walk over the sockets we got right now */
2010 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
2011 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2013 int action = CURL_POLL_NONE;
2017 /* get it from the hash */
2018 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2020 if(curraction & GETSOCK_READSOCK(i))
2021 action |= CURL_POLL_IN;
2022 if(curraction & GETSOCK_WRITESOCK(i))
2023 action |= CURL_POLL_OUT;
2026 /* yeps, already present so check if it has the same action set */
2027 if(entry->action == action)
2028 /* same, continue */
2032 /* this is a socket we didn't have before, add it! */
2033 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
2039 /* we know (entry != NULL) at this point, see the logic above */
2040 if(multi->socket_cb)
2041 multi->socket_cb(easy->easy_handle,
2044 multi->socket_userp,
2047 entry->action = action; /* store the current action state */
2050 num = i; /* number of sockets */
2052 /* when we've walked over all the sockets we should have right now, we must
2053 make sure to detect sockets that are removed */
2054 for(i=0; i< easy->numsocks; i++) {
2056 s = easy->sockets[i];
2057 for(j=0; j<num; j++) {
2059 /* this is still supervised */
2060 s = CURL_SOCKET_BAD;
2064 if(s != CURL_SOCKET_BAD) {
2066 /* this socket has been removed. Tell the app to remove it */
2067 remove_sock_from_hash = TRUE;
2069 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2071 /* check if the socket to be removed serves a connection which has
2072 other easy-s in a pipeline. In this case the socket should not be
2074 struct connectdata *easy_conn;
2076 easy_by_hash = entry->easy->multi_pos;
2077 easy_conn = easy_by_hash->easy_conn;
2079 if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
2080 /* the handle should not be removed from the pipe yet */
2081 remove_sock_from_hash = FALSE;
2083 /* Update the sockhash entry to instead point to the next in line
2084 for the recv_pipe, or the first (in case this particular easy
2086 if(entry->easy == easy->easy_handle) {
2087 if(isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
2088 entry->easy = easy_conn->recv_pipe->head->next->ptr;
2090 entry->easy = easy_conn->recv_pipe->head->ptr;
2093 if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
2094 /* the handle should not be removed from the pipe yet */
2095 remove_sock_from_hash = FALSE;
2097 /* Update the sockhash entry to instead point to the next in line
2098 for the send_pipe, or the first (in case this particular easy
2100 if(entry->easy == easy->easy_handle) {
2101 if(isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
2102 entry->easy = easy_conn->send_pipe->head->next->ptr;
2104 entry->easy = easy_conn->send_pipe->head->ptr;
2107 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
2108 when action will be asked on the socket (see multi_socket()), the
2109 head of the correct pipe will be taken according to the
2114 /* just a precaution, this socket really SHOULD be in the hash already
2115 but in case it isn't, we don't have to tell the app to remove it
2116 either since it never got to know about it */
2117 remove_sock_from_hash = FALSE;
2119 if(remove_sock_from_hash) {
2120 /* in this case 'entry' is always non-NULL */
2121 if(multi->socket_cb)
2122 multi->socket_cb(easy->easy_handle,
2125 multi->socket_userp,
2127 sh_delentry(multi->sockhash, s);
2133 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2134 easy->numsocks = num;
2138 * add_next_timeout()
2140 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2141 * when it has just been removed from the splay tree because the timeout has
2142 * expired. This function is then to advance in the list to pick the next
2143 * timeout to use (skip the already expired ones) and add this node back to
2144 * the splay tree again.
2146 * The splay tree only has each sessionhandle as a single node and the nearest
2147 * timeout is used to sort it on.
2149 static CURLMcode add_next_timeout(struct timeval now,
2150 struct Curl_multi *multi,
2151 struct SessionHandle *d)
2153 struct timeval *tv = &d->state.expiretime;
2154 struct curl_llist *list = d->state.timeoutlist;
2155 struct curl_llist_element *e;
2157 /* move over the timeout list for this specific handle and remove all
2158 timeouts that are now passed tense and store the next pending
2160 for(e = list->head; e; ) {
2161 struct curl_llist_element *n = e->next;
2162 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2164 /* remove outdated entry */
2165 Curl_llist_remove(list, e, NULL);
2167 /* the list is sorted so get out on the first mismatch */
2173 /* clear the expire times within the handles that we remove from the
2179 /* copy the first entry to 'tv' */
2180 memcpy(tv, e->ptr, sizeof(*tv));
2182 /* remove first entry from list */
2183 Curl_llist_remove(list, e, NULL);
2185 /* insert this node again into the splay */
2186 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2187 &d->state.timenode);
2193 static CURLMcode multi_socket(struct Curl_multi *multi,
2197 int *running_handles)
2199 CURLMcode result = CURLM_OK;
2200 struct SessionHandle *data = NULL;
2201 struct Curl_tree *t;
2202 struct timeval now = Curl_tvnow();
2205 struct Curl_one_easy *easyp;
2206 /* *perform() deals with running_handles on its own */
2207 result = curl_multi_perform(multi, running_handles);
2209 /* walk through each easy handle and do the socket state change magic
2211 easyp=multi->easy.next;
2212 while(easyp != &multi->easy) {
2213 singlesocket(multi, easyp);
2214 easyp = easyp->next;
2217 /* or should we fall-through and do the timer-based stuff? */
2220 else if(s != CURL_SOCKET_TIMEOUT) {
2222 struct Curl_sh_entry *entry =
2223 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2226 /* Unmatched socket, we can't act on it but we ignore this fact. In
2227 real-world tests it has been proved that libevent can in fact give
2228 the application actions even though the socket was just previously
2229 asked to get removed, so thus we better survive stray socket actions
2230 and just move on. */
2235 if(data->magic != CURLEASY_MAGIC_NUMBER)
2236 /* bad bad bad bad bad bad bad */
2237 return CURLM_INTERNAL_ERROR;
2239 /* If the pipeline is enabled, take the handle which is in the head of
2240 the pipeline. If we should write into the socket, take the send_pipe
2241 head. If we should read from the socket, take the recv_pipe head. */
2242 if(data->set.one_easy->easy_conn) {
2243 if((ev_bitmask & CURL_POLL_OUT) &&
2244 data->set.one_easy->easy_conn->send_pipe &&
2245 data->set.one_easy->easy_conn->send_pipe->head)
2246 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2247 else if((ev_bitmask & CURL_POLL_IN) &&
2248 data->set.one_easy->easy_conn->recv_pipe &&
2249 data->set.one_easy->easy_conn->recv_pipe->head)
2250 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2253 if(data->set.one_easy->easy_conn &&
2254 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2255 /* set socket event bitmask if they're not locked */
2256 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2259 result = multi_runsingle(multi, now, data->set.one_easy);
2260 while(CURLM_CALL_MULTI_PERFORM == result);
2262 if(data->set.one_easy->easy_conn &&
2263 !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
2264 /* clear the bitmask only if not locked */
2265 data->set.one_easy->easy_conn->cselect_bits = 0;
2267 if(CURLM_OK >= result)
2268 /* get the socket(s) and check if the state has been changed since
2270 singlesocket(multi, data->set.one_easy);
2272 /* Now we fall-through and do the timer-based stuff, since we don't want
2273 to force the user to have to deal with timeouts as long as at least
2274 one connection in fact has traffic. */
2276 data = NULL; /* set data to NULL again to avoid calling
2277 multi_runsingle() in case there's no need to */
2281 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2282 triggered too early */
2283 if(now.tv_usec >= 1000000) {
2285 now.tv_usec -= 1000000;
2289 * The loop following here will go on as long as there are expire-times left
2290 * to process in the splay and 'data' will be re-assigned for every expired
2291 * handle we deal with.
2294 /* the first loop lap 'data' can be NULL */
2297 result = multi_runsingle(multi, now, data->set.one_easy);
2298 while(CURLM_CALL_MULTI_PERFORM == result);
2300 if(CURLM_OK >= result)
2301 /* get the socket(s) and check if the state has been changed since
2303 singlesocket(multi, data->set.one_easy);
2306 /* Check if there's one (more) expired timer to deal with! This function
2307 extracts a matching node if there is one */
2309 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2311 data = t->payload; /* assign this for next loop */
2312 (void)add_next_timeout(now, multi, t->payload);
2317 *running_handles = multi->num_alive;
2321 #undef curl_multi_setopt
2322 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2323 CURLMoption option, ...)
2325 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2326 CURLMcode res = CURLM_OK;
2329 if(!GOOD_MULTI_HANDLE(multi))
2330 return CURLM_BAD_HANDLE;
2332 va_start(param, option);
2335 case CURLMOPT_SOCKETFUNCTION:
2336 multi->socket_cb = va_arg(param, curl_socket_callback);
2338 case CURLMOPT_SOCKETDATA:
2339 multi->socket_userp = va_arg(param, void *);
2341 case CURLMOPT_PIPELINING:
2342 multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2344 case CURLMOPT_TIMERFUNCTION:
2345 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2347 case CURLMOPT_TIMERDATA:
2348 multi->timer_userp = va_arg(param, void *);
2350 case CURLMOPT_MAXCONNECTS:
2351 multi->maxconnects = va_arg(param, long);
2354 res = CURLM_UNKNOWN_OPTION;
2361 /* we define curl_multi_socket() in the public multi.h header */
2362 #undef curl_multi_socket
2364 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2365 int *running_handles)
2367 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2368 0, running_handles);
2369 if(CURLM_OK >= result)
2370 update_timer((struct Curl_multi *)multi_handle);
2374 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2375 int ev_bitmask, int *running_handles)
2377 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2378 ev_bitmask, running_handles);
2379 if(CURLM_OK >= result)
2380 update_timer((struct Curl_multi *)multi_handle);
2384 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2387 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2388 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2389 if(CURLM_OK >= result)
2390 update_timer((struct Curl_multi *)multi_handle);
2394 static CURLMcode multi_timeout(struct Curl_multi *multi,
2397 static struct timeval tv_zero = {0,0};
2399 if(multi->timetree) {
2400 /* we have a tree of expire times */
2401 struct timeval now = Curl_tvnow();
2403 /* splay the lowest to the bottom */
2404 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2406 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2407 /* some time left before expiration */
2408 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2411 * Since we only provide millisecond resolution on the returned value
2412 * and the diff might be less than one millisecond here, we don't
2413 * return zero as that may cause short bursts of busyloops on fast
2414 * processors while the diff is still present but less than one
2415 * millisecond! instead we return 1 until the time is ripe.
2420 /* 0 means immediately */
2429 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2432 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2434 /* First, make some basic checks that the CURLM handle is a good handle */
2435 if(!GOOD_MULTI_HANDLE(multi))
2436 return CURLM_BAD_HANDLE;
2438 return multi_timeout(multi, timeout_ms);
2442 * Tell the application it should update its timers, if it subscribes to the
2443 * update timer callback.
2445 static int update_timer(struct Curl_multi *multi)
2449 if(!multi->timer_cb)
2451 if(multi_timeout(multi, &timeout_ms)) {
2454 if(timeout_ms < 0) {
2455 static const struct timeval none={0,0};
2456 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2457 multi->timer_lastcall = none;
2458 /* there's no timeout now but there was one previously, tell the app to
2460 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2465 /* When multi_timeout() is done, multi->timetree points to the node with the
2466 * timeout we got the (relative) time-out time for. We can thus easily check
2467 * if this is the same (fixed) time as we got in a previous call and then
2468 * avoid calling the callback again. */
2469 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2472 multi->timer_lastcall = multi->timetree->key;
2474 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2477 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2478 struct connectdata *conn)
2480 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2481 struct curl_llist_element *sendhead = conn->send_pipe->head;
2482 struct curl_llist *pipeline;
2485 if(!Curl_isPipeliningEnabled(handle) ||
2487 pipeline = conn->send_pipe;
2489 if(conn->server_supports_pipelining &&
2490 pipeLen < MAX_PIPELINE_LENGTH)
2491 pipeline = conn->send_pipe;
2493 pipeline = conn->pend_pipe;
2496 rc = Curl_addHandleToPipeline(handle, pipeline);
2498 if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2499 /* this is a new one as head, expire it */
2500 conn->writechannel_inuse = FALSE; /* not in use yet */
2502 infof(conn->data, "%p is at send pipe head!\n",
2503 conn->send_pipe->head->ptr);
2505 Curl_expire(conn->send_pipe->head->ptr, 1);
2511 static int checkPendPipeline(struct connectdata *conn)
2514 struct curl_llist_element *sendhead = conn->send_pipe->head;
2516 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2517 if(conn->server_supports_pipelining || pipeLen == 0) {
2518 struct curl_llist_element *curr = conn->pend_pipe->head;
2519 const size_t maxPipeLen =
2520 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2522 while(pipeLen < maxPipeLen && curr) {
2523 Curl_llist_move(conn->pend_pipe, curr,
2524 conn->send_pipe, conn->send_pipe->tail);
2525 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2526 ++result; /* count how many handles we moved */
2527 curr = conn->pend_pipe->head;
2533 conn->now = Curl_tvnow();
2534 /* something moved, check for a new send pipeline leader */
2535 if(sendhead != conn->send_pipe->head) {
2536 /* this is a new one as head, expire it */
2537 conn->writechannel_inuse = FALSE; /* not in use yet */
2539 infof(conn->data, "%p is at send pipe head!\n",
2540 conn->send_pipe->head->ptr);
2542 Curl_expire(conn->send_pipe->head->ptr, 1);
2549 /* Move this transfer from the sending list to the receiving list.
2551 Pay special attention to the new sending list "leader" as it needs to get
2552 checked to update what sockets it acts on.
2555 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2556 struct connectdata *conn)
2558 struct curl_llist_element *curr;
2560 curr = conn->send_pipe->head;
2562 if(curr->ptr == handle) {
2563 Curl_llist_move(conn->send_pipe, curr,
2564 conn->recv_pipe, conn->recv_pipe->tail);
2566 if(conn->send_pipe->head) {
2567 /* Since there's a new easy handle at the start of the send pipeline,
2568 set its timeout value to 1ms to make it trigger instantly */
2569 conn->writechannel_inuse = FALSE; /* not used now */
2571 infof(conn->data, "%p is at send pipe head B!\n",
2572 conn->send_pipe->head->ptr);
2574 Curl_expire(conn->send_pipe->head->ptr, 1);
2577 /* The receiver's list is not really interesting here since either this
2578 handle is now first in the list and we'll deal with it soon, or
2579 another handle is already first and thus is already taken care of */
2581 break; /* we're done! */
2587 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2588 struct connectdata *conn)
2590 struct curl_llist_element *curr;
2592 curr = conn->recv_pipe->head;
2594 if(curr->ptr == handle) {
2595 Curl_llist_move(conn->recv_pipe, curr,
2596 conn->done_pipe, conn->done_pipe->tail);
2602 static bool isHandleAtHead(struct SessionHandle *handle,
2603 struct curl_llist *pipeline)
2605 struct curl_llist_element *curr = pipeline->head;
2607 return (curr->ptr == handle) ? TRUE : FALSE;
2613 * multi_freetimeout()
2615 * Callback used by the llist system when a single timeout list entry is
2618 static void multi_freetimeout(void *user, void *entryptr)
2622 /* the entry was plain malloc()'ed */
2627 * multi_addtimeout()
2629 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2630 * of list is always the timeout nearest in time.
2634 multi_addtimeout(struct curl_llist *timeoutlist,
2635 struct timeval *stamp)
2637 struct curl_llist_element *e;
2638 struct timeval *timedup;
2639 struct curl_llist_element *prev = NULL;
2641 timedup = malloc(sizeof(*timedup));
2643 return CURLM_OUT_OF_MEMORY;
2645 /* copy the timestamp */
2646 memcpy(timedup, stamp, sizeof(*timedup));
2648 if(Curl_llist_count(timeoutlist)) {
2649 /* find the correct spot in the list */
2650 for(e = timeoutlist->head; e; e = e->next) {
2651 struct timeval *checktime = e->ptr;
2652 long diff = curlx_tvdiff(*checktime, *timedup);
2660 this is the first timeout on the list */
2662 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2664 return CURLM_OUT_OF_MEMORY;
2673 * given a number of milliseconds from now to use to set the 'act before
2674 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2676 * Note that the timeout will be added to a queue of timeouts if it defines a
2677 * moment in time that is later than the current head of queue.
2679 * Pass zero to clear all timeout values for this handle.
2681 void Curl_expire(struct SessionHandle *data, long milli)
2683 struct Curl_multi *multi = data->multi;
2684 struct timeval *nowp = &data->state.expiretime;
2687 /* this is only interesting for multi-interface using libcurl, and only
2688 while there is still a multi interface struct remaining! */
2693 /* No timeout, clear the time data. */
2694 if(nowp->tv_sec || nowp->tv_usec) {
2695 /* Since this is an cleared time, we must remove the previous entry from
2697 struct curl_llist *list = data->state.timeoutlist;
2699 rc = Curl_splayremovebyaddr(multi->timetree,
2700 &data->state.timenode,
2703 infof(data, "Internal error clearing splay node = %d\n", rc);
2705 /* flush the timeout list too */
2706 while(list->size > 0)
2707 Curl_llist_remove(list, list->tail, NULL);
2710 infof(data, "Expire cleared\n");
2720 set.tv_sec += milli/1000;
2721 set.tv_usec += (milli%1000)*1000;
2723 if(set.tv_usec >= 1000000) {
2725 set.tv_usec -= 1000000;
2728 if(nowp->tv_sec || nowp->tv_usec) {
2729 /* This means that the struct is added as a node in the splay tree.
2730 Compare if the new time is earlier, and only remove-old/add-new if it
2732 long diff = curlx_tvdiff(set, *nowp);
2734 /* the new expire time was later so just add it to the queue
2736 multi_addtimeout(data->state.timeoutlist, &set);
2740 /* the new time is newer than the presently set one, so add the current
2741 to the queue and update the head */
2742 multi_addtimeout(data->state.timeoutlist, nowp);
2744 /* Since this is an updated time, we must remove the previous entry from
2745 the splay tree first and then re-add the new value */
2746 rc = Curl_splayremovebyaddr(multi->timetree,
2747 &data->state.timenode,
2750 infof(data, "Internal error removing splay node = %d\n", rc);
2754 data->state.timenode.payload = data;
2755 multi->timetree = Curl_splayinsert(*nowp,
2757 &data->state.timenode);
2760 Curl_splayprint(multi->timetree, 0, TRUE);
2764 CURLMcode curl_multi_assign(CURLM *multi_handle,
2765 curl_socket_t s, void *hashp)
2767 struct Curl_sh_entry *there = NULL;
2768 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2770 if(s != CURL_SOCKET_BAD)
2771 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2774 return CURLM_BAD_SOCKET;
2776 there->socketp = hashp;
2782 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2784 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2785 struct Curl_one_easy *easy;
2787 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2788 multi->num_easy, multi->num_alive);
2789 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2790 if(easy->state < CURLM_STATE_COMPLETED) {
2791 /* only display handles that are not completed */
2792 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2793 (void *)easy->easy_handle,
2794 statename[easy->state], easy->numsocks);
2795 for(i=0; i < easy->numsocks; i++) {
2796 curl_socket_t s = easy->sockets[i];
2797 struct Curl_sh_entry *entry =
2798 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2800 fprintf(stderr, "%d ", (int)s);
2802 fprintf(stderr, "INTERNAL CONFUSION\n");
2805 fprintf(stderr, "[%s %s] ",
2806 entry->action&CURL_POLL_IN?"RECVING":"",
2807 entry->action&CURL_POLL_OUT?"SENDING":"");
2810 fprintf(stderr, "\n");