1 /***************************************************************************
3 * Project ___| | | | _ \| |
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 ***************************************************************************/
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h>
38 #include <curl/curl.h>
51 /* The last #include file should be: */
55 /* the 'CURLMsg' is the part that is visible to the external user */
56 struct CURLMsg extmsg
;
57 struct Curl_message
*next
;
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
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 */
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)
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
];
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 */
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. */
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
;
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
;
168 time_t timer_lastcall
; /* the fixed time for the timeout for the previous
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
);
181 static const char *statename
[]={
200 void curl_multi_dump(CURLM
*multi_handle
);
203 /* always use this function to change state, to make debugging easier */
204 static void multistate(struct Curl_one_easy
*easy
, CURLMstate state
)
209 CURLMstate oldstate
= easy
->state
;
211 if(oldstate
== state
)
212 /* don't bother when the new state is the same as the old state */
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
);
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
;
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
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
,
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
;
259 /* it is present, return fine */
262 /* not present, add it */
263 check
= calloc(sizeof(struct Curl_sh_entry
), 1);
265 return NULL
; /* major failure */
269 /* make/add new hash entry */
270 if(NULL
== Curl_hash_add(sh
, (char *)&s
, sizeof(curl_socket_t
), 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
));
286 /* this socket is in the hash */
287 /* We remove the hash entry. (This'll end up in a call to
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
;
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
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);
333 multi
->type
= CURL_MULTI_HANDLE
;
335 multi
->hostcache
= Curl_mk_dnscache();
336 if(!multi
->hostcache
) {
337 /* failure, free mem and bail out */
342 multi
->sockhash
= sh_init();
343 if(!multi
->sockhash
) {
344 /* failure, free mem and bail out */
345 Curl_hash_destroy(multi
->hostcache
);
350 multi
->connc
= Curl_mk_connc(CONNCACHE_MULTI
, -1);
352 Curl_hash_destroy(multi
->hostcache
);
357 return (CURLM
*) multi
;
360 CURLMcode
curl_multi_add_handle(CURLM
*multi_handle
,
363 struct Curl_multi
*multi
=(struct Curl_multi
*)multi_handle
;
364 struct Curl_one_easy
*easy
;
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);
384 return CURLM_OUT_OF_MEMORY
;
388 struct closure
*next
= cl
->next
;
389 if(cl
->easy_handle
== (struct SessionHandle
*)easy_handle
) {
390 /* remove this handle from the closure list */
395 multi
->closure
= next
;
396 break; /* no need to continue since this handle can only be present once
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? */
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
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 */
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
462 CURLcode res
= Curl_ch_connc(easy_handle
, multi
->connc
,
463 multi
->connc
->num
*4);
465 /* TODO: we need to do some cleaning up here! */
466 return CURLM_OUT_OF_MEMORY
;
469 /* increase the alive-counter */
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
);
492 CURLMcode
curl_multi_remove_handle(CURLM
*multi_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
;
509 if(easy
->easy_handle
== (struct SessionHandle
*)curl_handle
)
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. */
520 /* this handle is "alive" so we need to count down the total number of
521 alive connections when this is removed */
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
;
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
);
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
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 */
596 easy
->easy_conn
->connectindex
= -1;
599 /* change state without using multistate(), only to make singlesocket() do
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 */
610 easy
->prev
->next
= easy
->next
;
611 /* make our next point to our previous node */
613 easy
->next
->prev
= easy
->prev
;
615 easy
->easy_handle
->set
.one_easy
= NULL
; /* detached */
618 We do not touch the easy handle here! */
623 multi
->num_easy
--; /* one less to care about now */
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
,
642 return GETSOCK_BLANK
;
644 sock
[0] = conn
->sock
[FIRSTSOCKET
];
645 return GETSOCK_WRITESOCK(0);
648 static int domore_getsock(struct connectdata
*conn
,
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
671 if (easy
->easy_handle
->state
.pipe_broke
) {
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. */
684 /* this will get called with CURLM_STATE_COMPLETED when a handle is
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
;
720 curl_socket_t sockbunch
[MAX_SOCKSPEREASYHANDLE
];
723 (void)exc_fd_set
; /* not used */
725 if(!GOOD_MULTI_HANDLE(multi
))
726 return CURLM_BAD_HANDLE
;
728 easy
=multi
->easy
.next
;
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
);
739 if(bitmap
& GETSOCK_WRITESOCK(i
)) {
740 FD_SET(sockbunch
[i
], write_fd_set
);
743 if(s
== CURL_SOCKET_BAD
)
744 /* this socket is unused, break out of loop */
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
;
760 static CURLMcode
multi_runsingle(struct Curl_multi
*multi
,
761 struct Curl_one_easy
*easy
)
763 struct Curl_message
*msg
= NULL
;
766 bool protocol_connect
;
769 CURLMcode result
= CURLM_OK
;
770 struct Curl_transfer_keeper
*k
;
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
;
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
;
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
) {
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
);
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
);
822 easy
->result
= CURLE_OUT_OF_MEMORY
;
823 multistate(easy
, CURLM_STATE_COMPLETED
);
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
;
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
);
857 /* We're now waiting for an asynchronous name lookup */
858 multistate(easy
, CURLM_STATE_WAITRESOLVE
);
860 /* after the connect has been sent off, go WAITCONNECT unless the
861 protocol connect is already done and we can go directly to
863 result
= CURLM_CALL_MULTI_PERFORM
;
865 if(protocol_connect
) {
866 multistate(easy
, CURLM_STATE_WAITDO
);
868 multistate(easy
, CURLM_STATE_WAITCONNECT
);
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
);
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
,
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 */
893 /* call again please so that we get the next socket setup */
894 result
= CURLM_CALL_MULTI_PERFORM
;
896 multistate(easy
, CURLM_STATE_DO
);
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 */
911 case CURLM_STATE_WAITCONNECT
:
912 /* awaiting a completion of an asynch connect */
913 easy
->result
= Curl_is_connected(easy
->easy_conn
,
917 easy
->result
= Curl_protocol_connect(easy
->easy_conn
,
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 */
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
);
935 /* after the connect has completed, go WAITDO */
936 multistate(easy
, CURLM_STATE_WAITDO
);
938 result
= CURLM_CALL_MULTI_PERFORM
;
943 case CURLM_STATE_PROTOCONNECT
:
944 /* protocol-specific connect phase */
945 easy
->result
= Curl_protocol_connecting(easy
->easy_conn
,
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 */
961 case CURLM_STATE_WAITDO
:
962 /* Wait for our turn to DO when we're pipelining requests */
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
));
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
;
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
;
990 /* Perform the protocol's DO action */
991 easy
->result
= Curl_do(&easy
->easy_conn
,
994 if(CURLE_OK
== easy
->result
) {
997 /* DO was not completed in one function call, we must continue
999 multistate(easy
, CURLM_STATE_DOING
);
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
);
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
;
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 */
1029 case CURLM_STATE_DOING
:
1030 /* we continue DOING until the DO phase is complete */
1031 easy
->result
= Curl_protocol_doing(easy
->easy_conn
,
1033 if(CURLE_OK
== easy
->result
) {
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
);
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 */
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 */
1061 case CURLM_STATE_DO_MORE
:
1062 /* Ready to do more? */
1063 easy
->result
= Curl_is_connected(easy
->easy_conn
,
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
);
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
;
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
;
1097 case CURLM_STATE_WAITPERFORM
:
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
));
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
;
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
);
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
);
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
;
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
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
) {
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
);
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
;
1201 /* Since we "took it", we are in charge of freeing this on
1206 /* after the transfer is done, go DONE */
1207 multistate(easy
, CURLM_STATE_DONE
);
1208 result
= CURLM_CALL_MULTI_PERFORM
;
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
);
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. */
1249 case CURLM_STATE_CANCELLED
:
1250 /* Cancelled transfer, wait to be cleaned up */
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
));
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
;
1296 easy
->msg_num
= 1; /* there is one unread message here */
1298 multi
->num_msgs
++; /* increase message counter */
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
;
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
;
1328 result
= multi_runsingle(multi
, easy
);
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.
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
);
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
1357 *running_handles
= multi
->num_alive
;
1359 if ( CURLM_OK
== returncode
)
1360 update_timer(multi
);
1364 /* This is called when an easy handle is cleanup'ed that is part of a multi
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
;
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
;
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
);
1408 Curl_rm_connc(multi
->connc
);
1410 /* remove all easy handles */
1411 easy
= multi
->easy
.next
;
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 */
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
;
1460 return NULL
; /* this means internal count confusion really */
1463 *msgs_in_queue
= multi
->num_msgs
;
1465 return &easy
->msg
->extmsg
;
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
];
1481 struct Curl_sh_entry
*entry
;
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
)));
1502 int action
= CURL_POLL_NONE
;
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
;
1515 /* yeps, already present so check if it has the same action set */
1516 if(entry
->action
== action
)
1517 /* same, continue */
1521 /* this is a socket we didn't have before, add it! */
1522 entry
= sh_addentry(multi
->sockhash
, s
, easy
->easy_handle
);
1528 multi
->socket_cb(easy
->easy_handle
,
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
++) {
1543 s
= easy
->sockets
[i
];
1544 for(j
=0; j
<num
; j
++) {
1546 /* this is still supervised */
1547 s
= CURL_SOCKET_BAD
;
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
));
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
,
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
,
1577 int *running_handles
)
1579 CURLMcode result
= CURLM_OK
;
1580 struct SessionHandle
*data
= NULL
;
1581 struct Curl_tree
*t
;
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
1590 easyp
=multi
->easy
.next
;
1592 singlesocket(multi
, easyp
);
1593 easyp
= easyp
->next
;
1596 /* or should we fall-through and do the timer-based stuff? */
1599 else if (s
!= CURL_SOCKET_TIMEOUT
) {
1601 struct Curl_sh_entry
*entry
=
1602 Curl_hash_pick(multi
->sockhash
, (char *)&s
, sizeof(s
));
1605 /* unmatched socket, major problemo! */
1606 return CURLM_BAD_SOCKET
; /* better return code? */
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
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.
1638 /* the first loop lap 'data' can be NULL */
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
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 */
1652 key
= now
.tv_sec
; /* drop the usec part */
1654 multi
->timetree
= Curl_splaygetbest(key
, multi
->timetree
, &t
);
1656 /* assign 'data' to be the easy handle we just removed from the splay
1659 /* clear the expire time within the handle we removed from the
1661 data
->state
.expiretime
.tv_sec
= 0;
1662 data
->state
.expiretime
.tv_usec
= 0;
1667 *running_handles
= multi
->num_alive
;
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
;
1678 if(!GOOD_MULTI_HANDLE(multi
))
1679 return CURLM_BAD_HANDLE
;
1681 va_start(param
, option
);
1684 case CURLMOPT_SOCKETFUNCTION
:
1685 multi
->socket_cb
= va_arg(param
, curl_socket_callback
);
1687 case CURLMOPT_SOCKETDATA
:
1688 multi
->socket_userp
= va_arg(param
, void *);
1690 case CURLMOPT_PIPELINING
:
1691 multi
->pipelining_enabled
= (bool)(0 != va_arg(param
, long));
1693 case CURLMOPT_TIMERFUNCTION
:
1694 multi
->timer_cb
= va_arg(param
, curl_multi_timer_callback
);
1696 case CURLMOPT_TIMERDATA
:
1697 multi
->timer_userp
= va_arg(param
, void *);
1700 res
= CURLM_UNKNOWN_OPTION
;
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
,
1713 if (CURLM_OK
== result
)
1714 update_timer((struct Curl_multi
*)multi_handle
);
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
);
1728 static CURLMcode
multi_timeout(struct Curl_multi
*multi
,
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 -
1742 /* 0 means immediately */
1751 CURLMcode
curl_multi_timeout(CURLM
*multi_handle
,
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
)
1770 if (!multi
->timer_cb
)
1772 if ( multi_timeout(multi
, &timeout_ms
) != CURLM_OK
)
1774 if ( timeout_ms
< 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
)
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
;
1797 /* this is only interesting for multi-interface using libcurl, and only
1798 while there is still a multi interface struct remaining! */
1803 /* No timeout, clear the time data. */
1805 /* Since this is an cleared time, we must remove the previous entry from
1807 rc
= Curl_splayremovebyaddr(multi
->timetree
,
1808 &data
->state
.timenode
,
1811 infof(data
, "Internal error clearing splay node = %d\n", rc
);
1812 infof(data
, "Expire cleared\n");
1822 set
.tv_sec
+= milli
/1000;
1823 set
.tv_usec
+= (milli
%1000)*1000;
1825 rest
= (int)(set
.tv_usec
- 1000000);
1827 /* bigger than a full microsec */
1829 set
.tv_usec
-= 1000000;
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
1836 long diff
= curlx_tvdiff(set
, *nowp
);
1838 /* the new expire time was later so we don't change this */
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
,
1847 infof(data
, "Internal error removing splay node = %d\n", rc
);
1852 infof(data
, "Expire at %ld / %ld (%ldms)\n",
1853 (long)nowp
->tv_sec
, (long)nowp
->tv_usec
, milli
);
1855 data
->state
.timenode
.payload
= data
;
1856 multi
->timetree
= Curl_splayinsert((int)nowp
->tv_sec
,
1858 &data
->state
.timenode
);
1861 Curl_splayprint(multi
->timetree
, 0, TRUE
);
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
));
1875 return CURLM_BAD_SOCKET
;
1877 there
->socketp
= hashp
;
1882 static bool multi_conn_using(struct Curl_multi
*multi
,
1883 struct SessionHandle
*data
)
1885 /* any live CLOSEACTION-connections pointing to the give 'data' ? */
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
)
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
)
1906 struct closure
*cl
= (struct closure
*)calloc(sizeof(struct closure
), 1);
1907 struct closure
*p
=NULL
;
1910 cl
->easy_handle
= data
;
1911 cl
->next
= multi
->closure
;
1912 multi
->closure
= cl
;
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
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. */
1925 for(i
=0; i
< multi
->connc
->num
; i
++) {
1926 if(multi
->connc
->connects
[i
] &&
1927 (multi
->connc
->connects
[i
]->data
== cl
->easy_handle
)) {
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
);
1956 void curl_multi_dump(CURLM
*multi_handle
)
1958 struct Curl_multi
*multi
=(struct Curl_multi
*)multi_handle
;
1959 struct Curl_one_easy
*easy
;
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
);
1976 fprintf(stderr
, "INTERNAL CONFUSION\n");
1979 fprintf(stderr
, "[%s %s] ",
1980 entry
->action
&CURL_POLL_IN
?"RECVING":"",
1981 entry
->action
&CURL_POLL_OUT
?"SENDING":"");
1984 fprintf(stderr
, "\n");