Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl / multi.c
blob7b9ad7c2a47274102d8fb5d9e9f144f24af8f2fd
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, 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 * $Id: multi.c,v 1.2 2007/03/15 19:22:13 andy Exp $
22 ***************************************************************************/
24 #include "setup.h"
25 #include <stdlib.h>
26 #include <string.h>
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
38 #include <curl/curl.h>
40 #include "urldata.h"
41 #include "transfer.h"
42 #include "url.h"
43 #include "connect.h"
44 #include "progress.h"
45 #include "memory.h"
46 #include "easyif.h"
47 #include "multiif.h"
48 #include "sendf.h"
49 #include "timeval.h"
51 /* The last #include file should be: */
52 #include "memdebug.h"
54 struct Curl_message {
55 /* the 'CURLMsg' is the part that is visible to the external user */
56 struct CURLMsg extmsg;
57 struct Curl_message *next;
60 typedef enum {
61 CURLM_STATE_INIT, /* start in this state */
62 CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
63 CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
64 CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
65 CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect
66 phase */
67 CURLM_STATE_WAITDO, /* wait for our turn to send the request */
68 CURLM_STATE_DO, /* start send off the request (part 1) */
69 CURLM_STATE_DOING, /* sending off the request (part 1) */
70 CURLM_STATE_DO_MORE, /* send off the request (part 2) */
71 CURLM_STATE_DO_DONE, /* done sending off request */
72 CURLM_STATE_WAITPERFORM, /* wait for our turn to read the response */
73 CURLM_STATE_PERFORM, /* transfer data */
74 CURLM_STATE_TOOFAST, /* wait because limit-rate exceeded */
75 CURLM_STATE_DONE, /* post data transfer operation */
76 CURLM_STATE_COMPLETED, /* operation complete */
77 CURLM_STATE_CANCELLED, /* cancelled */
79 CURLM_STATE_LAST /* not a true state, never use this */
80 } CURLMstate;
82 /* we support N sockets per easy handle. Set the corresponding bit to what
83 action we should wait for */
84 #define MAX_SOCKSPEREASYHANDLE 5
85 #define GETSOCK_READABLE (0x00ff)
86 #define GETSOCK_WRITABLE (0xff00)
88 struct closure {
89 struct closure *next; /* a simple one-way list of structs */
90 struct SessionHandle *easy_handle;
93 struct Curl_one_easy {
94 /* first, two fields for the linked list of these */
95 struct Curl_one_easy *next;
96 struct Curl_one_easy *prev;
98 struct SessionHandle *easy_handle; /* the easy handle for this unit */
99 struct connectdata *easy_conn; /* the "unit's" connection */
101 CURLMstate state; /* the handle's state */
102 CURLcode result; /* previous result */
104 struct Curl_message *msg; /* A pointer to one single posted message.
105 Cleanup should be done on this pointer NOT on
106 the linked list in Curl_multi. This message
107 will be deleted when this handle is removed
108 from the multi-handle */
109 int msg_num; /* number of messages left in 'msg' to return */
111 /* Array with the plain socket numbers this handle takes care of, in no
112 particular order. Note that all sockets are added to the sockhash, where
113 the state etc are also kept. This array is mostly used to detect when a
114 socket is to be removed from the hash. See singlesocket(). */
115 curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
116 int numsocks;
119 #define CURL_MULTI_HANDLE 0x000bab1e
121 #define GOOD_MULTI_HANDLE(x) \
122 ((x)&&(((struct Curl_multi *)x)->type == CURL_MULTI_HANDLE))
123 #define GOOD_EASY_HANDLE(x) \
124 (((struct SessionHandle *)x)->magic == CURLEASY_MAGIC_NUMBER)
126 /* This is the struct known as CURLM on the outside */
127 struct Curl_multi {
128 /* First a simple identifier to easier detect if a user mix up
129 this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
130 long type;
132 /* We have a linked list with easy handles */
133 struct Curl_one_easy easy;
135 int num_easy; /* amount of entries in the linked list above. */
136 int num_msgs; /* amount of messages in the easy handles */
137 int num_alive; /* amount of easy handles that are added but have not yet
138 reached COMPLETE state */
140 /* callback function and user data pointer for the *socket() API */
141 curl_socket_callback socket_cb;
142 void *socket_userp;
144 /* Hostname cache */
145 struct curl_hash *hostcache;
147 /* timetree points to the splay-tree of time nodes to figure out expire
148 times of all currently set timers */
149 struct Curl_tree *timetree;
151 /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
152 the pluralis form, there can be more than one easy handle waiting on the
153 same actual socket) */
154 struct curl_hash *sockhash;
156 /* Whether pipelining is enabled for this multi handle */
157 bool pipelining_enabled;
159 /* shared connection cache */
160 struct conncache *connc;
162 /* list of easy handles kept around for doing nice connection closures */
163 struct closure *closure;
165 /* timer callback and user data pointer for the *socket() API */
166 curl_multi_timer_callback timer_cb;
167 void *timer_userp;
168 time_t timer_lastcall; /* the fixed time for the timeout for the previous
169 callback */
172 static bool multi_conn_using(struct Curl_multi *multi,
173 struct SessionHandle *data);
174 static void singlesocket(struct Curl_multi *multi,
175 struct Curl_one_easy *easy);
176 static void add_closure(struct Curl_multi *multi,
177 struct SessionHandle *data);
178 static int update_timer(struct Curl_multi *multi);
180 #ifdef CURLDEBUG
181 static const char *statename[]={
182 "INIT",
183 "CONNECT",
184 "WAITRESOLVE",
185 "WAITCONNECT",
186 "PROTOCONNECT",
187 "WAITDO",
188 "DO",
189 "DOING",
190 "DO_MORE",
191 "DO_DONE",
192 "WAITPERFORM",
193 "PERFORM",
194 "TOOFAST",
195 "DONE",
196 "COMPLETED",
197 "CANCELLED"
200 void curl_multi_dump(CURLM *multi_handle);
201 #endif
203 /* always use this function to change state, to make debugging easier */
204 static void multistate(struct Curl_one_easy *easy, CURLMstate state)
206 #ifdef CURLDEBUG
207 long index = -1;
208 #endif
209 CURLMstate oldstate = easy->state;
211 if(oldstate == state)
212 /* don't bother when the new state is the same as the old state */
213 return;
215 easy->state = state;
217 #ifdef CURLDEBUG
218 if(easy->state > CURLM_STATE_CONNECT &&
219 easy->state < CURLM_STATE_COMPLETED)
220 index = easy->easy_conn->connectindex;
222 infof(easy->easy_handle,
223 "STATE: %s => %s handle %p; (connection #%ld) \n",
224 statename[oldstate], statename[easy->state],
225 (char *)easy, index);
226 #endif
227 if(state == CURLM_STATE_COMPLETED)
228 /* changing to COMPLETED means there's one less easy handle 'alive' */
229 easy->easy_handle->multi->num_alive--;
233 * We add one of these structs to the sockhash for a particular socket
236 struct Curl_sh_entry {
237 struct SessionHandle *easy;
238 time_t timestamp;
239 long inuse;
240 int action; /* what action READ/WRITE this socket waits for */
241 curl_socket_t socket; /* mainly to ease debugging */
242 void *socketp; /* settable by users with curl_multi_assign() */
244 /* bits for 'action' having no bits means this socket is not expecting any
245 action */
246 #define SH_READ 1
247 #define SH_WRITE 2
249 /* make sure this socket is present in the hash for this handle */
250 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
251 curl_socket_t s,
252 struct SessionHandle *data)
254 struct Curl_sh_entry *there =
255 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
256 struct Curl_sh_entry *check;
258 if(there)
259 /* it is present, return fine */
260 return there;
262 /* not present, add it */
263 check = calloc(sizeof(struct Curl_sh_entry), 1);
264 if(!check)
265 return NULL; /* major failure */
266 check->easy = data;
267 check->socket = s;
269 /* make/add new hash entry */
270 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
271 free(check);
272 return NULL; /* major failure */
275 return check; /* things are good in sockhash land */
279 /* delete the given socket + handle from the hash */
280 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
282 struct Curl_sh_entry *there =
283 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
285 if(there) {
286 /* this socket is in the hash */
287 /* We remove the hash entry. (This'll end up in a call to
288 sh_freeentry().) */
289 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
294 * free a sockhash entry
296 static void sh_freeentry(void *freethis)
298 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
300 free(p);
304 * sh_init() creates a new socket hash and returns the handle for it.
306 * Quote from README.multi_socket:
308 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
309 * is somewhat of a bottle neck. Its current implementation may be a bit too
310 * limiting. It simply has a fixed-size array, and on each entry in the array
311 * it has a linked list with entries. So the hash only checks which list to
312 * scan through. The code I had used so for used a list with merely 7 slots
313 * (as that is what the DNS hash uses) but with 7000 connections that would
314 * make an average of 1000 nodes in each list to run through. I upped that to
315 * 97 slots (I believe a prime is suitable) and noticed a significant speed
316 * increase. I need to reconsider the hash implementation or use a rather
317 * large default value like this. At 9000 connections I was still below 10us
318 * per call."
321 static struct curl_hash *sh_init(void)
323 return Curl_hash_alloc(97, sh_freeentry);
326 CURLM *curl_multi_init(void)
328 struct Curl_multi *multi = (void *)calloc(sizeof(struct Curl_multi), 1);
330 if(!multi)
331 return NULL;
333 multi->type = CURL_MULTI_HANDLE;
335 multi->hostcache = Curl_mk_dnscache();
336 if(!multi->hostcache) {
337 /* failure, free mem and bail out */
338 free(multi);
339 return NULL;
342 multi->sockhash = sh_init();
343 if(!multi->sockhash) {
344 /* failure, free mem and bail out */
345 Curl_hash_destroy(multi->hostcache);
346 free(multi);
347 return NULL;
350 multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1);
351 if(!multi->connc) {
352 Curl_hash_destroy(multi->hostcache);
353 free(multi);
354 return NULL;
357 return (CURLM *) multi;
360 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
361 CURL *easy_handle)
363 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
364 struct Curl_one_easy *easy;
365 struct closure *cl;
366 struct closure *prev=NULL;
368 /* First, make some basic checks that the CURLM handle is a good handle */
369 if(!GOOD_MULTI_HANDLE(multi))
370 return CURLM_BAD_HANDLE;
372 /* Verify that we got a somewhat good easy handle too */
373 if(!GOOD_EASY_HANDLE(easy_handle))
374 return CURLM_BAD_EASY_HANDLE;
376 /* Prevent users to add the same handle more than once! */
377 if(((struct SessionHandle *)easy_handle)->multi)
378 /* possibly we should create a new unique error code for this condition */
379 return CURLM_BAD_EASY_HANDLE;
381 /* Now, time to add an easy handle to the multi stack */
382 easy = (struct Curl_one_easy *)calloc(sizeof(struct Curl_one_easy), 1);
383 if(!easy)
384 return CURLM_OUT_OF_MEMORY;
386 cl = multi->closure;
387 while(cl) {
388 struct closure *next = cl->next;
389 if(cl->easy_handle == (struct SessionHandle *)easy_handle) {
390 /* remove this handle from the closure list */
391 free(cl);
392 if(prev)
393 prev->next = next;
394 else
395 multi->closure = next;
396 break; /* no need to continue since this handle can only be present once
397 in the list */
399 cl = next;
402 /* set the easy handle */
403 easy->easy_handle = easy_handle;
404 multistate(easy, CURLM_STATE_INIT);
406 /* for multi interface connections, we share DNS cache automatically if the
407 easy handle's one is currently private. */
408 if (easy->easy_handle->dns.hostcache &&
409 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
410 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
411 easy->easy_handle->dns.hostcache = NULL;
412 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
415 if (!easy->easy_handle->dns.hostcache ||
416 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
417 easy->easy_handle->dns.hostcache = multi->hostcache;
418 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
421 if(easy->easy_handle->state.connc) {
422 if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) {
423 /* kill old private version */
424 Curl_rm_connc(easy->easy_handle->state.connc);
425 /* point out our shared one instead */
426 easy->easy_handle->state.connc = multi->connc;
428 /* else it is already using multi? */
430 else
431 /* point out our shared one */
432 easy->easy_handle->state.connc = multi->connc;
434 /* Make sure the type is setup correctly */
435 easy->easy_handle->state.connc->type = CONNCACHE_MULTI;
437 /* We add this new entry first in the list. We make our 'next' point to the
438 previous next and our 'prev' point back to the 'first' struct */
439 easy->next = multi->easy.next;
440 easy->prev = &multi->easy;
442 /* make 'easy' the first node in the chain */
443 multi->easy.next = easy;
445 /* if there was a next node, make sure its 'prev' pointer links back to
446 the new node */
447 if(easy->next)
448 easy->next->prev = easy;
450 Curl_easy_addmulti(easy_handle, multi_handle);
452 /* make the SessionHandle struct refer back to this struct */
453 easy->easy_handle->set.one_easy = easy;
455 /* increase the node-counter */
456 multi->num_easy++;
458 if((multi->num_easy * 4) > multi->connc->num) {
459 /* We want the connection cache to have plenty room. Before we supported
460 the shared cache every single easy handle had 5 entries in their cache
461 by default. */
462 CURLcode res = Curl_ch_connc(easy_handle, multi->connc,
463 multi->connc->num*4);
464 if(res != CURLE_OK)
465 /* TODO: we need to do some cleaning up here! */
466 return CURLM_OUT_OF_MEMORY;
469 /* increase the alive-counter */
470 multi->num_alive++;
472 update_timer(multi);
473 return CURLM_OK;
476 #if 0
477 /* Debug-function, used like this:
479 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
481 * Enable the hash print function first by editing hash.c
483 static void debug_print_sock_hash(void *p)
485 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
487 fprintf(stderr, " [easy %p/magic %x/socket %d]",
488 (void *)sh->easy, sh->easy->magic, sh->socket);
490 #endif
492 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
493 CURL *curl_handle)
495 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
496 struct Curl_one_easy *easy;
498 /* First, make some basic checks that the CURLM handle is a good handle */
499 if(!GOOD_MULTI_HANDLE(multi))
500 return CURLM_BAD_HANDLE;
502 /* Verify that we got a somewhat good easy handle too */
503 if(!GOOD_EASY_HANDLE(curl_handle))
504 return CURLM_BAD_EASY_HANDLE;
506 /* scan through the list and remove the 'curl_handle' */
507 easy = multi->easy.next;
508 while(easy) {
509 if(easy->easy_handle == (struct SessionHandle *)curl_handle)
510 break;
511 easy=easy->next;
514 if(easy) {
515 bool premature = (bool)(easy->state != CURLM_STATE_COMPLETED);
517 /* If the 'state' is not INIT or COMPLETED, we might need to do something
518 nice to put the easy_handle in a good known state when this returns. */
519 if(premature)
520 /* this handle is "alive" so we need to count down the total number of
521 alive connections when this is removed */
522 multi->num_alive--;
524 if (easy->easy_handle->state.is_in_pipeline &&
525 easy->state > CURLM_STATE_DO) {
526 /* If the handle is in a pipeline and has finished sending off its
527 request, we need to remember the fact that we want to remove this
528 handle but do the actual removal at a later time */
529 easy->easy_handle->state.cancelled = TRUE;
530 return CURLM_OK;
533 /* The timer must be shut down before easy->multi is set to NULL,
534 else the timenode will remain in the splay tree after
535 curl_easy_cleanup is called. */
536 Curl_expire(easy->easy_handle, 0);
538 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
539 /* clear out the usage of the shared DNS cache */
540 easy->easy_handle->dns.hostcache = NULL;
541 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
544 /* if we have a connection we must call Curl_done() here so that we
545 don't leave a half-baked one around */
546 if(easy->easy_conn) {
547 /* Set up the association right */
548 easy->easy_conn->data = easy->easy_handle;
550 /* Curl_done() clears the conn->data field to lose the association
551 between the easy handle and the connection */
552 Curl_done(&easy->easy_conn, easy->result, premature);
554 if(easy->easy_conn)
555 /* the connection is still alive, set back the association to enable
556 the check below to trigger TRUE */
557 easy->easy_conn->data = easy->easy_handle;
560 /* If this easy_handle was the last one in charge for one or more
561 connections a the shared connection cache, we might need to keep this
562 handle around until either A) the connection is closed and killed
563 properly, or B) another easy_handle uses the connection.
565 The reason why we need to have a easy_handle associated with a live
566 connection is simply that some connections will need a handle to get
567 closed down properly. Currently, the only connections that need to keep
568 a easy_handle handle around are using FTP(S). Such connections have
569 the PROT_CLOSEACTION bit set.
571 Thus, we need to check for all connections in the shared cache that
572 points to this handle and are using PROT_CLOSEACTION. If there's any,
573 we need to add this handle to the list of "easy handles kept around for
574 nice connection closures".
576 if(multi_conn_using(multi, easy->easy_handle)) {
577 /* There's at least one connection using this handle so we must keep
578 this handle around. We also keep the connection cache pointer
579 pointing to the shared one since that will be used on close as
580 well. */
581 easy->easy_handle->state.shared_conn = multi;
583 /* this handle is still being used by a shared connection cache and
584 thus we leave it around for now */
585 add_closure(multi, easy->easy_handle);
588 if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
589 /* if this was using the shared connection cache we clear the pointer
590 to that since we're not part of that handle anymore */
591 easy->easy_handle->state.connc = NULL;
593 /* and modify the connectindex since this handle can't point to the
594 connection cache anymore */
595 if(easy->easy_conn)
596 easy->easy_conn->connectindex = -1;
599 /* change state without using multistate(), only to make singlesocket() do
600 what we want */
601 easy->state = CURLM_STATE_COMPLETED;
602 singlesocket(multi, easy); /* to let the application know what sockets
603 that vanish with this handle */
605 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
606 to this multi handle */
608 /* make the previous node point to our next */
609 if(easy->prev)
610 easy->prev->next = easy->next;
611 /* make our next point to our previous node */
612 if(easy->next)
613 easy->next->prev = easy->prev;
615 easy->easy_handle->set.one_easy = NULL; /* detached */
617 /* NOTE NOTE NOTE
618 We do not touch the easy handle here! */
619 if (easy->msg)
620 free(easy->msg);
621 free(easy);
623 multi->num_easy--; /* one less to care about now */
625 update_timer(multi);
626 return CURLM_OK;
628 else
629 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
632 bool Curl_multi_canPipeline(struct Curl_multi* multi)
634 return multi->pipelining_enabled;
637 static int waitconnect_getsock(struct connectdata *conn,
638 curl_socket_t *sock,
639 int numsocks)
641 if(!numsocks)
642 return GETSOCK_BLANK;
644 sock[0] = conn->sock[FIRSTSOCKET];
645 return GETSOCK_WRITESOCK(0);
648 static int domore_getsock(struct connectdata *conn,
649 curl_socket_t *sock,
650 int numsocks)
652 if(!numsocks)
653 return GETSOCK_BLANK;
655 /* When in DO_MORE state, we could be either waiting for us
656 to connect to a remote site, or we could wait for that site
657 to connect to us. It makes a difference in the way: if we
658 connect to the site we wait for the socket to become writable, if
659 the site connects to us we wait for it to become readable */
660 sock[0] = conn->sock[SECONDARYSOCKET];
662 return GETSOCK_WRITESOCK(0);
665 /* returns bitmapped flags for this handle and its sockets */
666 static int multi_getsock(struct Curl_one_easy *easy,
667 curl_socket_t *socks, /* points to numsocks number
668 of sockets */
669 int numsocks)
671 if (easy->easy_handle->state.pipe_broke) {
672 return 0;
675 if (easy->state > CURLM_STATE_CONNECT &&
676 easy->state < CURLM_STATE_COMPLETED) {
677 /* Set up ownership correctly */
678 easy->easy_conn->data = easy->easy_handle;
681 switch(easy->state) {
682 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
683 default:
684 /* this will get called with CURLM_STATE_COMPLETED when a handle is
685 removed */
686 return 0;
688 case CURLM_STATE_WAITRESOLVE:
689 return Curl_resolv_getsock(easy->easy_conn, socks, numsocks);
691 case CURLM_STATE_PROTOCONNECT:
692 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
694 case CURLM_STATE_DOING:
695 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
697 case CURLM_STATE_WAITCONNECT:
698 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
700 case CURLM_STATE_DO_MORE:
701 return domore_getsock(easy->easy_conn, socks, numsocks);
703 case CURLM_STATE_PERFORM:
704 case CURLM_STATE_WAITPERFORM:
705 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
710 CURLMcode curl_multi_fdset(CURLM *multi_handle,
711 fd_set *read_fd_set, fd_set *write_fd_set,
712 fd_set *exc_fd_set, int *max_fd)
714 /* Scan through all the easy handles to get the file descriptors set.
715 Some easy handles may not have connected to the remote host yet,
716 and then we must make sure that is done. */
717 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
718 struct Curl_one_easy *easy;
719 int this_max_fd=-1;
720 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
721 int bitmap;
722 int i;
723 (void)exc_fd_set; /* not used */
725 if(!GOOD_MULTI_HANDLE(multi))
726 return CURLM_BAD_HANDLE;
728 easy=multi->easy.next;
729 while(easy) {
730 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
732 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
733 curl_socket_t s = CURL_SOCKET_BAD;
735 if(bitmap & GETSOCK_READSOCK(i)) {
736 FD_SET(sockbunch[i], read_fd_set);
737 s = sockbunch[i];
739 if(bitmap & GETSOCK_WRITESOCK(i)) {
740 FD_SET(sockbunch[i], write_fd_set);
741 s = sockbunch[i];
743 if(s == CURL_SOCKET_BAD)
744 /* this socket is unused, break out of loop */
745 break;
746 else {
747 if((int)s > this_max_fd)
748 this_max_fd = (int)s;
752 easy = easy->next; /* check next handle */
755 *max_fd = this_max_fd;
757 return CURLM_OK;
760 static CURLMcode multi_runsingle(struct Curl_multi *multi,
761 struct Curl_one_easy *easy)
763 struct Curl_message *msg = NULL;
764 bool connected;
765 bool async;
766 bool protocol_connect;
767 bool dophase_done;
768 bool done;
769 CURLMcode result = CURLM_OK;
770 struct Curl_transfer_keeper *k;
772 do {
774 if(!GOOD_EASY_HANDLE(easy->easy_handle))
775 return CURLM_BAD_EASY_HANDLE;
777 if (easy->easy_handle->state.pipe_broke) {
778 infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n",
779 easy, easy->easy_handle->reqdata.path);
780 if(easy->easy_handle->state.is_in_pipeline) {
781 /* Head back to the CONNECT state */
782 multistate(easy, CURLM_STATE_CONNECT);
783 result = CURLM_CALL_MULTI_PERFORM;
784 easy->result = CURLE_OK;
785 } else {
786 easy->result = CURLE_COULDNT_CONNECT;
787 multistate(easy, CURLM_STATE_COMPLETED);
790 easy->easy_handle->state.pipe_broke = FALSE;
791 easy->easy_conn = NULL;
792 break;
795 if (easy->state > CURLM_STATE_CONNECT &&
796 easy->state < CURLM_STATE_COMPLETED) {
797 /* Make sure we set the connection's current owner */
798 easy->easy_conn->data = easy->easy_handle;
801 if (CURLM_STATE_WAITCONNECT <= easy->state &&
802 easy->state <= CURLM_STATE_DO &&
803 easy->easy_handle->change.url_changed) {
804 char *gotourl;
805 Curl_posttransfer(easy->easy_handle);
807 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
808 /* We make sure that the pipe broken flag is reset
809 because in this case, it isn't an actual break */
810 easy->easy_handle->state.pipe_broke = FALSE;
811 if(CURLE_OK == easy->result) {
812 gotourl = strdup(easy->easy_handle->change.url);
813 if(gotourl) {
814 easy->easy_handle->change.url_changed = FALSE;
815 easy->result = Curl_follow(easy->easy_handle, gotourl, FALSE);
816 if(CURLE_OK == easy->result)
817 multistate(easy, CURLM_STATE_CONNECT);
818 else
819 free(gotourl);
821 else {
822 easy->result = CURLE_OUT_OF_MEMORY;
823 multistate(easy, CURLM_STATE_COMPLETED);
824 break;
829 easy->easy_handle->change.url_changed = FALSE;
831 switch(easy->state) {
832 case CURLM_STATE_INIT:
833 /* init this transfer. */
834 easy->result=Curl_pretransfer(easy->easy_handle);
836 if(CURLE_OK == easy->result) {
837 /* after init, go CONNECT */
838 multistate(easy, CURLM_STATE_CONNECT);
839 result = CURLM_CALL_MULTI_PERFORM;
841 easy->easy_handle->state.used_interface = Curl_if_multi;
843 break;
845 case CURLM_STATE_CONNECT:
846 /* Connect. We get a connection identifier filled in. */
847 Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
848 easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
849 &async, &protocol_connect);
851 if(CURLE_OK == easy->result) {
852 /* Add this handle to the send pipeline */
853 Curl_addHandleToPipeline(easy->easy_handle,
854 easy->easy_conn->send_pipe);
856 if(async)
857 /* We're now waiting for an asynchronous name lookup */
858 multistate(easy, CURLM_STATE_WAITRESOLVE);
859 else {
860 /* after the connect has been sent off, go WAITCONNECT unless the
861 protocol connect is already done and we can go directly to
862 WAITDO! */
863 result = CURLM_CALL_MULTI_PERFORM;
865 if(protocol_connect) {
866 multistate(easy, CURLM_STATE_WAITDO);
867 } else {
868 multistate(easy, CURLM_STATE_WAITCONNECT);
872 break;
874 case CURLM_STATE_WAITRESOLVE:
875 /* awaiting an asynch name resolve to complete */
877 struct Curl_dns_entry *dns = NULL;
879 /* check if we have the name resolved by now */
880 easy->result = Curl_is_resolved(easy->easy_conn, &dns);
882 if(dns) {
883 /* Perform the next step in the connection phase, and then move on
884 to the WAITCONNECT state */
885 easy->result = Curl_async_resolved(easy->easy_conn,
886 &protocol_connect);
888 if(CURLE_OK != easy->result)
889 /* if Curl_async_resolved() returns failure, the connection struct
890 is already freed and gone */
891 easy->easy_conn = NULL; /* no more connection */
892 else {
893 /* call again please so that we get the next socket setup */
894 result = CURLM_CALL_MULTI_PERFORM;
895 if(protocol_connect)
896 multistate(easy, CURLM_STATE_DO);
897 else
898 multistate(easy, CURLM_STATE_WAITCONNECT);
902 if(CURLE_OK != easy->result) {
903 /* failure detected */
904 Curl_disconnect(easy->easy_conn); /* disconnect properly */
905 easy->easy_conn = NULL; /* no more connection */
906 break;
909 break;
911 case CURLM_STATE_WAITCONNECT:
912 /* awaiting a completion of an asynch connect */
913 easy->result = Curl_is_connected(easy->easy_conn,
914 FIRSTSOCKET,
915 &connected);
916 if(connected)
917 easy->result = Curl_protocol_connect(easy->easy_conn,
918 &protocol_connect);
920 if(CURLE_OK != easy->result) {
921 /* failure detected */
922 Curl_disconnect(easy->easy_conn); /* close the connection */
923 easy->easy_conn = NULL; /* no more connection */
924 break;
927 if(connected) {
928 if(!protocol_connect) {
929 /* We have a TCP connection, but 'protocol_connect' may be false
930 and then we continue to 'STATE_PROTOCONNECT'. If protocol
931 connect is TRUE, we move on to STATE_DO. */
932 multistate(easy, CURLM_STATE_PROTOCONNECT);
934 else {
935 /* after the connect has completed, go WAITDO */
936 multistate(easy, CURLM_STATE_WAITDO);
938 result = CURLM_CALL_MULTI_PERFORM;
941 break;
943 case CURLM_STATE_PROTOCONNECT:
944 /* protocol-specific connect phase */
945 easy->result = Curl_protocol_connecting(easy->easy_conn,
946 &protocol_connect);
947 if(protocol_connect) {
948 /* after the connect has completed, go WAITDO */
949 multistate(easy, CURLM_STATE_WAITDO);
950 result = CURLM_CALL_MULTI_PERFORM;
952 else if(easy->result) {
953 /* failure detected */
954 Curl_posttransfer(easy->easy_handle);
955 Curl_done(&easy->easy_conn, easy->result, FALSE);
956 Curl_disconnect(easy->easy_conn); /* close the connection */
957 easy->easy_conn = NULL; /* no more connection */
959 break;
961 case CURLM_STATE_WAITDO:
962 /* Wait for our turn to DO when we're pipelining requests */
963 #ifdef CURLDEBUG
964 infof(easy->easy_handle, "Conn %d send pipe %d inuse %d athead %d\n",
965 easy->easy_conn->connectindex,
966 easy->easy_conn->send_pipe->size,
967 easy->easy_conn->writechannel_inuse,
968 Curl_isHandleAtHead(easy->easy_handle,
969 easy->easy_conn->send_pipe));
970 #endif
971 if (!easy->easy_conn->writechannel_inuse &&
972 Curl_isHandleAtHead(easy->easy_handle,
973 easy->easy_conn->send_pipe)) {
974 /* Grab the channel */
975 easy->easy_conn->writechannel_inuse = TRUE;
976 multistate(easy, CURLM_STATE_DO);
977 result = CURLM_CALL_MULTI_PERFORM;
979 break;
981 case CURLM_STATE_DO:
982 if(easy->easy_handle->set.connect_only) {
983 /* keep connection open for application to use the socket */
984 easy->easy_conn->bits.close = FALSE;
985 multistate(easy, CURLM_STATE_DONE);
986 easy->result = CURLE_OK;
987 result = CURLM_OK;
989 else {
990 /* Perform the protocol's DO action */
991 easy->result = Curl_do(&easy->easy_conn,
992 &dophase_done);
994 if(CURLE_OK == easy->result) {
996 if(!dophase_done) {
997 /* DO was not completed in one function call, we must continue
998 DOING... */
999 multistate(easy, CURLM_STATE_DOING);
1000 result = CURLM_OK;
1003 /* after DO, go DO_DONE... or DO_MORE */
1004 else if(easy->easy_conn->bits.do_more) {
1005 /* we're supposed to do more, but we need to sit down, relax
1006 and wait a little while first */
1007 multistate(easy, CURLM_STATE_DO_MORE);
1008 result = CURLM_OK;
1010 else {
1011 /* we're done with the DO, now DO_DONE */
1012 easy->result = Curl_readwrite_init(easy->easy_conn);
1013 if(CURLE_OK == easy->result) {
1014 multistate(easy, CURLM_STATE_DO_DONE);
1015 result = CURLM_CALL_MULTI_PERFORM;
1019 else {
1020 /* failure detected */
1021 Curl_posttransfer(easy->easy_handle);
1022 Curl_done(&easy->easy_conn, easy->result, FALSE);
1023 Curl_disconnect(easy->easy_conn); /* close the connection */
1024 easy->easy_conn = NULL; /* no more connection */
1027 break;
1029 case CURLM_STATE_DOING:
1030 /* we continue DOING until the DO phase is complete */
1031 easy->result = Curl_protocol_doing(easy->easy_conn,
1032 &dophase_done);
1033 if(CURLE_OK == easy->result) {
1034 if(dophase_done) {
1035 /* after DO, go PERFORM... or DO_MORE */
1036 if(easy->easy_conn->bits.do_more) {
1037 /* we're supposed to do more, but we need to sit down, relax
1038 and wait a little while first */
1039 multistate(easy, CURLM_STATE_DO_MORE);
1040 result = CURLM_OK;
1042 else {
1043 /* we're done with the DO, now DO_DONE */
1044 easy->result = Curl_readwrite_init(easy->easy_conn);
1045 if(CURLE_OK == easy->result) {
1046 multistate(easy, CURLM_STATE_DO_DONE);
1047 result = CURLM_CALL_MULTI_PERFORM;
1050 } /* dophase_done */
1052 else {
1053 /* failure detected */
1054 Curl_posttransfer(easy->easy_handle);
1055 Curl_done(&easy->easy_conn, easy->result, FALSE);
1056 Curl_disconnect(easy->easy_conn); /* close the connection */
1057 easy->easy_conn = NULL; /* no more connection */
1059 break;
1061 case CURLM_STATE_DO_MORE:
1062 /* Ready to do more? */
1063 easy->result = Curl_is_connected(easy->easy_conn,
1064 SECONDARYSOCKET,
1065 &connected);
1066 if(connected) {
1068 * When we are connected, DO MORE and then go DO_DONE
1070 easy->result = Curl_do_more(easy->easy_conn);
1072 if(CURLE_OK == easy->result)
1073 easy->result = Curl_readwrite_init(easy->easy_conn);
1074 else
1075 /* Remove ourselves from the send pipeline */
1076 Curl_removeHandleFromPipeline(easy->easy_handle,
1077 easy->easy_conn->send_pipe);
1079 if(CURLE_OK == easy->result) {
1080 multistate(easy, CURLM_STATE_DO_DONE);
1081 result = CURLM_CALL_MULTI_PERFORM;
1084 break;
1086 case CURLM_STATE_DO_DONE:
1087 /* Remove ourselves from the send pipeline */
1088 Curl_removeHandleFromPipeline(easy->easy_handle,
1089 easy->easy_conn->send_pipe);
1090 /* Add ourselves to the recv pipeline */
1091 Curl_addHandleToPipeline(easy->easy_handle,
1092 easy->easy_conn->recv_pipe);
1093 multistate(easy, CURLM_STATE_WAITPERFORM);
1094 result = CURLM_CALL_MULTI_PERFORM;
1095 break;
1097 case CURLM_STATE_WAITPERFORM:
1098 #ifdef CURLDEBUG
1099 infof(easy->easy_handle, "Conn %d recv pipe %d inuse %d athead %d\n",
1100 easy->easy_conn->connectindex,
1101 easy->easy_conn->recv_pipe->size,
1102 easy->easy_conn->readchannel_inuse,
1103 Curl_isHandleAtHead(easy->easy_handle,
1104 easy->easy_conn->recv_pipe));
1105 #endif
1106 /* Wait for our turn to PERFORM */
1107 if (!easy->easy_conn->readchannel_inuse &&
1108 Curl_isHandleAtHead(easy->easy_handle,
1109 easy->easy_conn->recv_pipe)) {
1110 /* Grab the channel */
1111 easy->easy_conn->readchannel_inuse = TRUE;
1112 multistate(easy, CURLM_STATE_PERFORM);
1113 result = CURLM_CALL_MULTI_PERFORM;
1115 break;
1117 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1118 /* if both rates are within spec, resume transfer */
1119 Curl_pgrsUpdate(easy->easy_conn);
1120 if ( ( ( easy->easy_handle->set.max_send_speed == 0 ) ||
1121 ( easy->easy_handle->progress.ulspeed <
1122 easy->easy_handle->set.max_send_speed ) ) &&
1123 ( ( easy->easy_handle->set.max_recv_speed == 0 ) ||
1124 ( easy->easy_handle->progress.dlspeed <
1125 easy->easy_handle->set.max_recv_speed ) )
1127 multistate(easy, CURLM_STATE_PERFORM);
1128 break;
1130 case CURLM_STATE_PERFORM:
1131 /* check if over speed */
1132 if ( ( ( easy->easy_handle->set.max_send_speed > 0 ) &&
1133 ( easy->easy_handle->progress.ulspeed >
1134 easy->easy_handle->set.max_send_speed ) ) ||
1135 ( ( easy->easy_handle->set.max_recv_speed > 0 ) &&
1136 ( easy->easy_handle->progress.dlspeed >
1137 easy->easy_handle->set.max_recv_speed ) )
1139 /* Transfer is over the speed limit. Change state. TODO: Call
1140 * Curl_expire() with the time left until we're targeted to be below
1141 * the speed limit again. */
1142 multistate(easy, CURLM_STATE_TOOFAST );
1143 break;
1146 /* read/write data if it is ready to do so */
1147 easy->result = Curl_readwrite(easy->easy_conn, &done);
1149 k = &easy->easy_handle->reqdata.keep;
1151 if (!(k->keepon & KEEP_READ)) {
1152 /* We're done reading */
1153 easy->easy_conn->readchannel_inuse = FALSE;
1156 if (!(k->keepon & KEEP_WRITE)) {
1157 /* We're done writing */
1158 easy->easy_conn->writechannel_inuse = FALSE;
1161 if(easy->result) {
1162 /* The transfer phase returned error, we mark the connection to get
1163 * closed to prevent being re-used. This is becasue we can't
1164 * possibly know if the connection is in a good shape or not now. */
1165 easy->easy_conn->bits.close = TRUE;
1167 if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
1168 /* if we failed anywhere, we must clean up the secondary socket if
1169 it was used */
1170 sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
1171 easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
1173 Curl_posttransfer(easy->easy_handle);
1174 Curl_done(&easy->easy_conn, easy->result, FALSE);
1176 else if(TRUE == done) {
1177 char *newurl;
1178 bool retry = Curl_retry_request(easy->easy_conn, &newurl);
1180 /* call this even if the readwrite function returned error */
1181 Curl_posttransfer(easy->easy_handle);
1183 /* When we follow redirects, must to go back to the CONNECT state */
1184 if(easy->easy_handle->reqdata.newurl || retry) {
1185 Curl_removeHandleFromPipeline(easy->easy_handle,
1186 easy->easy_conn->recv_pipe);
1187 if(!retry) {
1188 /* if the URL is a follow-location and not just a retried request
1189 then figure out the URL here */
1190 newurl = easy->easy_handle->reqdata.newurl;
1191 easy->easy_handle->reqdata.newurl = NULL;
1193 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1194 if(easy->result == CURLE_OK)
1195 easy->result = Curl_follow(easy->easy_handle, newurl, retry);
1196 if(CURLE_OK == easy->result) {
1197 multistate(easy, CURLM_STATE_CONNECT);
1198 result = CURLM_CALL_MULTI_PERFORM;
1200 else
1201 /* Since we "took it", we are in charge of freeing this on
1202 failure */
1203 free(newurl);
1205 else {
1206 /* after the transfer is done, go DONE */
1207 multistate(easy, CURLM_STATE_DONE);
1208 result = CURLM_CALL_MULTI_PERFORM;
1212 break;
1214 case CURLM_STATE_DONE:
1215 /* Remove ourselves from the receive pipeline */
1216 Curl_removeHandleFromPipeline(easy->easy_handle,
1217 easy->easy_conn->recv_pipe);
1218 easy->easy_handle->state.is_in_pipeline = FALSE;
1220 if (easy->easy_conn->bits.stream_was_rewound) {
1221 /* This request read past its response boundary so we quickly
1222 let the other requests consume those bytes since there is no
1223 guarantee that the socket will become active again */
1224 result = CURLM_CALL_MULTI_PERFORM;
1227 if (!easy->easy_handle->state.cancelled) {
1228 /* post-transfer command */
1229 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1231 /* after we have DONE what we're supposed to do, go COMPLETED, and
1232 it doesn't matter what the Curl_done() returned! */
1233 multistate(easy, CURLM_STATE_COMPLETED);
1236 break;
1238 case CURLM_STATE_COMPLETED:
1239 if (easy->easy_handle->state.cancelled)
1240 /* Go into the CANCELLED state if we were cancelled */
1241 multistate(easy, CURLM_STATE_CANCELLED);
1243 /* this is a completed transfer, it is likely to still be connected */
1245 /* This node should be delinked from the list now and we should post
1246 an information message that we are complete. */
1247 break;
1249 case CURLM_STATE_CANCELLED:
1250 /* Cancelled transfer, wait to be cleaned up */
1251 break;
1253 default:
1254 return CURLM_INTERNAL_ERROR;
1257 if(CURLM_STATE_COMPLETED != easy->state) {
1258 if(CURLE_OK != easy->result) {
1260 * If an error was returned, and we aren't in completed state now,
1261 * then we go to completed and consider this transfer aborted.
1263 easy->easy_handle->state.is_in_pipeline = FALSE;
1264 easy->easy_handle->state.pipe_broke = FALSE;
1266 if(easy->easy_conn) {
1267 /* if this has a connection, unsubscribe from the pipelines */
1268 easy->easy_conn->writechannel_inuse = FALSE;
1269 easy->easy_conn->readchannel_inuse = FALSE;
1271 multistate(easy, CURLM_STATE_COMPLETED);
1275 } while (easy->easy_handle->change.url_changed);
1277 if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
1278 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1279 /* clear out the usage of the shared DNS cache */
1280 easy->easy_handle->dns.hostcache = NULL;
1281 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1284 /* now add a node to the Curl_message linked list with this info */
1285 msg = (struct Curl_message *)malloc(sizeof(struct Curl_message));
1287 if(!msg)
1288 return CURLM_OUT_OF_MEMORY;
1290 msg->extmsg.msg = CURLMSG_DONE;
1291 msg->extmsg.easy_handle = easy->easy_handle;
1292 msg->extmsg.data.result = easy->result;
1293 msg->next = NULL;
1295 easy->msg = msg;
1296 easy->msg_num = 1; /* there is one unread message here */
1298 multi->num_msgs++; /* increase message counter */
1301 return result;
1305 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1307 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1308 struct Curl_one_easy *easy;
1309 CURLMcode returncode=CURLM_OK;
1310 struct Curl_tree *t;
1312 if(!GOOD_MULTI_HANDLE(multi))
1313 return CURLM_BAD_HANDLE;
1315 easy=multi->easy.next;
1316 while(easy) {
1317 CURLMcode result;
1319 if (easy->easy_handle->state.cancelled &&
1320 easy->state == CURLM_STATE_CANCELLED) {
1321 /* Remove cancelled handles once it's safe to do so */
1322 Curl_multi_rmeasy(multi_handle, easy->easy_handle);
1323 easy->easy_handle = NULL;
1324 easy = easy->next;
1325 continue;
1328 result = multi_runsingle(multi, easy);
1329 if(result)
1330 returncode = result;
1332 easy = easy->next; /* operate on next handle */
1336 * Simply remove all expired timers from the splay since handles are dealt
1337 * with unconditionally by this function and curl_multi_timeout() requires
1338 * that already passed/handled expire times are removed from the splay.
1340 do {
1341 struct timeval now = Curl_tvnow();
1342 int key = now.tv_sec; /* drop the usec part */
1344 multi->timetree = Curl_splaygetbest(key, multi->timetree, &t);
1345 if (t) {
1346 struct SessionHandle *d = t->payload;
1347 struct timeval* tv = &d->state.expiretime;
1349 /* clear the expire times within the handles that we remove from the
1350 splay tree */
1351 tv->tv_sec = 0;
1352 tv->tv_usec = 0;
1355 } while(t);
1357 *running_handles = multi->num_alive;
1359 if ( CURLM_OK == returncode )
1360 update_timer(multi);
1361 return returncode;
1364 /* This is called when an easy handle is cleanup'ed that is part of a multi
1365 handle */
1366 void Curl_multi_rmeasy(void *multi_handle, CURL *easy_handle)
1368 curl_multi_remove_handle(multi_handle, easy_handle);
1372 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1374 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1375 struct Curl_one_easy *easy;
1376 struct Curl_one_easy *nexteasy;
1377 int i;
1378 struct closure *cl;
1379 struct closure *n;
1381 if(GOOD_MULTI_HANDLE(multi)) {
1382 multi->type = 0; /* not good anymore */
1383 Curl_hash_destroy(multi->hostcache);
1384 Curl_hash_destroy(multi->sockhash);
1386 /* go over all connections that have close actions */
1387 for(i=0; i< multi->connc->num; i++) {
1388 if(multi->connc->connects[i] &&
1389 multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
1390 Curl_disconnect(multi->connc->connects[i]);
1391 multi->connc->connects[i] = NULL;
1394 /* now walk through the list of handles we kept around only to be
1395 able to close connections "properly" */
1396 cl = multi->closure;
1397 while(cl) {
1398 cl->easy_handle->state.shared_conn = NULL; /* no more shared */
1399 if(cl->easy_handle->state.closed)
1400 /* close handle only if curl_easy_cleanup() already has been called
1401 for this easy handle */
1402 Curl_close(cl->easy_handle);
1403 n = cl->next;
1404 free(cl);
1405 cl= n;
1408 Curl_rm_connc(multi->connc);
1410 /* remove all easy handles */
1411 easy = multi->easy.next;
1412 while(easy) {
1413 nexteasy=easy->next;
1414 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1415 /* clear out the usage of the shared DNS cache */
1416 easy->easy_handle->dns.hostcache = NULL;
1417 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1420 /* Clear the pointer to the connection cache */
1421 easy->easy_handle->state.connc = NULL;
1423 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1425 if (easy->msg)
1426 free(easy->msg);
1427 free(easy);
1428 easy = nexteasy;
1431 free(multi);
1433 return CURLM_OK;
1435 else
1436 return CURLM_BAD_HANDLE;
1439 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1441 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1443 *msgs_in_queue = 0; /* default to none */
1445 if(GOOD_MULTI_HANDLE(multi)) {
1446 struct Curl_one_easy *easy;
1448 if(!multi->num_msgs)
1449 return NULL; /* no messages left to return */
1451 easy=multi->easy.next;
1452 while(easy) {
1453 if(easy->msg_num) {
1454 easy->msg_num--;
1455 break;
1457 easy = easy->next;
1459 if(!easy)
1460 return NULL; /* this means internal count confusion really */
1462 multi->num_msgs--;
1463 *msgs_in_queue = multi->num_msgs;
1465 return &easy->msg->extmsg;
1467 else
1468 return NULL;
1472 * singlesocket() checks what sockets we deal with and their "action state"
1473 * and if we have a different state in any of those sockets from last time we
1474 * call the callback accordingly.
1476 static void singlesocket(struct Curl_multi *multi,
1477 struct Curl_one_easy *easy)
1479 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1480 int i;
1481 struct Curl_sh_entry *entry;
1482 curl_socket_t s;
1483 int num;
1484 unsigned int curraction;
1486 memset(&socks, 0, sizeof(socks));
1487 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1488 socks[i] = CURL_SOCKET_BAD;
1490 /* Fill in the 'current' struct with the state as it is now: what sockets to
1491 supervise and for what actions */
1492 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1494 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1495 sockets we should have from now on. Detect the differences, remove no
1496 longer supervised ones and add new ones */
1498 /* walk over the sockets we got right now */
1499 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1500 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1501 i++) {
1502 int action = CURL_POLL_NONE;
1504 s = socks[i];
1506 /* get it from the hash */
1507 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1509 if(curraction & GETSOCK_READSOCK(i))
1510 action |= CURL_POLL_IN;
1511 if(curraction & GETSOCK_WRITESOCK(i))
1512 action |= CURL_POLL_OUT;
1514 if(entry) {
1515 /* yeps, already present so check if it has the same action set */
1516 if(entry->action == action)
1517 /* same, continue */
1518 continue;
1520 else {
1521 /* this is a socket we didn't have before, add it! */
1522 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1523 if(!entry)
1524 /* fatal */
1525 return;
1528 multi->socket_cb(easy->easy_handle,
1530 action,
1531 multi->socket_userp,
1532 entry ? entry->socketp : NULL);
1534 entry->action = action; /* store the current action state */
1537 num = i; /* number of sockets */
1539 /* when we've walked over all the sockets we should have right now, we must
1540 make sure to detect sockets that are removed */
1541 for(i=0; i< easy->numsocks; i++) {
1542 int j;
1543 s = easy->sockets[i];
1544 for(j=0; j<num; j++) {
1545 if(s == socks[j]) {
1546 /* this is still supervised */
1547 s = CURL_SOCKET_BAD;
1548 break;
1551 if(s != CURL_SOCKET_BAD) {
1552 /* this socket has been removed. Remove it */
1554 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1555 if(entry) {
1556 /* just a precaution, this socket really SHOULD be in the hash already
1557 but in case it isn't, we don't have to tell the app to remove it
1558 either since it never got to know about it */
1559 multi->socket_cb(easy->easy_handle,
1561 CURL_POLL_REMOVE,
1562 multi->socket_userp,
1563 entry ? entry->socketp : NULL);
1565 sh_delentry(multi->sockhash, s);
1570 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
1571 easy->numsocks = num;
1574 static CURLMcode multi_socket(struct Curl_multi *multi,
1575 bool checkall,
1576 curl_socket_t s,
1577 int *running_handles)
1579 CURLMcode result = CURLM_OK;
1580 struct SessionHandle *data = NULL;
1581 struct Curl_tree *t;
1583 if(checkall) {
1584 struct Curl_one_easy *easyp;
1585 /* *perform() deals with running_handles on its own */
1586 result = curl_multi_perform(multi, running_handles);
1588 /* walk through each easy handle and do the socket state change magic
1589 and callbacks */
1590 easyp=multi->easy.next;
1591 while(easyp) {
1592 singlesocket(multi, easyp);
1593 easyp = easyp->next;
1596 /* or should we fall-through and do the timer-based stuff? */
1597 return result;
1599 else if (s != CURL_SOCKET_TIMEOUT) {
1601 struct Curl_sh_entry *entry =
1602 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1604 if(!entry)
1605 /* unmatched socket, major problemo! */
1606 return CURLM_BAD_SOCKET; /* better return code? */
1608 data = entry->easy;
1610 if(data->magic != CURLEASY_MAGIC_NUMBER)
1611 /* bad bad bad bad bad bad bad */
1612 return CURLM_INTERNAL_ERROR;
1614 result = multi_runsingle(multi, data->set.one_easy);
1616 if(result == CURLM_OK)
1617 /* get the socket(s) and check if the state has been changed since
1618 last */
1619 singlesocket(multi, data->set.one_easy);
1621 /* Now we fall-through and do the timer-based stuff, since we don't want
1622 to force the user to have to deal with timeouts as long as at least one
1623 connection in fact has traffic. */
1625 data = NULL; /* set data to NULL again to avoid calling multi_runsingle()
1626 in case there's no need to */
1630 * The loop following here will go on as long as there are expire-times left
1631 * to process in the splay and 'data' will be re-assigned for every expired
1632 * handle we deal with.
1634 do {
1635 int key;
1636 struct timeval now;
1638 /* the first loop lap 'data' can be NULL */
1639 if(data) {
1640 result = multi_runsingle(multi, data->set.one_easy);
1642 if(result == CURLM_OK)
1643 /* get the socket(s) and check if the state has been changed since
1644 last */
1645 singlesocket(multi, data->set.one_easy);
1648 /* Check if there's one (more) expired timer to deal with! This function
1649 extracts a matching node if there is one */
1651 now = Curl_tvnow();
1652 key = now.tv_sec; /* drop the usec part */
1654 multi->timetree = Curl_splaygetbest(key, multi->timetree, &t);
1655 if(t) {
1656 /* assign 'data' to be the easy handle we just removed from the splay
1657 tree */
1658 data = t->payload;
1659 /* clear the expire time within the handle we removed from the
1660 splay tree */
1661 data->state.expiretime.tv_sec = 0;
1662 data->state.expiretime.tv_usec = 0;
1665 } while(t);
1667 *running_handles = multi->num_alive;
1668 return result;
1671 CURLMcode curl_multi_setopt(CURLM *multi_handle,
1672 CURLMoption option, ...)
1674 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1675 CURLMcode res = CURLM_OK;
1676 va_list param;
1678 if(!GOOD_MULTI_HANDLE(multi))
1679 return CURLM_BAD_HANDLE;
1681 va_start(param, option);
1683 switch(option) {
1684 case CURLMOPT_SOCKETFUNCTION:
1685 multi->socket_cb = va_arg(param, curl_socket_callback);
1686 break;
1687 case CURLMOPT_SOCKETDATA:
1688 multi->socket_userp = va_arg(param, void *);
1689 break;
1690 case CURLMOPT_PIPELINING:
1691 multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
1692 break;
1693 case CURLMOPT_TIMERFUNCTION:
1694 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
1695 break;
1696 case CURLMOPT_TIMERDATA:
1697 multi->timer_userp = va_arg(param, void *);
1698 break;
1699 default:
1700 res = CURLM_UNKNOWN_OPTION;
1701 break;
1703 va_end(param);
1704 return res;
1708 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
1709 int *running_handles)
1711 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
1712 running_handles);
1713 if (CURLM_OK == result)
1714 update_timer((struct Curl_multi *)multi_handle);
1715 return result;
1718 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
1721 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
1722 TRUE, CURL_SOCKET_BAD, running_handles);
1723 if (CURLM_OK == result)
1724 update_timer((struct Curl_multi *)multi_handle);
1725 return result;
1728 static CURLMcode multi_timeout(struct Curl_multi *multi,
1729 long *timeout_ms)
1731 if(multi->timetree) {
1732 /* we have a tree of expire times */
1733 struct timeval now = Curl_tvnow();
1735 /* splay the lowest to the bottom */
1736 multi->timetree = Curl_splay(0, multi->timetree);
1738 /* At least currently, the splay key is a time_t for the expire time */
1739 *timeout_ms = (multi->timetree->key - now.tv_sec) * 1000 -
1740 now.tv_usec/1000;
1741 if(*timeout_ms < 0)
1742 /* 0 means immediately */
1743 *timeout_ms = 0;
1745 else
1746 *timeout_ms = -1;
1748 return CURLM_OK;
1751 CURLMcode curl_multi_timeout(CURLM *multi_handle,
1752 long *timeout_ms)
1754 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1756 /* First, make some basic checks that the CURLM handle is a good handle */
1757 if(!GOOD_MULTI_HANDLE(multi))
1758 return CURLM_BAD_HANDLE;
1760 return multi_timeout(multi, timeout_ms);
1764 * Tell the application it should update its timers, if it subscribes to the
1765 * update timer callback.
1767 static int update_timer(struct Curl_multi *multi)
1769 long timeout_ms;
1770 if (!multi->timer_cb)
1771 return 0;
1772 if ( multi_timeout(multi, &timeout_ms) != CURLM_OK )
1773 return -1;
1774 if ( timeout_ms < 0 )
1775 return 0;
1777 /* When multi_timeout() is done, multi->timetree points to the node with the
1778 * timeout we got the (relative) time-out time for. We can thus easily check
1779 * if this is the same (fixed) time as we got in a previous call and then
1780 * avoid calling the callback again. */
1781 if(multi->timetree->key == multi->timer_lastcall)
1782 return 0;
1784 multi->timer_lastcall = multi->timetree->key;
1786 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
1789 /* given a number of milliseconds from now to use to set the 'act before
1790 this'-time for the transfer, to be extracted by curl_multi_timeout() */
1791 void Curl_expire(struct SessionHandle *data, long milli)
1793 struct Curl_multi *multi = data->multi;
1794 struct timeval *nowp = &data->state.expiretime;
1795 int rc;
1797 /* this is only interesting for multi-interface using libcurl, and only
1798 while there is still a multi interface struct remaining! */
1799 if(!multi)
1800 return;
1802 if(!milli) {
1803 /* No timeout, clear the time data. */
1804 if(nowp->tv_sec) {
1805 /* Since this is an cleared time, we must remove the previous entry from
1806 the splay tree */
1807 rc = Curl_splayremovebyaddr(multi->timetree,
1808 &data->state.timenode,
1809 &multi->timetree);
1810 if(rc)
1811 infof(data, "Internal error clearing splay node = %d\n", rc);
1812 infof(data, "Expire cleared\n");
1813 nowp->tv_sec = 0;
1814 nowp->tv_usec = 0;
1817 else {
1818 struct timeval set;
1819 int rest;
1821 set = Curl_tvnow();
1822 set.tv_sec += milli/1000;
1823 set.tv_usec += (milli%1000)*1000;
1825 rest = (int)(set.tv_usec - 1000000);
1826 if(rest > 0) {
1827 /* bigger than a full microsec */
1828 set.tv_sec++;
1829 set.tv_usec -= 1000000;
1832 if(nowp->tv_sec) {
1833 /* This means that the struct is added as a node in the splay tree.
1834 Compare if the new time is earlier, and only remove-old/add-new if it
1835 is. */
1836 long diff = curlx_tvdiff(set, *nowp);
1837 if(diff > 0)
1838 /* the new expire time was later so we don't change this */
1839 return;
1841 /* Since this is an updated time, we must remove the previous entry from
1842 the splay tree first and then re-add the new value */
1843 rc = Curl_splayremovebyaddr(multi->timetree,
1844 &data->state.timenode,
1845 &multi->timetree);
1846 if(rc)
1847 infof(data, "Internal error removing splay node = %d\n", rc);
1850 *nowp = set;
1851 #if 0
1852 infof(data, "Expire at %ld / %ld (%ldms)\n",
1853 (long)nowp->tv_sec, (long)nowp->tv_usec, milli);
1854 #endif
1855 data->state.timenode.payload = data;
1856 multi->timetree = Curl_splayinsert((int)nowp->tv_sec,
1857 multi->timetree,
1858 &data->state.timenode);
1860 #if 0
1861 Curl_splayprint(multi->timetree, 0, TRUE);
1862 #endif
1865 CURLMcode curl_multi_assign(CURLM *multi_handle,
1866 curl_socket_t s, void *hashp)
1868 struct Curl_sh_entry *there = NULL;
1869 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
1871 if(s != CURL_SOCKET_BAD)
1872 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
1874 if(!there)
1875 return CURLM_BAD_SOCKET;
1877 there->socketp = hashp;
1879 return CURLM_OK;
1882 static bool multi_conn_using(struct Curl_multi *multi,
1883 struct SessionHandle *data)
1885 /* any live CLOSEACTION-connections pointing to the give 'data' ? */
1886 int i;
1888 for(i=0; i< multi->connc->num; i++) {
1889 if(multi->connc->connects[i] &&
1890 (multi->connc->connects[i]->data == data) &&
1891 multi->connc->connects[i]->protocol & PROT_CLOSEACTION)
1892 return TRUE;
1895 return FALSE;
1898 /* Add the given data pointer to the list of 'closure handles' that are kept
1899 around only to be able to close some connections nicely - just make sure
1900 that this handle isn't already added, like for the cases when an easy
1901 handle is removed, added and removed again... */
1902 static void add_closure(struct Curl_multi *multi,
1903 struct SessionHandle *data)
1905 int i;
1906 struct closure *cl = (struct closure *)calloc(sizeof(struct closure), 1);
1907 struct closure *p=NULL;
1908 struct closure *n;
1909 if(cl) {
1910 cl->easy_handle = data;
1911 cl->next = multi->closure;
1912 multi->closure = cl;
1915 p = multi->closure;
1916 cl = p->next; /* start immediately on the second since the first is the one
1917 we just added and it is _very_ likely to actually exist
1918 used in the cache since that's the whole purpose of adding
1919 it to this list! */
1921 /* When adding, scan through all the other currently kept handles and see if
1922 there are any connections still referring to them and kill them if not. */
1923 while(cl) {
1924 bool inuse = FALSE;
1925 for(i=0; i< multi->connc->num; i++) {
1926 if(multi->connc->connects[i] &&
1927 (multi->connc->connects[i]->data == cl->easy_handle)) {
1928 inuse = TRUE;
1929 break;
1933 n = cl->next;
1935 if(!inuse) {
1936 /* cl->easy_handle is now killable */
1937 infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle);
1938 /* unmark it as not having a connection around that uses it anymore */
1939 cl->easy_handle->state.shared_conn= NULL;
1940 Curl_close(cl->easy_handle);
1941 if(p)
1942 p->next = n;
1943 else
1944 multi->closure = n;
1945 free(cl);
1947 else
1948 p = cl;
1950 cl = n;
1955 #ifdef CURLDEBUG
1956 void curl_multi_dump(CURLM *multi_handle)
1958 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1959 struct Curl_one_easy *easy;
1960 int i;
1961 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
1962 multi->num_easy, multi->num_alive);
1963 for(easy=multi->easy.next; easy; easy = easy->next) {
1964 if(easy->state != CURLM_STATE_COMPLETED) {
1965 /* only display handles that are not completed */
1966 fprintf(stderr, "handle %p, state %s, %d sockets\n",
1967 (void *)easy->easy_handle,
1968 statename[easy->state], easy->numsocks);
1969 for(i=0; i < easy->numsocks; i++) {
1970 curl_socket_t s = easy->sockets[i];
1971 struct Curl_sh_entry *entry =
1972 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1974 fprintf(stderr, "%d ", (int)s);
1975 if(!entry) {
1976 fprintf(stderr, "INTERNAL CONFUSION\n");
1977 continue;
1979 fprintf(stderr, "[%s %s] ",
1980 entry->action&CURL_POLL_IN?"RECVING":"",
1981 entry->action&CURL_POLL_OUT?"SENDING":"");
1983 if(easy->numsocks)
1984 fprintf(stderr, "\n");
1988 #endif