1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2010, 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 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
32 #include <curl/curl.h>
46 #define _MPRINTF_REPLACE /* use our functions only */
47 #include <curl/mprintf.h>
49 #include "curl_memory.h"
50 /* The last #include file should be: */
54 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
55 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
56 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
58 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
59 #define CURL_SOCKET_HASH_TABLE_SIZE 911
63 /* the 'CURLMsg' is the part that is visible to the external user */
64 struct CURLMsg extmsg;
67 /* NOTE: if you add a state here, add the name to the statename[] array as
71 CURLM_STATE_INIT, /* 0 - start in this state */
72 CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */
73 CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
74 CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
75 CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
76 CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
78 CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */
79 CURLM_STATE_DO, /* 7 - start send off the request (part 1) */
80 CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */
81 CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */
82 CURLM_STATE_DO_DONE, /* 10 - done sending off request */
83 CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
84 CURLM_STATE_PERFORM, /* 12 - transfer data */
85 CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
86 CURLM_STATE_DONE, /* 14 - post data transfer operation */
87 CURLM_STATE_COMPLETED, /* 15 - operation complete */
88 CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
89 CURLM_STATE_LAST /* 17 - not a true state, never use this */
92 /* we support N sockets per easy handle. Set the corresponding bit to what
93 action we should wait for */
94 #define MAX_SOCKSPEREASYHANDLE 5
95 #define GETSOCK_READABLE (0x00ff)
96 #define GETSOCK_WRITABLE (0xff00)
99 struct closure *next; /* a simple one-way list of structs */
100 struct SessionHandle *easy_handle;
103 struct Curl_one_easy {
104 /* first, two fields for the linked list of these */
105 struct Curl_one_easy *next;
106 struct Curl_one_easy *prev;
108 struct SessionHandle *easy_handle; /* the easy handle for this unit */
109 struct connectdata *easy_conn; /* the "unit's" connection */
111 CURLMstate state; /* the handle's state */
112 CURLcode result; /* previous result */
114 struct Curl_message msg; /* A single posted message. */
116 /* Array with the plain socket numbers this handle takes care of, in no
117 particular order. Note that all sockets are added to the sockhash, where
118 the state etc are also kept. This array is mostly used to detect when a
119 socket is to be removed from the hash. See singlesocket(). */
120 curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
124 #define CURL_MULTI_HANDLE 0x000bab1e
126 #define GOOD_MULTI_HANDLE(x) \
127 ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
128 #define GOOD_EASY_HANDLE(x) \
129 (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)
131 /* This is the struct known as CURLM on the outside */
133 /* First a simple identifier to easier detect if a user mix up
134 this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
137 /* We have a linked list with easy handles */
138 struct Curl_one_easy easy;
140 int num_easy; /* amount of entries in the linked list above. */
141 int num_alive; /* amount of easy handles that are added but have not yet
142 reached COMPLETE state */
144 struct curl_llist *msglist; /* a list of messages from completed transfers */
146 /* callback function and user data pointer for the *socket() API */
147 curl_socket_callback socket_cb;
151 struct curl_hash *hostcache;
153 /* timetree points to the splay-tree of time nodes to figure out expire
154 times of all currently set timers */
155 struct Curl_tree *timetree;
157 /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
158 the pluralis form, there can be more than one easy handle waiting on the
159 same actual socket) */
160 struct curl_hash *sockhash;
162 /* Whether pipelining is enabled for this multi handle */
163 bool pipelining_enabled;
165 /* shared connection cache */
166 struct conncache *connc;
167 long maxconnects; /* if >0, a fixed limit of the maximum number of entries
168 we're allowed to grow the connection cache to */
170 /* list of easy handles kept around for doing nice connection closures */
171 struct closure *closure;
173 /* timer callback and user data pointer for the *socket() API */
174 curl_multi_timer_callback timer_cb;
176 struct timeval timer_lastcall; /* the fixed time for the timeout for the
180 static void multi_connc_remove_handle(struct Curl_multi *multi,
181 struct SessionHandle *data);
182 static void singlesocket(struct Curl_multi *multi,
183 struct Curl_one_easy *easy);
184 static CURLMcode add_closure(struct Curl_multi *multi,
185 struct SessionHandle *data);
186 static int update_timer(struct Curl_multi *multi);
188 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
189 struct connectdata *conn);
190 static int checkPendPipeline(struct connectdata *conn);
191 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
192 struct connectdata *conn);
193 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
194 struct connectdata *conn);
195 static bool isHandleAtHead(struct SessionHandle *handle,
196 struct curl_llist *pipeline);
197 static CURLMcode add_next_timeout(struct timeval now,
198 struct Curl_multi *multi,
199 struct SessionHandle *d);
202 static const char * const statename[]={
223 static void multi_freetimeout(void *a, void *b);
225 /* always use this function to change state, to make debugging easier */
226 static void multistate(struct Curl_one_easy *easy, CURLMstate state)
229 long connectindex = -5000;
231 CURLMstate oldstate = easy->state;
233 if(oldstate == state)
234 /* don't bother when the new state is the same as the old state */
240 if(easy->easy_conn) {
241 if(easy->state > CURLM_STATE_CONNECT &&
242 easy->state < CURLM_STATE_COMPLETED)
243 connectindex = easy->easy_conn->connectindex;
245 infof(easy->easy_handle,
246 "STATE: %s => %s handle %p; (connection #%ld) \n",
247 statename[oldstate], statename[easy->state],
248 (char *)easy, connectindex);
251 if(state == CURLM_STATE_COMPLETED)
252 /* changing to COMPLETED means there's one less easy handle 'alive' */
253 easy->easy_handle->multi->num_alive--;
257 * We add one of these structs to the sockhash for a particular socket
260 struct Curl_sh_entry {
261 struct SessionHandle *easy;
263 int action; /* what action READ/WRITE this socket waits for */
264 curl_socket_t socket; /* mainly to ease debugging */
265 void *socketp; /* settable by users with curl_multi_assign() */
267 /* bits for 'action' having no bits means this socket is not expecting any
272 /* make sure this socket is present in the hash for this handle */
273 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
275 struct SessionHandle *data)
277 struct Curl_sh_entry *there =
278 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
279 struct Curl_sh_entry *check;
282 /* it is present, return fine */
285 /* not present, add it */
286 check = calloc(1, sizeof(struct Curl_sh_entry));
288 return NULL; /* major failure */
292 /* make/add new hash entry */
293 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
295 return NULL; /* major failure */
298 return check; /* things are good in sockhash land */
302 /* delete the given socket + handle from the hash */
303 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
305 struct Curl_sh_entry *there =
306 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
309 /* this socket is in the hash */
310 /* We remove the hash entry. (This'll end up in a call to
312 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
317 * free a sockhash entry
319 static void sh_freeentry(void *freethis)
321 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
327 static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
329 (void) k1_len; (void) k2_len;
331 return (*((int* ) k1)) == (*((int* ) k2));
334 static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
336 int fd = * ((int* ) key);
339 return (fd % (int)slots_num);
343 * sh_init() creates a new socket hash and returns the handle for it.
345 * Quote from README.multi_socket:
347 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
348 * is somewhat of a bottle neck. Its current implementation may be a bit too
349 * limiting. It simply has a fixed-size array, and on each entry in the array
350 * it has a linked list with entries. So the hash only checks which list to
351 * scan through. The code I had used so for used a list with merely 7 slots
352 * (as that is what the DNS hash uses) but with 7000 connections that would
353 * make an average of 1000 nodes in each list to run through. I upped that to
354 * 97 slots (I believe a prime is suitable) and noticed a significant speed
355 * increase. I need to reconsider the hash implementation or use a rather
356 * large default value like this. At 9000 connections I was still below 10us
360 static struct curl_hash *sh_init(void)
362 return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
369 * Called when a transfer is completed. Adds the given msg pointer to
370 * the list kept in the multi handle.
372 static CURLMcode multi_addmsg(struct Curl_multi *multi,
373 struct Curl_message *msg)
375 if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
376 return CURLM_OUT_OF_MEMORY;
384 * Callback used by the llist system when a single list entry is destroyed.
386 static void multi_freeamsg(void *a, void *b)
393 CURLM *curl_multi_init(void)
395 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
400 multi->type = CURL_MULTI_HANDLE;
402 multi->hostcache = Curl_mk_dnscache();
403 if(!multi->hostcache)
406 multi->sockhash = sh_init();
410 multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1L);
414 multi->msglist = Curl_llist_alloc(multi_freeamsg);
418 /* Let's make the doubly-linked list a circular list. This makes
419 the linked list code simpler and allows inserting at the end
420 with less work (we didn't keep a tail pointer before). */
421 multi->easy.next = &multi->easy;
422 multi->easy.prev = &multi->easy;
424 return (CURLM *) multi;
428 Curl_hash_destroy(multi->sockhash);
430 Curl_hash_destroy(multi->hostcache);
432 Curl_rm_connc(multi->connc);
438 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
441 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
442 struct Curl_one_easy *easy;
444 struct closure *prev=NULL;
445 struct SessionHandle *data = easy_handle;
447 /* First, make some basic checks that the CURLM handle is a good handle */
448 if(!GOOD_MULTI_HANDLE(multi))
449 return CURLM_BAD_HANDLE;
451 /* Verify that we got a somewhat good easy handle too */
452 if(!GOOD_EASY_HANDLE(easy_handle))
453 return CURLM_BAD_EASY_HANDLE;
455 /* Prevent users to add the same handle more than once! */
456 if(((struct SessionHandle *)easy_handle)->multi)
457 /* possibly we should create a new unique error code for this condition */
458 return CURLM_BAD_EASY_HANDLE;
460 data->state.timeoutlist = Curl_llist_alloc(multi_freetimeout);
461 if(!data->state.timeoutlist)
462 return CURLM_OUT_OF_MEMORY;
464 /* Now, time to add an easy handle to the multi stack */
465 easy = calloc(1, sizeof(struct Curl_one_easy));
467 return CURLM_OUT_OF_MEMORY;
471 struct closure *next = cl->next;
472 if(cl->easy_handle == (struct SessionHandle *)easy_handle) {
473 /* remove this handle from the closure list */
478 multi->closure = next;
479 break; /* no need to continue since this handle can only be present once
486 /* set the easy handle */
487 easy->easy_handle = easy_handle;
488 multistate(easy, CURLM_STATE_INIT);
490 /* set the back pointer to one_easy to assist in removal */
491 easy->easy_handle->multi_pos = easy;
493 /* for multi interface connections, we share DNS cache automatically if the
494 easy handle's one is currently private. */
495 if(easy->easy_handle->dns.hostcache &&
496 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
497 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
498 easy->easy_handle->dns.hostcache = NULL;
499 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
502 if(!easy->easy_handle->dns.hostcache ||
503 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
504 easy->easy_handle->dns.hostcache = multi->hostcache;
505 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
508 if(easy->easy_handle->state.connc) {
509 if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) {
510 /* kill old private version */
511 Curl_rm_connc(easy->easy_handle->state.connc);
512 /* point out our shared one instead */
513 easy->easy_handle->state.connc = multi->connc;
515 /* else it is already using multi? */
518 /* point out our shared one */
519 easy->easy_handle->state.connc = multi->connc;
521 /* Make sure the type is setup correctly */
522 easy->easy_handle->state.connc->type = CONNCACHE_MULTI;
524 /* This adds the new entry at the back of the list
525 to try and maintain a FIFO queue so the pipelined
526 requests are in order. */
528 /* We add this new entry last in the list. We make our 'next' point to the
529 'first' struct and our 'prev' point to the previous 'prev' */
530 easy->next = &multi->easy;
531 easy->prev = multi->easy.prev;
533 /* make 'easy' the last node in the chain */
534 multi->easy.prev = easy;
536 /* if there was a prev node, make sure its 'next' pointer links to
538 easy->prev->next = easy;
540 Curl_easy_addmulti(easy_handle, multi_handle);
542 /* make the SessionHandle struct refer back to this struct */
543 easy->easy_handle->set.one_easy = easy;
545 /* Set the timeout for this handle to expire really soon so that it will
546 be taken care of even when this handle is added in the midst of operation
547 when only the curl_multi_socket() API is used. During that flow, only
548 sockets that time-out or have actions will be dealt with. Since this
549 handle has no action yet, we make sure it times out to get things to
551 Curl_expire(easy->easy_handle, 1);
553 /* increase the node-counter */
556 if((multi->num_easy * 4) > multi->connc->num) {
557 /* We want the connection cache to have plenty room. Before we supported
558 the shared cache every single easy handle had 5 entries in their cache
560 long newmax = multi->num_easy * 4;
562 if(multi->maxconnects && (multi->maxconnects < newmax))
563 /* don't grow beyond the allowed size */
564 newmax = multi->maxconnects;
566 if(newmax > multi->connc->num) {
567 /* we only do this is we can in fact grow the cache */
568 CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax);
569 if(res != CURLE_OK) {
570 /* FIXME: may need to do more cleanup here */
571 curl_multi_remove_handle(multi_handle, easy_handle);
572 return CURLM_OUT_OF_MEMORY;
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 = (bool)(easy->state < CURLM_STATE_COMPLETED);
632 bool easy_owns_conn = (bool)(easy->easy_conn &&
633 (easy->easy_conn->data == easy->easy_handle));
635 /* If the 'state' is not INIT or COMPLETED, we might need to do something
636 nice to put the easy_handle in a good known state when this returns. */
638 /* this handle is "alive" so we need to count down the total number of
639 alive connections when this is removed */
642 if(easy->easy_conn &&
643 (easy->easy_conn->send_pipe->size +
644 easy->easy_conn->recv_pipe->size > 1) &&
645 easy->state > CURLM_STATE_WAITDO &&
646 easy->state < CURLM_STATE_COMPLETED) {
647 /* If the handle is in a pipeline and has started sending off its
648 request but not received its reponse yet, we need to close
650 easy->easy_conn->bits.close = TRUE;
651 /* Set connection owner so that Curl_done() closes it.
652 We can sefely do this here since connection is killed. */
653 easy->easy_conn->data = easy->easy_handle;
656 /* The timer must be shut down before easy->multi is set to NULL,
657 else the timenode will remain in the splay tree after
658 curl_easy_cleanup is called. */
659 Curl_expire(easy->easy_handle, 0);
661 /* destroy the timeout list that is held in the easy handle */
662 if(data->state.timeoutlist) {
663 Curl_llist_destroy(data->state.timeoutlist, NULL);
664 data->state.timeoutlist = NULL;
667 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
668 /* clear out the usage of the shared DNS cache */
669 easy->easy_handle->dns.hostcache = NULL;
670 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
673 if(easy->easy_conn) {
675 /* we must call Curl_done() here (if we still "own it") so that we don't
676 leave a half-baked one around */
677 if (easy_owns_conn) {
679 /* Curl_done() clears the conn->data field to lose the association
680 between the easy handle and the connection
682 Note that this ignores the return code simply because there's
683 nothing really useful to do with it anyway! */
684 (void)Curl_done(&easy->easy_conn, easy->result, premature);
687 /* the connection is still alive, set back the association to enable
688 the check below to trigger TRUE */
689 easy->easy_conn->data = easy->easy_handle;
692 /* Clear connection pipelines, if Curl_done above was not called */
693 Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
696 /* figure out if the easy handle is used by one or more connections in the
698 multi_connc_remove_handle(multi, easy->easy_handle);
700 if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
701 /* if this was using the shared connection cache we clear the pointer
702 to that since we're not part of that handle anymore */
703 easy->easy_handle->state.connc = NULL;
705 /* Since we return the connection back to the communal connection pool
706 we mark the last connection as inaccessible */
707 easy->easy_handle->state.lastconnect = -1;
709 /* Modify the connectindex since this handle can't point to the
710 connection cache anymore.
712 TODO: consider if this is really what we want. The connection cache
713 is within the multi handle and that owns the connections so we should
714 not need to touch connections like this when we just remove an easy
717 if(easy->easy_conn && easy_owns_conn &&
718 (easy->easy_conn->send_pipe->size +
719 easy->easy_conn->recv_pipe->size == 0))
720 easy->easy_conn->connectindex = -1;
723 /* change state without using multistate(), only to make singlesocket() do
725 easy->state = CURLM_STATE_COMPLETED;
726 singlesocket(multi, easy); /* to let the application know what sockets
727 that vanish with this handle */
729 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
730 to this multi handle */
733 /* make sure there's no pending message in the queue sent from this easy
735 struct curl_llist_element *e;
737 for(e = multi->msglist->head; e; e = e->next) {
738 struct Curl_message *msg = e->ptr;
740 if(msg->extmsg.easy_handle == easy->easy_handle) {
741 Curl_llist_remove(multi->msglist, e, NULL);
742 /* there can only be one from this specific handle */
748 /* make the previous node point to our next */
750 easy->prev->next = easy->next;
751 /* make our next point to our previous node */
753 easy->next->prev = easy->prev;
755 easy->easy_handle->set.one_easy = NULL; /* detached */
757 /* Null the position in the controlling structure */
758 easy->easy_handle->multi_pos = NULL;
761 We do not touch the easy handle here! */
764 multi->num_easy--; /* one less to care about now */
770 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
773 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
775 return multi->pipelining_enabled;
778 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
780 struct Curl_one_easy *one_easy = data->set.one_easy;
783 one_easy->easy_conn = NULL;
786 static int waitconnect_getsock(struct connectdata *conn,
791 return GETSOCK_BLANK;
793 sock[0] = conn->sock[FIRSTSOCKET];
795 /* when we've sent a CONNECT to a proxy, we should rather wait for the
796 socket to become readable to be able to get the response headers */
797 if(conn->bits.tunnel_connecting)
798 return GETSOCK_READSOCK(0);
800 return GETSOCK_WRITESOCK(0);
803 static int domore_getsock(struct connectdata *conn,
808 return GETSOCK_BLANK;
810 /* When in DO_MORE state, we could be either waiting for us
811 to connect to a remote site, or we could wait for that site
812 to connect to us. It makes a difference in the way: if we
813 connect to the site we wait for the socket to become writable, if
814 the site connects to us we wait for it to become readable */
815 sock[0] = conn->sock[SECONDARYSOCKET];
817 return GETSOCK_WRITESOCK(0);
820 /* returns bitmapped flags for this handle and its sockets */
821 static int multi_getsock(struct Curl_one_easy *easy,
822 curl_socket_t *socks, /* points to numsocks number
826 /* If the pipe broke, or if there's no connection left for this easy handle,
827 then we MUST bail out now with no bitmask set. The no connection case can
828 happen when this is called from curl_multi_remove_handle() =>
829 singlesocket() => multi_getsock().
831 if(easy->easy_handle->state.pipe_broke || !easy->easy_conn)
834 if(easy->state > CURLM_STATE_CONNECT &&
835 easy->state < CURLM_STATE_COMPLETED) {
836 /* Set up ownership correctly */
837 easy->easy_conn->data = easy->easy_handle;
840 switch(easy->state) {
842 #if 0 /* switch back on these cases to get the compiler to check for all enums
844 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
845 case CURLM_STATE_COMPLETED:
846 case CURLM_STATE_MSGSENT:
847 case CURLM_STATE_INIT:
848 case CURLM_STATE_CONNECT:
849 case CURLM_STATE_WAITDO:
850 case CURLM_STATE_DONE:
851 case CURLM_STATE_LAST:
852 /* this will get called with CURLM_STATE_COMPLETED when a handle is
857 case CURLM_STATE_WAITRESOLVE:
858 return Curl_resolv_getsock(easy->easy_conn, socks, numsocks);
860 case CURLM_STATE_PROTOCONNECT:
861 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
864 case CURLM_STATE_DOING:
865 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
867 case CURLM_STATE_WAITPROXYCONNECT:
868 case CURLM_STATE_WAITCONNECT:
869 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
871 case CURLM_STATE_DO_MORE:
872 return domore_getsock(easy->easy_conn, socks, numsocks);
874 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
875 to waiting for the same as the *PERFORM states */
876 case CURLM_STATE_PERFORM:
877 case CURLM_STATE_WAITPERFORM:
878 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
883 CURLMcode curl_multi_fdset(CURLM *multi_handle,
884 fd_set *read_fd_set, fd_set *write_fd_set,
885 fd_set *exc_fd_set, int *max_fd)
887 /* Scan through all the easy handles to get the file descriptors set.
888 Some easy handles may not have connected to the remote host yet,
889 and then we must make sure that is done. */
890 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
891 struct Curl_one_easy *easy;
893 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
896 (void)exc_fd_set; /* not used */
898 if(!GOOD_MULTI_HANDLE(multi))
899 return CURLM_BAD_HANDLE;
901 easy=multi->easy.next;
902 while(easy != &multi->easy) {
903 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
905 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
906 curl_socket_t s = CURL_SOCKET_BAD;
908 if(bitmap & GETSOCK_READSOCK(i)) {
909 FD_SET(sockbunch[i], read_fd_set);
912 if(bitmap & GETSOCK_WRITESOCK(i)) {
913 FD_SET(sockbunch[i], write_fd_set);
916 if(s == CURL_SOCKET_BAD)
917 /* this socket is unused, break out of loop */
920 if((int)s > this_max_fd)
921 this_max_fd = (int)s;
925 easy = easy->next; /* check next handle */
928 *max_fd = this_max_fd;
933 static CURLMcode multi_runsingle(struct Curl_multi *multi,
935 struct Curl_one_easy *easy)
937 struct Curl_message *msg = NULL;
940 bool protocol_connect = FALSE;
943 CURLMcode result = CURLM_OK;
944 struct SingleRequest *k;
945 struct SessionHandle *data;
948 if(!GOOD_EASY_HANDLE(easy->easy_handle))
949 return CURLM_BAD_EASY_HANDLE;
951 data = easy->easy_handle;
954 /* this is a do-while loop just to allow a break to skip to the end
956 bool disconnect_conn = FALSE;
958 /* Handle the case when the pipe breaks, i.e., the connection
959 we're using gets cleaned up and we're left with nothing. */
960 if(data->state.pipe_broke) {
961 infof(data, "Pipe broke: handle 0x%p, url = %s\n",
962 easy, data->state.path);
964 if(easy->state < CURLM_STATE_COMPLETED) {
965 /* Head back to the CONNECT state */
966 multistate(easy, CURLM_STATE_CONNECT);
967 result = CURLM_CALL_MULTI_PERFORM;
968 easy->result = CURLE_OK;
971 data->state.pipe_broke = FALSE;
972 easy->easy_conn = NULL;
976 if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
977 easy->state < CURLM_STATE_COMPLETED)
978 /* Make sure we set the connection's current owner */
979 easy->easy_conn->data = data;
981 if(easy->easy_conn &&
982 (easy->state >= CURLM_STATE_CONNECT) &&
983 (easy->state < CURLM_STATE_COMPLETED)) {
984 /* we need to wait for the connect state as only then is the start time
985 stored, but we must not check already completed handles */
987 timeout_ms = Curl_timeleft(easy->easy_conn, &now,
988 (easy->state <= CURLM_STATE_WAITDO)?
992 /* Handle timed out */
993 if(easy->state == CURLM_STATE_WAITRESOLVE)
994 failf(data, "Resolving timed out after %ld milliseconds",
995 Curl_tvdiff(now, data->progress.t_startsingle));
996 else if(easy->state == CURLM_STATE_WAITCONNECT)
997 failf(data, "Connection timed out after %ld milliseconds",
998 Curl_tvdiff(now, data->progress.t_startsingle));
1001 failf(data, "Operation timed out after %ld milliseconds with %"
1002 FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
1003 Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount,
1006 easy->result = CURLE_OPERATION_TIMEDOUT;
1007 multistate(easy, CURLM_STATE_COMPLETED);
1012 switch(easy->state) {
1013 case CURLM_STATE_INIT:
1014 /* init this transfer. */
1015 easy->result=Curl_pretransfer(data);
1017 if(CURLE_OK == easy->result) {
1018 /* after init, go CONNECT */
1019 multistate(easy, CURLM_STATE_CONNECT);
1020 result = CURLM_CALL_MULTI_PERFORM;
1022 data->state.used_interface = Curl_if_multi;
1026 case CURLM_STATE_CONNECT:
1027 /* Connect. We get a connection identifier filled in. */
1028 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1029 easy->result = Curl_connect(data, &easy->easy_conn,
1030 &async, &protocol_connect);
1032 if(CURLE_OK == easy->result) {
1033 /* Add this handle to the send or pend pipeline */
1034 easy->result = addHandleToSendOrPendPipeline(data,
1036 if(CURLE_OK == easy->result) {
1038 /* We're now waiting for an asynchronous name lookup */
1039 multistate(easy, CURLM_STATE_WAITRESOLVE);
1041 /* after the connect has been sent off, go WAITCONNECT unless the
1042 protocol connect is already done and we can go directly to
1044 result = CURLM_CALL_MULTI_PERFORM;
1046 if(protocol_connect)
1047 multistate(easy, multi->pipelining_enabled?
1048 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1050 #ifndef CURL_DISABLE_HTTP
1051 if(easy->easy_conn->bits.tunnel_connecting)
1052 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1055 multistate(easy, CURLM_STATE_WAITCONNECT);
1062 case CURLM_STATE_WAITRESOLVE:
1063 /* awaiting an asynch name resolve to complete */
1065 struct Curl_dns_entry *dns = NULL;
1067 /* check if we have the name resolved by now */
1068 easy->result = Curl_is_resolved(easy->easy_conn, &dns);
1071 /* Update sockets here. Mainly because the socket(s) may have been
1072 closed and the application thus needs to be told, even if it is
1073 likely that the same socket(s) will again be used further down. */
1074 singlesocket(multi, easy);
1076 /* Perform the next step in the connection phase, and then move on
1077 to the WAITCONNECT state */
1078 easy->result = Curl_async_resolved(easy->easy_conn,
1081 if(CURLE_OK != easy->result)
1082 /* if Curl_async_resolved() returns failure, the connection struct
1083 is already freed and gone */
1084 easy->easy_conn = NULL; /* no more connection */
1086 /* call again please so that we get the next socket setup */
1087 result = CURLM_CALL_MULTI_PERFORM;
1088 if(protocol_connect)
1089 multistate(easy, multi->pipelining_enabled?
1090 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1092 #ifndef CURL_DISABLE_HTTP
1093 if(easy->easy_conn->bits.tunnel_connecting)
1094 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1097 multistate(easy, CURLM_STATE_WAITCONNECT);
1102 if(CURLE_OK != easy->result) {
1103 /* failure detected */
1104 disconnect_conn = TRUE;
1110 #ifndef CURL_DISABLE_HTTP
1111 case CURLM_STATE_WAITPROXYCONNECT:
1112 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1113 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1115 if(easy->easy_conn->bits.proxy_connect_closed) {
1116 /* reset the error buffer */
1117 if(data->set.errorbuffer)
1118 data->set.errorbuffer[0] = '\0';
1119 data->state.errorbuf = FALSE;
1121 easy->result = CURLE_OK;
1122 result = CURLM_CALL_MULTI_PERFORM;
1123 multistate(easy, CURLM_STATE_CONNECT);
1125 else if (CURLE_OK == easy->result) {
1126 if(!easy->easy_conn->bits.tunnel_connecting)
1127 multistate(easy, CURLM_STATE_WAITCONNECT);
1132 case CURLM_STATE_WAITCONNECT:
1133 /* awaiting a completion of an asynch connect */
1134 easy->result = Curl_is_connected(easy->easy_conn,
1138 /* see if we need to do any proxy magic first once we connected */
1139 easy->result = Curl_connected_proxy(easy->easy_conn);
1142 /* if everything is still fine we do the protocol-specific connect
1144 easy->result = Curl_protocol_connect(easy->easy_conn,
1148 if(CURLE_OK != easy->result) {
1149 /* failure detected */
1150 /* Just break, the cleaning up is handled all in one place */
1151 disconnect_conn = TRUE;
1156 if(!protocol_connect) {
1157 /* We have a TCP connection, but 'protocol_connect' may be false
1158 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1159 connect is TRUE, we move on to STATE_DO.
1160 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1162 #ifndef CURL_DISABLE_HTTP
1163 if(easy->easy_conn->bits.tunnel_connecting)
1164 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1167 multistate(easy, CURLM_STATE_PROTOCONNECT);
1171 /* after the connect has completed, go WAITDO or DO */
1172 multistate(easy, multi->pipelining_enabled?
1173 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1175 result = CURLM_CALL_MULTI_PERFORM;
1179 case CURLM_STATE_PROTOCONNECT:
1180 /* protocol-specific connect phase */
1181 easy->result = Curl_protocol_connecting(easy->easy_conn,
1183 if((easy->result == CURLE_OK) && protocol_connect) {
1184 /* after the connect has completed, go WAITDO or DO */
1185 multistate(easy, multi->pipelining_enabled?
1186 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1187 result = CURLM_CALL_MULTI_PERFORM;
1189 else if(easy->result) {
1190 /* failure detected */
1191 Curl_posttransfer(data);
1192 Curl_done(&easy->easy_conn, easy->result, FALSE);
1193 disconnect_conn = TRUE;
1197 case CURLM_STATE_WAITDO:
1198 /* Wait for our turn to DO when we're pipelining requests */
1200 infof(data, "Conn %ld send pipe %zu inuse %d athead %d\n",
1201 easy->easy_conn->connectindex,
1202 easy->easy_conn->send_pipe->size,
1203 easy->easy_conn->writechannel_inuse?1:0,
1204 isHandleAtHead(data,
1205 easy->easy_conn->send_pipe)?1:0);
1207 if(!easy->easy_conn->writechannel_inuse &&
1208 isHandleAtHead(data,
1209 easy->easy_conn->send_pipe)) {
1210 /* Grab the channel */
1211 easy->easy_conn->writechannel_inuse = TRUE;
1212 multistate(easy, CURLM_STATE_DO);
1213 result = CURLM_CALL_MULTI_PERFORM;
1217 case CURLM_STATE_DO:
1218 if(data->set.connect_only) {
1219 /* keep connection open for application to use the socket */
1220 easy->easy_conn->bits.close = FALSE;
1221 multistate(easy, CURLM_STATE_DONE);
1222 easy->result = CURLE_OK;
1226 /* Perform the protocol's DO action */
1227 easy->result = Curl_do(&easy->easy_conn,
1230 if(CURLE_OK == easy->result) {
1232 /* some steps needed for wildcard matching */
1233 if(data->set.wildcardmatch) {
1234 struct WildcardData *wc = &data->wildcard;
1235 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1236 /* skip some states if it is important */
1237 Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1238 multistate(easy, CURLM_STATE_DONE);
1239 result = CURLM_CALL_MULTI_PERFORM;
1243 /* DO was not completed in one function call, we must continue
1245 multistate(easy, CURLM_STATE_DOING);
1249 /* after DO, go DO_DONE... or DO_MORE */
1250 else if(easy->easy_conn->bits.do_more) {
1251 /* we're supposed to do more, but we need to sit down, relax
1252 and wait a little while first */
1253 multistate(easy, CURLM_STATE_DO_MORE);
1257 /* we're done with the DO, now DO_DONE */
1258 multistate(easy, CURLM_STATE_DO_DONE);
1259 result = CURLM_CALL_MULTI_PERFORM;
1262 else if ((CURLE_SEND_ERROR == easy->result) &&
1263 easy->easy_conn->bits.reuse) {
1265 * In this situation, a connection that we were trying to use
1266 * may have unexpectedly died. If possible, send the connection
1267 * back to the CONNECT phase so we can try again.
1269 char *newurl = NULL;
1270 followtype follow=FOLLOW_NONE;
1274 drc = Curl_retry_request(easy->easy_conn, &newurl);
1276 /* a failure here pretty much implies an out of memory */
1278 disconnect_conn = TRUE;
1281 retry = (bool)(newurl?TRUE:FALSE);
1283 Curl_posttransfer(data);
1284 drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
1286 /* When set to retry the connection, we must to go back to
1287 * the CONNECT state */
1289 if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
1290 follow = FOLLOW_RETRY;
1291 drc = Curl_follow(data, newurl, follow);
1292 if(drc == CURLE_OK) {
1293 multistate(easy, CURLM_STATE_CONNECT);
1294 result = CURLM_CALL_MULTI_PERFORM;
1295 easy->result = CURLE_OK;
1304 /* done didn't return OK or SEND_ERROR */
1310 /* Have error handler disconnect conn if we can't retry */
1311 disconnect_conn = TRUE;
1315 /* failure detected */
1316 Curl_posttransfer(data);
1317 Curl_done(&easy->easy_conn, easy->result, FALSE);
1318 disconnect_conn = TRUE;
1323 case CURLM_STATE_DOING:
1324 /* we continue DOING until the DO phase is complete */
1325 easy->result = Curl_protocol_doing(easy->easy_conn,
1327 if(CURLE_OK == easy->result) {
1329 /* after DO, go PERFORM... or DO_MORE */
1330 if(easy->easy_conn->bits.do_more) {
1331 /* we're supposed to do more, but we need to sit down, relax
1332 and wait a little while first */
1333 multistate(easy, CURLM_STATE_DO_MORE);
1337 /* we're done with the DO, now DO_DONE */
1338 multistate(easy, CURLM_STATE_DO_DONE);
1339 result = CURLM_CALL_MULTI_PERFORM;
1341 } /* dophase_done */
1344 /* failure detected */
1345 Curl_posttransfer(data);
1346 Curl_done(&easy->easy_conn, easy->result, FALSE);
1347 disconnect_conn = TRUE;
1351 case CURLM_STATE_DO_MORE:
1352 /* Ready to do more? */
1353 easy->result = Curl_is_connected(easy->easy_conn,
1358 * When we are connected, DO MORE and then go DO_DONE
1360 easy->result = Curl_do_more(easy->easy_conn);
1362 /* No need to remove ourselves from the send pipeline here since that
1363 is done for us in Curl_done() */
1365 if(CURLE_OK == easy->result) {
1366 multistate(easy, CURLM_STATE_DO_DONE);
1367 result = CURLM_CALL_MULTI_PERFORM;
1370 /* failure detected */
1371 Curl_posttransfer(data);
1372 Curl_done(&easy->easy_conn, easy->result, FALSE);
1373 disconnect_conn = TRUE;
1378 case CURLM_STATE_DO_DONE:
1379 /* Move ourselves from the send to recv pipeline */
1380 moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
1381 /* Check if we can move pending requests to send pipe */
1382 checkPendPipeline(easy->easy_conn);
1383 multistate(easy, CURLM_STATE_WAITPERFORM);
1384 result = CURLM_CALL_MULTI_PERFORM;
1387 case CURLM_STATE_WAITPERFORM:
1388 /* Wait for our turn to PERFORM */
1389 if(!easy->easy_conn->readchannel_inuse &&
1390 isHandleAtHead(data,
1391 easy->easy_conn->recv_pipe)) {
1392 /* Grab the channel */
1393 easy->easy_conn->readchannel_inuse = TRUE;
1394 multistate(easy, CURLM_STATE_PERFORM);
1395 result = CURLM_CALL_MULTI_PERFORM;
1399 infof(data, "Conn %ld recv pipe %zu inuse %d athead %d\n",
1400 easy->easy_conn->connectindex,
1401 easy->easy_conn->recv_pipe->size,
1402 easy->easy_conn->readchannel_inuse?1:0,
1403 isHandleAtHead(data,
1404 easy->easy_conn->recv_pipe)?1:0);
1409 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1410 /* if both rates are within spec, resume transfer */
1411 if( ( (data->set.max_send_speed == 0) ||
1412 (data->progress.ulspeed < data->set.max_send_speed )) &&
1413 ( (data->set.max_recv_speed == 0) ||
1414 (data->progress.dlspeed < data->set.max_recv_speed) ) )
1415 multistate(easy, CURLM_STATE_PERFORM);
1418 case CURLM_STATE_PERFORM:
1419 /* check if over send speed */
1420 if( (data->set.max_send_speed > 0) &&
1421 (data->progress.ulspeed > data->set.max_send_speed) ) {
1424 multistate(easy, CURLM_STATE_TOOFAST);
1426 /* calculate upload rate-limitation timeout. */
1427 buffersize = (int)(data->set.buffer_size ?
1428 data->set.buffer_size : BUFSIZE);
1429 timeout_ms = Curl_sleep_time(data->set.max_send_speed,
1430 data->progress.ulspeed, buffersize);
1431 Curl_expire(data, timeout_ms);
1435 /* check if over recv speed */
1436 if( (data->set.max_recv_speed > 0) &&
1437 (data->progress.dlspeed > data->set.max_recv_speed) ) {
1440 multistate(easy, CURLM_STATE_TOOFAST);
1442 /* Calculate download rate-limitation timeout. */
1443 buffersize = (int)(data->set.buffer_size ?
1444 data->set.buffer_size : BUFSIZE);
1445 timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
1446 data->progress.dlspeed, buffersize);
1447 Curl_expire(data, timeout_ms);
1451 /* read/write data if it is ready to do so */
1452 easy->result = Curl_readwrite(easy->easy_conn, &done);
1456 if(!(k->keepon & KEEP_RECV)) {
1457 /* We're done receiving */
1458 easy->easy_conn->readchannel_inuse = FALSE;
1461 if(!(k->keepon & KEEP_SEND)) {
1462 /* We're done sending */
1463 easy->easy_conn->writechannel_inuse = FALSE;
1467 /* The transfer phase returned error, we mark the connection to get
1468 * closed to prevent being re-used. This is because we can't possibly
1469 * know if the connection is in a good shape or not now. Unless it is
1470 * a protocol which uses two "channels" like FTP, as then the error
1471 * happened in the data connection.
1473 if(!(easy->easy_conn->protocol & PROT_DUALCHANNEL))
1474 easy->easy_conn->bits.close = TRUE;
1476 Curl_posttransfer(data);
1477 Curl_done(&easy->easy_conn, easy->result, FALSE);
1479 else if(TRUE == done) {
1480 char *newurl = NULL;
1482 followtype follow=FOLLOW_NONE;
1484 easy->result = Curl_retry_request(easy->easy_conn, &newurl);
1486 retry = (bool)(newurl?TRUE:FALSE);
1488 /* call this even if the readwrite function returned error */
1489 Curl_posttransfer(data);
1491 /* we're no longer receving */
1492 moveHandleFromRecvToDonePipeline(data,
1495 /* expire the new receiving pipeline head */
1496 if(easy->easy_conn->recv_pipe->head)
1497 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1499 /* Check if we can move pending requests to send pipe */
1500 checkPendPipeline(easy->easy_conn);
1502 /* When we follow redirects or is set to retry the connection, we must
1503 to go back to the CONNECT state */
1504 if(data->req.newurl || retry) {
1506 /* if the URL is a follow-location and not just a retried request
1507 then figure out the URL here */
1508 newurl = data->req.newurl;
1509 data->req.newurl = NULL;
1510 follow = FOLLOW_REDIR;
1513 follow = FOLLOW_RETRY;
1514 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1515 if(easy->result == CURLE_OK)
1516 easy->result = Curl_follow(data, newurl, follow);
1517 if(CURLE_OK == easy->result) {
1518 multistate(easy, CURLM_STATE_CONNECT);
1519 result = CURLM_CALL_MULTI_PERFORM;
1522 /* Since we "took it", we are in charge of freeing this on
1527 /* after the transfer is done, go DONE */
1529 /* but first check to see if we got a location info even though we're
1530 not following redirects */
1531 if (data->req.location) {
1532 newurl = data->req.location;
1533 data->req.location = NULL;
1534 easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
1539 multistate(easy, CURLM_STATE_DONE);
1540 result = CURLM_CALL_MULTI_PERFORM;
1546 case CURLM_STATE_DONE:
1548 if(easy->easy_conn) {
1549 /* Remove ourselves from the receive and done pipelines. Handle
1550 should be on one of these lists, depending upon how we got here. */
1551 Curl_removeHandleFromPipeline(data,
1552 easy->easy_conn->recv_pipe);
1553 Curl_removeHandleFromPipeline(data,
1554 easy->easy_conn->done_pipe);
1555 /* Check if we can move pending requests to send pipe */
1556 checkPendPipeline(easy->easy_conn);
1558 if(easy->easy_conn->bits.stream_was_rewound) {
1559 /* This request read past its response boundary so we quickly let
1560 the other requests consume those bytes since there is no
1561 guarantee that the socket will become active again */
1562 result = CURLM_CALL_MULTI_PERFORM;
1565 /* post-transfer command */
1566 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1568 * If there are other handles on the pipeline, Curl_done won't set
1569 * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
1570 * access free'd data, if the connection is free'd and the handle
1571 * removed before we perform the processing in CURLM_STATE_COMPLETED
1573 if (easy->easy_conn)
1574 easy->easy_conn = NULL;
1577 if(data->set.wildcardmatch) {
1578 if(data->wildcard.state != CURLWC_DONE) {
1579 /* if a wildcard is set and we are not ending -> lets start again
1580 with CURLM_STATE_INIT */
1581 result = CURLM_CALL_MULTI_PERFORM;
1582 multistate(easy, CURLM_STATE_INIT);
1587 /* after we have DONE what we're supposed to do, go COMPLETED, and
1588 it doesn't matter what the Curl_done() returned! */
1589 multistate(easy, CURLM_STATE_COMPLETED);
1593 case CURLM_STATE_COMPLETED:
1594 /* this is a completed transfer, it is likely to still be connected */
1596 /* This node should be delinked from the list now and we should post
1597 an information message that we are complete. */
1599 /* Important: reset the conn pointer so that we don't point to memory
1600 that could be freed anytime */
1601 easy->easy_conn = NULL;
1603 Curl_expire(data, 0); /* stop all timers */
1606 case CURLM_STATE_MSGSENT:
1607 return CURLM_OK; /* do nothing */
1610 return CURLM_INTERNAL_ERROR;
1613 if(CURLM_STATE_COMPLETED > easy->state) {
1614 if(CURLE_OK != easy->result) {
1616 * If an error was returned, and we aren't in completed state now,
1617 * then we go to completed and consider this transfer aborted.
1620 /* NOTE: no attempt to disconnect connections must be made
1621 in the case blocks above - cleanup happens only here */
1623 data->state.pipe_broke = FALSE;
1625 if(easy->easy_conn) {
1626 /* if this has a connection, unsubscribe from the pipelines */
1627 easy->easy_conn->writechannel_inuse = FALSE;
1628 easy->easy_conn->readchannel_inuse = FALSE;
1629 Curl_removeHandleFromPipeline(data,
1630 easy->easy_conn->send_pipe);
1631 Curl_removeHandleFromPipeline(data,
1632 easy->easy_conn->recv_pipe);
1633 Curl_removeHandleFromPipeline(data,
1634 easy->easy_conn->done_pipe);
1635 /* Check if we can move pending requests to send pipe */
1636 checkPendPipeline(easy->easy_conn);
1639 if(disconnect_conn) {
1640 /* disconnect properly */
1641 Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE);
1643 /* This is where we make sure that the easy_conn pointer is reset.
1644 We don't have to do this in every case block above where a
1645 failure is detected */
1646 easy->easy_conn = NULL;
1649 multistate(easy, CURLM_STATE_COMPLETED);
1651 /* if there's still a connection to use, call the progress function */
1652 else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn))
1653 easy->result = CURLE_ABORTED_BY_CALLBACK;
1657 if(CURLM_STATE_COMPLETED == easy->state) {
1658 if(data->dns.hostcachetype == HCACHE_MULTI) {
1659 /* clear out the usage of the shared DNS cache */
1660 data->dns.hostcache = NULL;
1661 data->dns.hostcachetype = HCACHE_NONE;
1664 /* now fill in the Curl_message with this info */
1667 msg->extmsg.msg = CURLMSG_DONE;
1668 msg->extmsg.easy_handle = data;
1669 msg->extmsg.data.result = easy->result;
1671 result = multi_addmsg(multi, msg);
1673 multistate(easy, CURLM_STATE_MSGSENT);
1680 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1682 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1683 struct Curl_one_easy *easy;
1684 CURLMcode returncode=CURLM_OK;
1685 struct Curl_tree *t;
1686 struct timeval now = Curl_tvnow();
1688 if(!GOOD_MULTI_HANDLE(multi))
1689 return CURLM_BAD_HANDLE;
1691 easy=multi->easy.next;
1692 while(easy != &multi->easy) {
1694 struct WildcardData *wc = &easy->easy_handle->wildcard;
1696 if(easy->easy_handle->set.wildcardmatch) {
1698 CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
1700 return CURLM_OUT_OF_MEMORY;
1705 result = multi_runsingle(multi, now, easy);
1706 while (CURLM_CALL_MULTI_PERFORM == result);
1708 if(easy->easy_handle->set.wildcardmatch) {
1709 /* destruct wildcard structures if it is needed */
1710 if(wc->state == CURLWC_DONE || result)
1711 Curl_wildcard_dtor(wc);
1715 returncode = result;
1717 easy = easy->next; /* operate on next handle */
1721 * Simply remove all expired timers from the splay since handles are dealt
1722 * with unconditionally by this function and curl_multi_timeout() requires
1723 * that already passed/handled expire times are removed from the splay.
1725 * It is important that the 'now' value is set at the entry of this function
1726 * and not for the current time as it may have ticked a little while since
1727 * then and then we risk this loop to remove timers that actually have not
1731 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1733 /* the removed may have another timeout in queue */
1734 (void)add_next_timeout(now, multi, t->payload);
1738 *running_handles = multi->num_alive;
1740 if( CURLM_OK >= returncode )
1741 update_timer(multi);
1746 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1748 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1749 struct Curl_one_easy *easy;
1750 struct Curl_one_easy *nexteasy;
1755 if(GOOD_MULTI_HANDLE(multi)) {
1756 multi->type = 0; /* not good anymore */
1757 Curl_hash_destroy(multi->hostcache);
1758 Curl_hash_destroy(multi->sockhash);
1759 multi->hostcache = NULL;
1760 multi->sockhash = NULL;
1762 /* go over all connections that have close actions */
1763 for(i=0; i< multi->connc->num; i++) {
1764 if(multi->connc->connects[i] &&
1765 multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
1766 Curl_disconnect(multi->connc->connects[i], /* dead_connection */ FALSE);
1767 multi->connc->connects[i] = NULL;
1770 /* now walk through the list of handles we kept around only to be
1771 able to close connections "properly" */
1772 cl = multi->closure;
1774 cl->easy_handle->state.shared_conn = NULL; /* no more shared */
1775 if(cl->easy_handle->state.closed)
1776 /* close handle only if curl_easy_cleanup() already has been called
1777 for this easy handle */
1778 Curl_close(cl->easy_handle);
1784 Curl_rm_connc(multi->connc);
1786 /* remove the pending list of messages */
1787 Curl_llist_destroy(multi->msglist, NULL);
1789 /* remove all easy handles */
1790 easy = multi->easy.next;
1791 while(easy != &multi->easy) {
1792 nexteasy=easy->next;
1793 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1794 /* clear out the usage of the shared DNS cache */
1795 easy->easy_handle->dns.hostcache = NULL;
1796 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1799 /* Clear the pointer to the connection cache */
1800 easy->easy_handle->state.connc = NULL;
1802 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1813 return CURLM_BAD_HANDLE;
1817 * curl_multi_info_read()
1819 * This function is the primary way for a multi/multi_socket application to
1820 * figure out if a transfer has ended. We MUST make this function as fast as
1821 * possible as it will be polled frequently and we MUST NOT scan any lists in
1822 * here to figure out things. We must scale fine to thousands of handles and
1823 * beyond. The current design is fully O(1).
1826 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1828 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1829 struct Curl_message *msg;
1831 *msgs_in_queue = 0; /* default to none */
1833 if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
1834 /* there is one or more messages in the list */
1835 struct curl_llist_element *e;
1837 /* extract the head of the list to return */
1838 e = multi->msglist->head;
1842 /* remove the extracted entry */
1843 Curl_llist_remove(multi->msglist, e, NULL);
1845 *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
1847 return &msg->extmsg;
1854 * singlesocket() checks what sockets we deal with and their "action state"
1855 * and if we have a different state in any of those sockets from last time we
1856 * call the callback accordingly.
1858 static void singlesocket(struct Curl_multi *multi,
1859 struct Curl_one_easy *easy)
1861 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1863 struct Curl_sh_entry *entry;
1866 unsigned int curraction;
1867 struct Curl_one_easy *easy_by_hash;
1868 bool remove_sock_from_hash;
1870 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1871 socks[i] = CURL_SOCKET_BAD;
1873 /* Fill in the 'current' struct with the state as it is now: what sockets to
1874 supervise and for what actions */
1875 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1877 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1878 sockets we should have from now on. Detect the differences, remove no
1879 longer supervised ones and add new ones */
1881 /* walk over the sockets we got right now */
1882 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1883 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1885 int action = CURL_POLL_NONE;
1889 /* get it from the hash */
1890 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1892 if(curraction & GETSOCK_READSOCK(i))
1893 action |= CURL_POLL_IN;
1894 if(curraction & GETSOCK_WRITESOCK(i))
1895 action |= CURL_POLL_OUT;
1898 /* yeps, already present so check if it has the same action set */
1899 if(entry->action == action)
1900 /* same, continue */
1904 /* this is a socket we didn't have before, add it! */
1905 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1911 /* we know (entry != NULL) at this point, see the logic above */
1912 multi->socket_cb(easy->easy_handle,
1915 multi->socket_userp,
1918 entry->action = action; /* store the current action state */
1921 num = i; /* number of sockets */
1923 /* when we've walked over all the sockets we should have right now, we must
1924 make sure to detect sockets that are removed */
1925 for(i=0; i< easy->numsocks; i++) {
1927 s = easy->sockets[i];
1928 for(j=0; j<num; j++) {
1930 /* this is still supervised */
1931 s = CURL_SOCKET_BAD;
1935 if(s != CURL_SOCKET_BAD) {
1937 /* this socket has been removed. Tell the app to remove it */
1938 remove_sock_from_hash = TRUE;
1940 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1942 /* check if the socket to be removed serves a connection which has
1943 other easy-s in a pipeline. In this case the socket should not be
1945 struct connectdata *easy_conn;
1947 easy_by_hash = entry->easy->multi_pos;
1948 easy_conn = easy_by_hash->easy_conn;
1950 if (easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
1951 /* the handle should not be removed from the pipe yet */
1952 remove_sock_from_hash = FALSE;
1954 /* Update the sockhash entry to instead point to the next in line
1955 for the recv_pipe, or the first (in case this particular easy
1957 if (entry->easy == easy->easy_handle) {
1958 if (isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe))
1959 entry->easy = easy_conn->recv_pipe->head->next->ptr;
1961 entry->easy = easy_conn->recv_pipe->head->ptr;
1964 if (easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
1965 /* the handle should not be removed from the pipe yet */
1966 remove_sock_from_hash = FALSE;
1968 /* Update the sockhash entry to instead point to the next in line
1969 for the send_pipe, or the first (in case this particular easy
1971 if (entry->easy == easy->easy_handle) {
1972 if (isHandleAtHead(easy->easy_handle, easy_conn->send_pipe))
1973 entry->easy = easy_conn->send_pipe->head->next->ptr;
1975 entry->easy = easy_conn->send_pipe->head->ptr;
1978 /* Don't worry about overwriting recv_pipe head with send_pipe_head,
1979 when action will be asked on the socket (see multi_socket()), the
1980 head of the correct pipe will be taken according to the
1985 /* just a precaution, this socket really SHOULD be in the hash already
1986 but in case it isn't, we don't have to tell the app to remove it
1987 either since it never got to know about it */
1988 remove_sock_from_hash = FALSE;
1990 if (remove_sock_from_hash) {
1991 multi->socket_cb(easy->easy_handle,
1994 multi->socket_userp,
1995 entry ? entry->socketp : NULL);
1996 sh_delentry(multi->sockhash, s);
2002 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
2003 easy->numsocks = num;
2007 * add_next_timeout()
2009 * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
2010 * when it has just been removed from the splay tree because the timeout has
2011 * expired. This function is then to advance in the list to pick the next
2012 * timeout to use (skip the already expired ones) and add this node back to
2013 * the splay tree again.
2015 * The splay tree only has each sessionhandle as a single node and the nearest
2016 * timeout is used to sort it on.
2018 static CURLMcode add_next_timeout(struct timeval now,
2019 struct Curl_multi *multi,
2020 struct SessionHandle *d)
2022 struct timeval *tv = &d->state.expiretime;
2023 struct curl_llist *list = d->state.timeoutlist;
2024 struct curl_llist_element *e;
2026 /* move over the timeout list for this specific handle and remove all
2027 timeouts that are now passed tense and store the next pending
2029 for(e = list->head; e; ) {
2030 struct curl_llist_element *n = e->next;
2031 long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
2033 /* remove outdated entry */
2034 Curl_llist_remove(list, e, NULL);
2036 /* the list is sorted so get out on the first mismatch */
2041 /* clear the expire times within the handles that we remove from the
2048 /* copy the first entry to 'tv' */
2049 memcpy(tv, e->ptr, sizeof(*tv));
2051 /* remove first entry from list */
2052 Curl_llist_remove(list, e, NULL);
2054 /* insert this node again into the splay */
2055 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2056 &d->state.timenode);
2062 static CURLMcode multi_socket(struct Curl_multi *multi,
2066 int *running_handles)
2068 CURLMcode result = CURLM_OK;
2069 struct SessionHandle *data = NULL;
2070 struct Curl_tree *t;
2071 struct timeval now = Curl_tvnow();
2074 struct Curl_one_easy *easyp;
2075 /* *perform() deals with running_handles on its own */
2076 result = curl_multi_perform(multi, running_handles);
2078 /* walk through each easy handle and do the socket state change magic
2080 easyp=multi->easy.next;
2081 while(easyp != &multi->easy) {
2082 singlesocket(multi, easyp);
2083 easyp = easyp->next;
2086 /* or should we fall-through and do the timer-based stuff? */
2089 else if(s != CURL_SOCKET_TIMEOUT) {
2091 struct Curl_sh_entry *entry =
2092 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2095 /* Unmatched socket, we can't act on it but we ignore this fact. In
2096 real-world tests it has been proved that libevent can in fact give
2097 the application actions even though the socket was just previously
2098 asked to get removed, so thus we better survive stray socket actions
2099 and just move on. */
2104 if(data->magic != CURLEASY_MAGIC_NUMBER)
2105 /* bad bad bad bad bad bad bad */
2106 return CURLM_INTERNAL_ERROR;
2108 /* If the pipeline is enabled, take the handle which is in the head of
2109 the pipeline. If we should write into the socket, take the send_pipe
2110 head. If we should read from the socket, take the recv_pipe head. */
2111 if(data->set.one_easy->easy_conn) {
2112 if ((ev_bitmask & CURL_POLL_OUT) &&
2113 data->set.one_easy->easy_conn->send_pipe &&
2114 data->set.one_easy->easy_conn->send_pipe->head)
2115 data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
2116 else if ((ev_bitmask & CURL_POLL_IN) &&
2117 data->set.one_easy->easy_conn->recv_pipe &&
2118 data->set.one_easy->easy_conn->recv_pipe->head)
2119 data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
2122 if(data->set.one_easy->easy_conn) /* set socket event bitmask */
2123 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
2126 result = multi_runsingle(multi, now, data->set.one_easy);
2127 while (CURLM_CALL_MULTI_PERFORM == result);
2129 if(data->set.one_easy->easy_conn)
2130 data->set.one_easy->easy_conn->cselect_bits = 0;
2132 if(CURLM_OK >= result)
2133 /* get the socket(s) and check if the state has been changed since
2135 singlesocket(multi, data->set.one_easy);
2137 /* Now we fall-through and do the timer-based stuff, since we don't want
2138 to force the user to have to deal with timeouts as long as at least
2139 one connection in fact has traffic. */
2141 data = NULL; /* set data to NULL again to avoid calling
2142 multi_runsingle() in case there's no need to */
2146 now.tv_usec += 40000; /* compensate for bad precision timers that might've
2147 triggered too early */
2148 if(now.tv_usec >= 1000000) {
2150 now.tv_usec -= 1000000;
2154 * The loop following here will go on as long as there are expire-times left
2155 * to process in the splay and 'data' will be re-assigned for every expired
2156 * handle we deal with.
2159 /* the first loop lap 'data' can be NULL */
2162 result = multi_runsingle(multi, now, data->set.one_easy);
2163 while (CURLM_CALL_MULTI_PERFORM == result);
2165 if(CURLM_OK >= result)
2166 /* get the socket(s) and check if the state has been changed since
2168 singlesocket(multi, data->set.one_easy);
2171 /* Check if there's one (more) expired timer to deal with! This function
2172 extracts a matching node if there is one */
2174 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2176 data = t->payload; /* assign this for next loop */
2177 (void)add_next_timeout(now, multi, t->payload);
2182 *running_handles = multi->num_alive;
2186 #undef curl_multi_setopt
2187 CURLMcode curl_multi_setopt(CURLM *multi_handle,
2188 CURLMoption option, ...)
2190 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2191 CURLMcode res = CURLM_OK;
2194 if(!GOOD_MULTI_HANDLE(multi))
2195 return CURLM_BAD_HANDLE;
2197 va_start(param, option);
2200 case CURLMOPT_SOCKETFUNCTION:
2201 multi->socket_cb = va_arg(param, curl_socket_callback);
2203 case CURLMOPT_SOCKETDATA:
2204 multi->socket_userp = va_arg(param, void *);
2206 case CURLMOPT_PIPELINING:
2207 multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
2209 case CURLMOPT_TIMERFUNCTION:
2210 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2212 case CURLMOPT_TIMERDATA:
2213 multi->timer_userp = va_arg(param, void *);
2215 case CURLMOPT_MAXCONNECTS:
2216 multi->maxconnects = va_arg(param, long);
2219 res = CURLM_UNKNOWN_OPTION;
2226 /* we define curl_multi_socket() in the public multi.h header */
2227 #undef curl_multi_socket
2229 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
2230 int *running_handles)
2232 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2233 0, running_handles);
2234 if(CURLM_OK >= result)
2235 update_timer((struct Curl_multi *)multi_handle);
2239 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
2240 int ev_bitmask, int *running_handles)
2242 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
2243 ev_bitmask, running_handles);
2244 if(CURLM_OK >= result)
2245 update_timer((struct Curl_multi *)multi_handle);
2249 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
2252 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
2253 TRUE, CURL_SOCKET_BAD, 0, running_handles);
2254 if(CURLM_OK >= result)
2255 update_timer((struct Curl_multi *)multi_handle);
2259 static CURLMcode multi_timeout(struct Curl_multi *multi,
2262 static struct timeval tv_zero = {0,0};
2264 if(multi->timetree) {
2265 /* we have a tree of expire times */
2266 struct timeval now = Curl_tvnow();
2268 /* splay the lowest to the bottom */
2269 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2271 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2272 /* some time left before expiration */
2273 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
2276 * Since we only provide millisecond resolution on the returned value
2277 * and the diff might be less than one millisecond here, we don't
2278 * return zero as that may cause short bursts of busyloops on fast
2279 * processors while the diff is still present but less than one
2280 * millisecond! instead we return 1 until the time is ripe.
2285 /* 0 means immediately */
2294 CURLMcode curl_multi_timeout(CURLM *multi_handle,
2297 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2299 /* First, make some basic checks that the CURLM handle is a good handle */
2300 if(!GOOD_MULTI_HANDLE(multi))
2301 return CURLM_BAD_HANDLE;
2303 return multi_timeout(multi, timeout_ms);
2307 * Tell the application it should update its timers, if it subscribes to the
2308 * update timer callback.
2310 static int update_timer(struct Curl_multi *multi)
2314 if(!multi->timer_cb)
2316 if(multi_timeout(multi, &timeout_ms)) {
2319 if( timeout_ms < 0 ) {
2320 static const struct timeval none={0,0};
2321 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2322 multi->timer_lastcall = none;
2323 /* there's no timeout now but there was one previously, tell the app to
2325 return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
2330 /* When multi_timeout() is done, multi->timetree points to the node with the
2331 * timeout we got the (relative) time-out time for. We can thus easily check
2332 * if this is the same (fixed) time as we got in a previous call and then
2333 * avoid calling the callback again. */
2334 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2337 multi->timer_lastcall = multi->timetree->key;
2339 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
2342 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
2343 struct connectdata *conn)
2345 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2346 struct curl_llist_element *sendhead = conn->send_pipe->head;
2347 struct curl_llist *pipeline;
2350 if(!Curl_isPipeliningEnabled(handle) ||
2352 pipeline = conn->send_pipe;
2354 if(conn->server_supports_pipelining &&
2355 pipeLen < MAX_PIPELINE_LENGTH)
2356 pipeline = conn->send_pipe;
2358 pipeline = conn->pend_pipe;
2361 rc = Curl_addHandleToPipeline(handle, pipeline);
2363 if (pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
2364 /* this is a new one as head, expire it */
2365 conn->writechannel_inuse = FALSE; /* not in use yet */
2366 infof(conn->data, "%p is at send pipe head!\n",
2367 conn->send_pipe->head->ptr);
2368 Curl_expire(conn->send_pipe->head->ptr, 1);
2374 static int checkPendPipeline(struct connectdata *conn)
2377 struct curl_llist_element *sendhead = conn->send_pipe->head;
2379 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
2380 if (conn->server_supports_pipelining || pipeLen == 0) {
2381 struct curl_llist_element *curr = conn->pend_pipe->head;
2382 const size_t maxPipeLen =
2383 conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1;
2385 while(pipeLen < maxPipeLen && curr) {
2386 Curl_llist_move(conn->pend_pipe, curr,
2387 conn->send_pipe, conn->send_pipe->tail);
2388 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
2389 ++result; /* count how many handles we moved */
2390 curr = conn->pend_pipe->head;
2396 conn->now = Curl_tvnow();
2397 /* something moved, check for a new send pipeline leader */
2398 if(sendhead != conn->send_pipe->head) {
2399 /* this is a new one as head, expire it */
2400 conn->writechannel_inuse = FALSE; /* not in use yet */
2401 infof(conn->data, "%p is at send pipe head!\n",
2402 conn->send_pipe->head->ptr);
2403 Curl_expire(conn->send_pipe->head->ptr, 1);
2410 /* Move this transfer from the sending list to the receiving list.
2412 Pay special attention to the new sending list "leader" as it needs to get
2413 checked to update what sockets it acts on.
2416 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2417 struct connectdata *conn)
2419 struct curl_llist_element *curr;
2421 curr = conn->send_pipe->head;
2423 if(curr->ptr == handle) {
2424 Curl_llist_move(conn->send_pipe, curr,
2425 conn->recv_pipe, conn->recv_pipe->tail);
2427 if(conn->send_pipe->head) {
2428 /* Since there's a new easy handle at the start of the send pipeline,
2429 set its timeout value to 1ms to make it trigger instantly */
2430 conn->writechannel_inuse = FALSE; /* not used now */
2431 infof(conn->data, "%p is at send pipe head B!\n",
2432 conn->send_pipe->head->ptr);
2433 Curl_expire(conn->send_pipe->head->ptr, 1);
2436 /* The receiver's list is not really interesting here since either this
2437 handle is now first in the list and we'll deal with it soon, or
2438 another handle is already first and thus is already taken care of */
2440 break; /* we're done! */
2446 static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle,
2447 struct connectdata *conn)
2449 struct curl_llist_element *curr;
2451 curr = conn->recv_pipe->head;
2453 if(curr->ptr == handle) {
2454 Curl_llist_move(conn->recv_pipe, curr,
2455 conn->done_pipe, conn->done_pipe->tail);
2461 static bool isHandleAtHead(struct SessionHandle *handle,
2462 struct curl_llist *pipeline)
2464 struct curl_llist_element *curr = pipeline->head;
2466 return (bool)(curr->ptr == handle);
2472 * multi_freetimeout()
2474 * Callback used by the llist system when a single timeout list entry is
2477 static void multi_freetimeout(void *user, void *entryptr)
2481 /* the entry was plain malloc()'ed */
2486 * multi_addtimeout()
2488 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2489 * of list is always the timeout nearest in time.
2493 multi_addtimeout(struct curl_llist *timeoutlist,
2494 struct timeval *stamp)
2496 struct curl_llist_element *e;
2497 struct timeval *timedup;
2498 struct curl_llist_element *prev = NULL;
2500 timedup = malloc(sizeof(*timedup));
2502 return CURLM_OUT_OF_MEMORY;
2504 /* copy the timestamp */
2505 memcpy(timedup, stamp, sizeof(*timedup));
2507 if(Curl_llist_count(timeoutlist)) {
2508 /* find the correct spot in the list */
2509 for(e = timeoutlist->head; e; e = e->next) {
2510 struct timeval *checktime = e->ptr;
2511 long diff = curlx_tvdiff(*checktime, *timedup);
2519 this is the first timeout on the list */
2521 if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
2523 return CURLM_OUT_OF_MEMORY;
2532 * given a number of milliseconds from now to use to set the 'act before
2533 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2535 * Note that the timeout will be added to a queue of timeouts if it defines a
2536 * moment in time that is later than the current head of queue.
2538 * Pass zero to clear all timeout values for this handle.
2540 void Curl_expire(struct SessionHandle *data, long milli)
2542 struct Curl_multi *multi = data->multi;
2543 struct timeval *nowp = &data->state.expiretime;
2546 /* this is only interesting for multi-interface using libcurl, and only
2547 while there is still a multi interface struct remaining! */
2552 /* No timeout, clear the time data. */
2553 if(nowp->tv_sec || nowp->tv_usec) {
2554 /* Since this is an cleared time, we must remove the previous entry from
2556 struct curl_llist *list = data->state.timeoutlist;
2558 rc = Curl_splayremovebyaddr(multi->timetree,
2559 &data->state.timenode,
2562 infof(data, "Internal error clearing splay node = %d\n", rc);
2564 /* flush the timeout list too */
2565 while(list->size > 0)
2566 Curl_llist_remove(list, list->tail, NULL);
2568 infof(data, "Expire cleared\n");
2577 set.tv_sec += milli/1000;
2578 set.tv_usec += (milli%1000)*1000;
2580 if(set.tv_usec >= 1000000) {
2582 set.tv_usec -= 1000000;
2585 if(nowp->tv_sec || nowp->tv_usec) {
2586 /* This means that the struct is added as a node in the splay tree.
2587 Compare if the new time is earlier, and only remove-old/add-new if it
2589 long diff = curlx_tvdiff(set, *nowp);
2591 /* the new expire time was later so just add it to the queue
2593 multi_addtimeout(data->state.timeoutlist, &set);
2597 /* the new time is newer than the presently set one, so add the current
2598 to the queue and update the head */
2599 multi_addtimeout(data->state.timeoutlist, nowp);
2601 /* Since this is an updated time, we must remove the previous entry from
2602 the splay tree first and then re-add the new value */
2603 rc = Curl_splayremovebyaddr(multi->timetree,
2604 &data->state.timenode,
2607 infof(data, "Internal error removing splay node = %d\n", rc);
2611 data->state.timenode.payload = data;
2612 multi->timetree = Curl_splayinsert(*nowp,
2614 &data->state.timenode);
2617 Curl_splayprint(multi->timetree, 0, TRUE);
2621 CURLMcode curl_multi_assign(CURLM *multi_handle,
2622 curl_socket_t s, void *hashp)
2624 struct Curl_sh_entry *there = NULL;
2625 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2627 if(s != CURL_SOCKET_BAD)
2628 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2631 return CURLM_BAD_SOCKET;
2633 there->socketp = hashp;
2638 static void multi_connc_remove_handle(struct Curl_multi *multi,
2639 struct SessionHandle *data)
2641 /* a connection in the connection cache pointing to the given 'data' ? */
2644 for(i=0; i< multi->connc->num; i++) {
2645 struct connectdata * conn = multi->connc->connects[i];
2647 if(conn && conn->data == data) {
2648 /* If this easy_handle was the last one in charge for one or more
2649 connections in the shared connection cache, we might need to keep
2650 this handle around until either A) the connection is closed and
2651 killed properly, or B) another easy_handle uses the connection.
2653 The reason why we need to have a easy_handle associated with a live
2654 connection is simply that some connections will need a handle to get
2655 closed down properly. Currently, the only connections that need to
2656 keep a easy_handle handle around are using FTP(S). Such connections
2657 have the PROT_CLOSEACTION bit set.
2659 Thus, we need to check for all connections in the shared cache that
2660 points to this handle and are using PROT_CLOSEACTION. If there's any,
2661 we need to add this handle to the list of "easy handles kept around
2662 for nice connection closures".
2665 if(conn->protocol & PROT_CLOSEACTION) {
2666 /* this handle is still being used by a shared connection and
2667 thus we leave it around for now */
2668 if(add_closure(multi, data) == CURLM_OK)
2669 data->state.shared_conn = multi;
2671 /* out of memory - so much for graceful shutdown */
2672 Curl_disconnect(conn, /* dead_connection */ FALSE);
2673 multi->connc->connects[i] = NULL;
2677 /* disconect the easy handle from the connection since the connection
2678 will now remain but this easy handle is going */
2684 /* Add the given data pointer to the list of 'closure handles' that are kept
2685 around only to be able to close some connections nicely - just make sure
2686 that this handle isn't already added, like for the cases when an easy
2687 handle is removed, added and removed again... */
2688 static CURLMcode add_closure(struct Curl_multi *multi,
2689 struct SessionHandle *data)
2691 struct closure *cl = multi->closure;
2692 struct closure *p = NULL;
2695 /* Before adding, scan through all the other currently kept handles and see
2696 if there are any connections still referring to them and kill them if
2703 for(i=0; i< multi->connc->num; i++) {
2704 if(multi->connc->connects[i] &&
2705 (multi->connc->connects[i]->data == cl->easy_handle)) {
2714 /* cl->easy_handle is now killable */
2716 /* unmark it as not having a connection around that uses it anymore */
2717 cl->easy_handle->state.shared_conn= NULL;
2719 if(cl->easy_handle->state.closed) {
2720 infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle);
2721 /* close handle only if curl_easy_cleanup() already has been called
2722 for this easy handle */
2723 Curl_close(cl->easy_handle);
2731 if(cl->easy_handle == data)
2741 cl = calloc(1, sizeof(struct closure));
2743 return CURLM_OUT_OF_MEMORY;
2745 cl->easy_handle = data;
2746 cl->next = multi->closure;
2747 multi->closure = cl;
2754 void Curl_multi_dump(const struct Curl_multi *multi_handle)
2756 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2757 struct Curl_one_easy *easy;
2759 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2760 multi->num_easy, multi->num_alive);
2761 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2762 if(easy->state < CURLM_STATE_COMPLETED) {
2763 /* only display handles that are not completed */
2764 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2765 (void *)easy->easy_handle,
2766 statename[easy->state], easy->numsocks);
2767 for(i=0; i < easy->numsocks; i++) {
2768 curl_socket_t s = easy->sockets[i];
2769 struct Curl_sh_entry *entry =
2770 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2772 fprintf(stderr, "%d ", (int)s);
2774 fprintf(stderr, "INTERNAL CONFUSION\n");
2777 fprintf(stderr, "[%s %s] ",
2778 entry->action&CURL_POLL_IN?"RECVING":"",
2779 entry->action&CURL_POLL_OUT?"SENDING":"");
2782 fprintf(stderr, "\n");