Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl-7.19.0 / lib / multi.c
blob7d7bc1064c97880072f25807ef08eee516f4644f
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2008, 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.1.1.1 2008-09-23 16:32:05 hoffman Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 #ifdef HAVE_SYS_SOCKET_H
27 #include <sys/socket.h>
28 #endif
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #include <curl/curl.h>
35 #include "urldata.h"
36 #include "transfer.h"
37 #include "url.h"
38 #include "connect.h"
39 #include "progress.h"
40 #include "memory.h"
41 #include "easyif.h"
42 #include "multiif.h"
43 #include "sendf.h"
44 #include "timeval.h"
45 #include "http.h"
47 /* The last #include file should be: */
48 #include "memdebug.h"
51 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
52 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
53 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
55 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
56 #define CURL_SOCKET_HASH_TABLE_SIZE 911
57 #endif
59 struct Curl_message {
60 /* the 'CURLMsg' is the part that is visible to the external user */
61 struct CURLMsg extmsg;
62 struct Curl_message *next;
65 /* NOTE: if you add a state here, add the name to the statename[] array as
66 well!
68 typedef enum {
69 CURLM_STATE_INIT, /* start in this state */
70 CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
71 CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
72 CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
73 CURLM_STATE_WAITPROXYCONNECT, /* awaiting proxy CONNECT to finalize */
74 CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect phase */
75 CURLM_STATE_WAITDO, /* wait for our turn to send the request */
76 CURLM_STATE_DO, /* start send off the request (part 1) */
77 CURLM_STATE_DOING, /* sending off the request (part 1) */
78 CURLM_STATE_DO_MORE, /* send off the request (part 2) */
79 CURLM_STATE_DO_DONE, /* done sending off request */
80 CURLM_STATE_WAITPERFORM, /* wait for our turn to read the response */
81 CURLM_STATE_PERFORM, /* transfer data */
82 CURLM_STATE_TOOFAST, /* wait because limit-rate exceeded */
83 CURLM_STATE_DONE, /* post data transfer operation */
84 CURLM_STATE_COMPLETED, /* operation complete */
86 CURLM_STATE_LAST /* not a true state, never use this */
87 } CURLMstate;
89 /* we support N sockets per easy handle. Set the corresponding bit to what
90 action we should wait for */
91 #define MAX_SOCKSPEREASYHANDLE 5
92 #define GETSOCK_READABLE (0x00ff)
93 #define GETSOCK_WRITABLE (0xff00)
95 struct closure {
96 struct closure *next; /* a simple one-way list of structs */
97 struct SessionHandle *easy_handle;
100 struct Curl_one_easy {
101 /* first, two fields for the linked list of these */
102 struct Curl_one_easy *next;
103 struct Curl_one_easy *prev;
105 struct SessionHandle *easy_handle; /* the easy handle for this unit */
106 struct connectdata *easy_conn; /* the "unit's" connection */
108 CURLMstate state; /* the handle's state */
109 CURLcode result; /* previous result */
111 struct Curl_message *msg; /* A pointer to one single posted message.
112 Cleanup should be done on this pointer NOT on
113 the linked list in Curl_multi. This message
114 will be deleted when this handle is removed
115 from the multi-handle */
116 int msg_num; /* number of messages left in 'msg' to return */
118 /* Array with the plain socket numbers this handle takes care of, in no
119 particular order. Note that all sockets are added to the sockhash, where
120 the state etc are also kept. This array is mostly used to detect when a
121 socket is to be removed from the hash. See singlesocket(). */
122 curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
123 int numsocks;
126 #define CURL_MULTI_HANDLE 0x000bab1e
128 #define GOOD_MULTI_HANDLE(x) \
129 ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
130 #define GOOD_EASY_HANDLE(x) \
131 (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER)
133 /* This is the struct known as CURLM on the outside */
134 struct Curl_multi {
135 /* First a simple identifier to easier detect if a user mix up
136 this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
137 long type;
139 /* We have a linked list with easy handles */
140 struct Curl_one_easy easy;
142 int num_easy; /* amount of entries in the linked list above. */
143 int num_msgs; /* amount of messages in the easy handles */
144 int num_alive; /* amount of easy handles that are added but have not yet
145 reached COMPLETE state */
147 /* callback function and user data pointer for the *socket() API */
148 curl_socket_callback socket_cb;
149 void *socket_userp;
151 /* Hostname cache */
152 struct curl_hash *hostcache;
154 /* timetree points to the splay-tree of time nodes to figure out expire
155 times of all currently set timers */
156 struct Curl_tree *timetree;
158 /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
159 the pluralis form, there can be more than one easy handle waiting on the
160 same actual socket) */
161 struct curl_hash *sockhash;
163 /* Whether pipelining is enabled for this multi handle */
164 bool pipelining_enabled;
166 /* shared connection cache */
167 struct conncache *connc;
168 long maxconnects; /* if >0, a fixed limit of the maximum number of entries
169 we're allowed to grow the connection cache to */
171 /* list of easy handles kept around for doing nice connection closures */
172 struct closure *closure;
174 /* timer callback and user data pointer for the *socket() API */
175 curl_multi_timer_callback timer_cb;
176 void *timer_userp;
177 struct timeval timer_lastcall; /* the fixed time for the timeout for the
178 previous callback */
181 static bool multi_conn_using(struct Curl_multi *multi,
182 struct SessionHandle *data);
183 static void singlesocket(struct Curl_multi *multi,
184 struct Curl_one_easy *easy);
185 static void add_closure(struct Curl_multi *multi,
186 struct SessionHandle *data);
187 static int update_timer(struct Curl_multi *multi);
189 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
190 struct connectdata *conn);
191 static int checkPendPipeline(struct connectdata *conn);
192 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *habdle,
193 struct connectdata *conn);
194 static bool isHandleAtHead(struct SessionHandle *handle,
195 struct curl_llist *pipeline);
197 #ifdef CURLDEBUG
198 static const char * const statename[]={
199 "INIT",
200 "CONNECT",
201 "WAITRESOLVE",
202 "WAITCONNECT",
203 "WAITPROXYCONNECT",
204 "PROTOCONNECT",
205 "WAITDO",
206 "DO",
207 "DOING",
208 "DO_MORE",
209 "DO_DONE",
210 "WAITPERFORM",
211 "PERFORM",
212 "TOOFAST",
213 "DONE",
214 "COMPLETED",
217 void curl_multi_dump(CURLM *multi_handle);
218 #endif
220 /* always use this function to change state, to make debugging easier */
221 static void multistate(struct Curl_one_easy *easy, CURLMstate state)
223 #ifdef CURLDEBUG
224 long connectindex = -5000;
225 #endif
226 CURLMstate oldstate = easy->state;
228 if(oldstate == state)
229 /* don't bother when the new state is the same as the old state */
230 return;
232 easy->state = state;
234 #ifdef CURLDEBUG
235 if(easy->state > CURLM_STATE_CONNECT &&
236 easy->state < CURLM_STATE_COMPLETED)
237 connectindex = easy->easy_conn->connectindex;
239 infof(easy->easy_handle,
240 "STATE: %s => %s handle %p; (connection #%ld) \n",
241 statename[oldstate], statename[easy->state],
242 (char *)easy, connectindex);
243 #endif
244 if(state == CURLM_STATE_COMPLETED)
245 /* changing to COMPLETED means there's one less easy handle 'alive' */
246 easy->easy_handle->multi->num_alive--;
250 * We add one of these structs to the sockhash for a particular socket
253 struct Curl_sh_entry {
254 struct SessionHandle *easy;
255 time_t timestamp;
256 long inuse;
257 int action; /* what action READ/WRITE this socket waits for */
258 curl_socket_t socket; /* mainly to ease debugging */
259 void *socketp; /* settable by users with curl_multi_assign() */
261 /* bits for 'action' having no bits means this socket is not expecting any
262 action */
263 #define SH_READ 1
264 #define SH_WRITE 2
266 /* make sure this socket is present in the hash for this handle */
267 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
268 curl_socket_t s,
269 struct SessionHandle *data)
271 struct Curl_sh_entry *there =
272 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
273 struct Curl_sh_entry *check;
275 if(there)
276 /* it is present, return fine */
277 return there;
279 /* not present, add it */
280 check = calloc(sizeof(struct Curl_sh_entry), 1);
281 if(!check)
282 return NULL; /* major failure */
283 check->easy = data;
284 check->socket = s;
286 /* make/add new hash entry */
287 if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
288 free(check);
289 return NULL; /* major failure */
292 return check; /* things are good in sockhash land */
296 /* delete the given socket + handle from the hash */
297 static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
299 struct Curl_sh_entry *there =
300 Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
302 if(there) {
303 /* this socket is in the hash */
304 /* We remove the hash entry. (This'll end up in a call to
305 sh_freeentry().) */
306 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
311 * free a sockhash entry
313 static void sh_freeentry(void *freethis)
315 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
317 free(p);
320 static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len)
322 (void) k1_len; (void) k2_len;
324 return ((*((int* ) k1)) == (*((int* ) k2))) ? 1 : 0;
327 static size_t hash_fd(void* key, size_t key_length, size_t slots_num)
329 int fd = * ((int* ) key);
330 (void) key_length;
332 return (fd % (int)slots_num);
336 * sh_init() creates a new socket hash and returns the handle for it.
338 * Quote from README.multi_socket:
340 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
341 * is somewhat of a bottle neck. Its current implementation may be a bit too
342 * limiting. It simply has a fixed-size array, and on each entry in the array
343 * it has a linked list with entries. So the hash only checks which list to
344 * scan through. The code I had used so for used a list with merely 7 slots
345 * (as that is what the DNS hash uses) but with 7000 connections that would
346 * make an average of 1000 nodes in each list to run through. I upped that to
347 * 97 slots (I believe a prime is suitable) and noticed a significant speed
348 * increase. I need to reconsider the hash implementation or use a rather
349 * large default value like this. At 9000 connections I was still below 10us
350 * per call."
353 static struct curl_hash *sh_init(void)
355 return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
356 sh_freeentry);
359 CURLM *curl_multi_init(void)
361 struct Curl_multi *multi = (void *)calloc(sizeof(struct Curl_multi), 1);
363 if(!multi)
364 return NULL;
366 multi->type = CURL_MULTI_HANDLE;
368 multi->hostcache = Curl_mk_dnscache();
369 if(!multi->hostcache) {
370 /* failure, free mem and bail out */
371 free(multi);
372 return NULL;
375 multi->sockhash = sh_init();
376 if(!multi->sockhash) {
377 /* failure, free mem and bail out */
378 Curl_hash_destroy(multi->hostcache);
379 free(multi);
380 return NULL;
383 multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1);
384 if(!multi->connc) {
385 Curl_hash_destroy(multi->sockhash);
386 Curl_hash_destroy(multi->hostcache);
387 free(multi);
388 return NULL;
391 /* Let's make the doubly-linked list a circular list. This makes
392 the linked list code simpler and allows inserting at the end
393 with less work (we didn't keep a tail pointer before). */
394 multi->easy.next = &multi->easy;
395 multi->easy.prev = &multi->easy;
397 return (CURLM *) multi;
400 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
401 CURL *easy_handle)
403 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
404 struct Curl_one_easy *easy;
405 struct closure *cl;
406 struct closure *prev=NULL;
408 /* First, make some basic checks that the CURLM handle is a good handle */
409 if(!GOOD_MULTI_HANDLE(multi))
410 return CURLM_BAD_HANDLE;
412 /* Verify that we got a somewhat good easy handle too */
413 if(!GOOD_EASY_HANDLE(easy_handle))
414 return CURLM_BAD_EASY_HANDLE;
416 /* Prevent users to add the same handle more than once! */
417 if(((struct SessionHandle *)easy_handle)->multi)
418 /* possibly we should create a new unique error code for this condition */
419 return CURLM_BAD_EASY_HANDLE;
421 /* Now, time to add an easy handle to the multi stack */
422 easy = (struct Curl_one_easy *)calloc(sizeof(struct Curl_one_easy), 1);
423 if(!easy)
424 return CURLM_OUT_OF_MEMORY;
426 cl = multi->closure;
427 while(cl) {
428 struct closure *next = cl->next;
429 if(cl->easy_handle == (struct SessionHandle *)easy_handle) {
430 /* remove this handle from the closure list */
431 free(cl);
432 if(prev)
433 prev->next = next;
434 else
435 multi->closure = next;
436 break; /* no need to continue since this handle can only be present once
437 in the list */
439 prev = cl;
440 cl = next;
443 /* set the easy handle */
444 easy->easy_handle = easy_handle;
445 multistate(easy, CURLM_STATE_INIT);
447 /* set the back pointer to one_easy to assist in removal */
448 easy->easy_handle->multi_pos = easy;
450 /* for multi interface connections, we share DNS cache automatically if the
451 easy handle's one is currently private. */
452 if(easy->easy_handle->dns.hostcache &&
453 (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) {
454 Curl_hash_destroy(easy->easy_handle->dns.hostcache);
455 easy->easy_handle->dns.hostcache = NULL;
456 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
459 if(!easy->easy_handle->dns.hostcache ||
460 (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) {
461 easy->easy_handle->dns.hostcache = multi->hostcache;
462 easy->easy_handle->dns.hostcachetype = HCACHE_MULTI;
465 if(easy->easy_handle->state.connc) {
466 if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) {
467 /* kill old private version */
468 Curl_rm_connc(easy->easy_handle->state.connc);
469 /* point out our shared one instead */
470 easy->easy_handle->state.connc = multi->connc;
472 /* else it is already using multi? */
474 else
475 /* point out our shared one */
476 easy->easy_handle->state.connc = multi->connc;
478 /* Make sure the type is setup correctly */
479 easy->easy_handle->state.connc->type = CONNCACHE_MULTI;
481 /* This adds the new entry at the back of the list
482 to try and maintain a FIFO queue so the pipelined
483 requests are in order. */
485 /* We add this new entry last in the list. We make our 'next' point to the
486 'first' struct and our 'prev' point to the previous 'prev' */
487 easy->next = &multi->easy;
488 easy->prev = multi->easy.prev;
490 /* make 'easy' the last node in the chain */
491 multi->easy.prev = easy;
493 /* if there was a prev node, make sure its 'next' pointer links to
494 the new node */
495 easy->prev->next = easy;
497 Curl_easy_addmulti(easy_handle, multi_handle);
499 /* make the SessionHandle struct refer back to this struct */
500 easy->easy_handle->set.one_easy = easy;
502 /* Set the timeout for this handle to expire really soon so that it will
503 be taken care of even when this handle is added in the midst of operation
504 when only the curl_multi_socket() API is used. During that flow, only
505 sockets that time-out or have actions will be dealt with. Since this
506 handle has no action yet, we make sure it times out to get things to
507 happen. */
508 Curl_expire(easy->easy_handle, 1);
510 /* increase the node-counter */
511 multi->num_easy++;
513 if((multi->num_easy * 4) > multi->connc->num) {
514 /* We want the connection cache to have plenty room. Before we supported
515 the shared cache every single easy handle had 5 entries in their cache
516 by default. */
517 long newmax = multi->num_easy * 4;
519 if(multi->maxconnects && (multi->maxconnects < newmax))
520 /* don't grow beyond the allowed size */
521 newmax = multi->maxconnects;
523 if(newmax > multi->connc->num) {
524 /* we only do this is we can in fact grow the cache */
525 CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax);
526 if(res != CURLE_OK) {
527 /* FIXME: may need to do more cleanup here */
528 curl_multi_remove_handle(multi_handle, easy_handle);
529 return CURLM_OUT_OF_MEMORY;
534 /* increase the alive-counter */
535 multi->num_alive++;
537 update_timer(multi);
538 return CURLM_OK;
541 #if 0
542 /* Debug-function, used like this:
544 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
546 * Enable the hash print function first by editing hash.c
548 static void debug_print_sock_hash(void *p)
550 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
552 fprintf(stderr, " [easy %p/magic %x/socket %d]",
553 (void *)sh->easy, sh->easy->magic, sh->socket);
555 #endif
557 CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
558 CURL *curl_handle)
560 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
561 struct Curl_one_easy *easy;
563 /* First, make some basic checks that the CURLM handle is a good handle */
564 if(!GOOD_MULTI_HANDLE(multi))
565 return CURLM_BAD_HANDLE;
567 /* Verify that we got a somewhat good easy handle too */
568 if(!GOOD_EASY_HANDLE(curl_handle))
569 return CURLM_BAD_EASY_HANDLE;
571 /* pick-up from the 'curl_handle' the kept position in the list */
572 easy = ((struct SessionHandle *)curl_handle)->multi_pos;
574 if(easy) {
575 bool premature = (bool)(easy->state != CURLM_STATE_COMPLETED);
577 /* If the 'state' is not INIT or COMPLETED, we might need to do something
578 nice to put the easy_handle in a good known state when this returns. */
579 if(premature)
580 /* this handle is "alive" so we need to count down the total number of
581 alive connections when this is removed */
582 multi->num_alive--;
584 if(easy->easy_conn &&
585 (easy->easy_conn->send_pipe->size +
586 easy->easy_conn->recv_pipe->size > 1) &&
587 easy->state > CURLM_STATE_WAITDO &&
588 easy->state < CURLM_STATE_COMPLETED) {
589 /* If the handle is in a pipeline and has started sending off its
590 request but not received its reponse yet, we need to close
591 connection. */
592 easy->easy_conn->bits.close = TRUE;
593 /* Set connection owner so that Curl_done() closes it.
594 We can sefely do this here since connection is killed. */
595 easy->easy_conn->data = easy->easy_handle;
598 /* The timer must be shut down before easy->multi is set to NULL,
599 else the timenode will remain in the splay tree after
600 curl_easy_cleanup is called. */
601 Curl_expire(easy->easy_handle, 0);
603 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
604 /* clear out the usage of the shared DNS cache */
605 easy->easy_handle->dns.hostcache = NULL;
606 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
609 /* we must call Curl_done() here (if we still "own it") so that we don't
610 leave a half-baked one around */
611 if(easy->easy_conn &&
612 (easy->easy_conn->data == easy->easy_handle)) {
614 /* Curl_done() clears the conn->data field to lose the association
615 between the easy handle and the connection
617 Note that this ignores the return code simply because there's nothing
618 really useful to do with it anyway! */
619 (void)Curl_done(&easy->easy_conn, easy->result, premature);
621 if(easy->easy_conn)
622 /* the connection is still alive, set back the association to enable
623 the check below to trigger TRUE */
624 easy->easy_conn->data = easy->easy_handle;
627 /* If this easy_handle was the last one in charge for one or more
628 connections a the shared connection cache, we might need to keep this
629 handle around until either A) the connection is closed and killed
630 properly, or B) another easy_handle uses the connection.
632 The reason why we need to have a easy_handle associated with a live
633 connection is simply that some connections will need a handle to get
634 closed down properly. Currently, the only connections that need to keep
635 a easy_handle handle around are using FTP(S). Such connections have
636 the PROT_CLOSEACTION bit set.
638 Thus, we need to check for all connections in the shared cache that
639 points to this handle and are using PROT_CLOSEACTION. If there's any,
640 we need to add this handle to the list of "easy handles kept around for
641 nice connection closures".
643 if(multi_conn_using(multi, easy->easy_handle)) {
644 /* There's at least one connection using this handle so we must keep
645 this handle around. We also keep the connection cache pointer
646 pointing to the shared one since that will be used on close as
647 well. */
648 easy->easy_handle->state.shared_conn = multi;
650 /* this handle is still being used by a shared connection cache and
651 thus we leave it around for now */
652 add_closure(multi, easy->easy_handle);
655 if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
656 /* if this was using the shared connection cache we clear the pointer
657 to that since we're not part of that handle anymore */
658 easy->easy_handle->state.connc = NULL;
660 /* and modify the connectindex since this handle can't point to the
661 connection cache anymore */
662 if(easy->easy_conn &&
663 (easy->easy_conn->send_pipe->size +
664 easy->easy_conn->recv_pipe->size == 0))
665 easy->easy_conn->connectindex = -1;
668 /* change state without using multistate(), only to make singlesocket() do
669 what we want */
670 easy->state = CURLM_STATE_COMPLETED;
671 singlesocket(multi, easy); /* to let the application know what sockets
672 that vanish with this handle */
674 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association
675 to this multi handle */
677 /* make the previous node point to our next */
678 if(easy->prev)
679 easy->prev->next = easy->next;
680 /* make our next point to our previous node */
681 if(easy->next)
682 easy->next->prev = easy->prev;
684 easy->easy_handle->set.one_easy = NULL; /* detached */
686 /* Null the position in the controlling structure */
687 easy->easy_handle->multi_pos = NULL;
689 /* NOTE NOTE NOTE
690 We do not touch the easy handle here! */
691 if(easy->msg)
692 free(easy->msg);
693 free(easy);
695 multi->num_easy--; /* one less to care about now */
697 update_timer(multi);
698 return CURLM_OK;
700 else
701 return CURLM_BAD_EASY_HANDLE; /* twasn't found */
704 bool Curl_multi_canPipeline(const struct Curl_multi* multi)
706 return multi->pipelining_enabled;
709 void Curl_multi_handlePipeBreak(struct SessionHandle *data)
711 struct Curl_one_easy *one_easy = data->set.one_easy;
713 if(one_easy)
714 one_easy->easy_conn = NULL;
717 static int waitconnect_getsock(struct connectdata *conn,
718 curl_socket_t *sock,
719 int numsocks)
721 if(!numsocks)
722 return GETSOCK_BLANK;
724 sock[0] = conn->sock[FIRSTSOCKET];
726 /* when we've sent a CONNECT to a proxy, we should rather wait for the
727 socket to become readable to be able to get the response headers */
728 if(conn->bits.tunnel_connecting)
729 return GETSOCK_READSOCK(0);
731 return GETSOCK_WRITESOCK(0);
734 static int domore_getsock(struct connectdata *conn,
735 curl_socket_t *sock,
736 int numsocks)
738 if(!numsocks)
739 return GETSOCK_BLANK;
741 /* When in DO_MORE state, we could be either waiting for us
742 to connect to a remote site, or we could wait for that site
743 to connect to us. It makes a difference in the way: if we
744 connect to the site we wait for the socket to become writable, if
745 the site connects to us we wait for it to become readable */
746 sock[0] = conn->sock[SECONDARYSOCKET];
748 return GETSOCK_WRITESOCK(0);
751 /* returns bitmapped flags for this handle and its sockets */
752 static int multi_getsock(struct Curl_one_easy *easy,
753 curl_socket_t *socks, /* points to numsocks number
754 of sockets */
755 int numsocks)
757 /* If the pipe broke, or if there's no connection left for this easy handle,
758 then we MUST bail out now with no bitmask set. The no connection case can
759 happen when this is called from curl_multi_remove_handle() =>
760 singlesocket() => multi_getsock().
763 if(easy->easy_handle->state.pipe_broke ||
764 !easy->easy_conn) {
765 return 0;
768 if(easy->state > CURLM_STATE_CONNECT &&
769 easy->state < CURLM_STATE_COMPLETED) {
770 /* Set up ownership correctly */
771 easy->easy_conn->data = easy->easy_handle;
774 switch(easy->state) {
775 default:
776 #if 0 /* switch back on these cases to get the compiler to check for all enums
777 to be present */
778 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
779 case CURLM_STATE_COMPLETED:
780 case CURLM_STATE_INIT:
781 case CURLM_STATE_CONNECT:
782 case CURLM_STATE_WAITDO:
783 case CURLM_STATE_DONE:
784 case CURLM_STATE_LAST:
785 /* this will get called with CURLM_STATE_COMPLETED when a handle is
786 removed */
787 #endif
788 return 0;
790 case CURLM_STATE_WAITRESOLVE:
791 return Curl_resolv_getsock(easy->easy_conn, socks, numsocks);
793 case CURLM_STATE_PROTOCONNECT:
794 return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
796 case CURLM_STATE_DO:
797 case CURLM_STATE_DOING:
798 return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
800 case CURLM_STATE_WAITPROXYCONNECT:
801 case CURLM_STATE_WAITCONNECT:
802 return waitconnect_getsock(easy->easy_conn, socks, numsocks);
804 case CURLM_STATE_DO_MORE:
805 return domore_getsock(easy->easy_conn, socks, numsocks);
807 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
808 to waiting for the same as the *PERFORM states */
809 case CURLM_STATE_PERFORM:
810 case CURLM_STATE_WAITPERFORM:
811 return Curl_single_getsock(easy->easy_conn, socks, numsocks);
816 CURLMcode curl_multi_fdset(CURLM *multi_handle,
817 fd_set *read_fd_set, fd_set *write_fd_set,
818 fd_set *exc_fd_set, int *max_fd)
820 /* Scan through all the easy handles to get the file descriptors set.
821 Some easy handles may not have connected to the remote host yet,
822 and then we must make sure that is done. */
823 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
824 struct Curl_one_easy *easy;
825 int this_max_fd=-1;
826 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
827 int bitmap;
828 int i;
829 (void)exc_fd_set; /* not used */
831 if(!GOOD_MULTI_HANDLE(multi))
832 return CURLM_BAD_HANDLE;
834 easy=multi->easy.next;
835 while(easy != &multi->easy) {
836 bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
838 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
839 curl_socket_t s = CURL_SOCKET_BAD;
841 if(bitmap & GETSOCK_READSOCK(i)) {
842 FD_SET(sockbunch[i], read_fd_set);
843 s = sockbunch[i];
845 if(bitmap & GETSOCK_WRITESOCK(i)) {
846 FD_SET(sockbunch[i], write_fd_set);
847 s = sockbunch[i];
849 if(s == CURL_SOCKET_BAD)
850 /* this socket is unused, break out of loop */
851 break;
852 else {
853 if((int)s > this_max_fd)
854 this_max_fd = (int)s;
858 easy = easy->next; /* check next handle */
861 *max_fd = this_max_fd;
863 return CURLM_OK;
866 static CURLMcode multi_runsingle(struct Curl_multi *multi,
867 struct Curl_one_easy *easy)
869 struct Curl_message *msg = NULL;
870 bool connected;
871 bool async;
872 bool protocol_connect = FALSE;
873 bool dophase_done;
874 bool done = FALSE;
875 CURLMcode result = CURLM_OK;
876 struct SingleRequest *k;
878 if(!GOOD_EASY_HANDLE(easy->easy_handle))
879 return CURLM_BAD_EASY_HANDLE;
881 do {
882 /* this is a do-while loop just to allow a break to skip to the end
883 of it */
884 bool disconnect_conn = FALSE;
886 /* Handle the case when the pipe breaks, i.e., the connection
887 we're using gets cleaned up and we're left with nothing. */
888 if(easy->easy_handle->state.pipe_broke) {
889 infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n",
890 easy, easy->easy_handle->state.path);
892 if(easy->state != CURLM_STATE_COMPLETED) {
893 /* Head back to the CONNECT state */
894 multistate(easy, CURLM_STATE_CONNECT);
895 result = CURLM_CALL_MULTI_PERFORM;
896 easy->result = CURLE_OK;
899 easy->easy_handle->state.pipe_broke = FALSE;
900 easy->easy_conn = NULL;
901 break;
904 if(easy->state > CURLM_STATE_CONNECT &&
905 easy->state < CURLM_STATE_COMPLETED)
906 /* Make sure we set the connection's current owner */
907 easy->easy_conn->data = easy->easy_handle;
909 switch(easy->state) {
910 case CURLM_STATE_INIT:
911 /* init this transfer. */
912 easy->result=Curl_pretransfer(easy->easy_handle);
914 if(CURLE_OK == easy->result) {
915 /* after init, go CONNECT */
916 multistate(easy, CURLM_STATE_CONNECT);
917 result = CURLM_CALL_MULTI_PERFORM;
919 easy->easy_handle->state.used_interface = Curl_if_multi;
921 break;
923 case CURLM_STATE_CONNECT:
924 /* Connect. We get a connection identifier filled in. */
925 Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
926 easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
927 &async, &protocol_connect);
929 if(CURLE_OK == easy->result) {
930 /* Add this handle to the send or pend pipeline */
931 easy->result = addHandleToSendOrPendPipeline(easy->easy_handle,
932 easy->easy_conn);
933 if(CURLE_OK == easy->result) {
934 if(async)
935 /* We're now waiting for an asynchronous name lookup */
936 multistate(easy, CURLM_STATE_WAITRESOLVE);
937 else {
938 /* after the connect has been sent off, go WAITCONNECT unless the
939 protocol connect is already done and we can go directly to
940 WAITDO or DO! */
941 result = CURLM_CALL_MULTI_PERFORM;
943 if(protocol_connect)
944 multistate(easy, multi->pipelining_enabled?
945 CURLM_STATE_WAITDO:CURLM_STATE_DO);
946 else {
947 #ifndef CURL_DISABLE_HTTP
948 if(easy->easy_conn->bits.tunnel_connecting)
949 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
950 else
951 #endif
952 multistate(easy, CURLM_STATE_WAITCONNECT);
957 break;
959 case CURLM_STATE_WAITRESOLVE:
960 /* awaiting an asynch name resolve to complete */
962 struct Curl_dns_entry *dns = NULL;
964 /* check if we have the name resolved by now */
965 easy->result = Curl_is_resolved(easy->easy_conn, &dns);
967 if(dns) {
968 /* Update sockets here. Mainly because the socket(s) may have been
969 closed and the application thus needs to be told, even if it is
970 likely that the same socket(s) will again be used further down. */
971 singlesocket(multi, easy);
973 /* Perform the next step in the connection phase, and then move on
974 to the WAITCONNECT state */
975 easy->result = Curl_async_resolved(easy->easy_conn,
976 &protocol_connect);
978 if(CURLE_OK != easy->result)
979 /* if Curl_async_resolved() returns failure, the connection struct
980 is already freed and gone */
981 easy->easy_conn = NULL; /* no more connection */
982 else {
983 /* call again please so that we get the next socket setup */
984 result = CURLM_CALL_MULTI_PERFORM;
985 if(protocol_connect)
986 multistate(easy, multi->pipelining_enabled?
987 CURLM_STATE_WAITDO:CURLM_STATE_DO);
988 else {
989 #ifndef CURL_DISABLE_HTTP
990 if(easy->easy_conn->bits.tunnel_connecting)
991 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
992 else
993 #endif
994 multistate(easy, CURLM_STATE_WAITCONNECT);
999 if(CURLE_OK != easy->result) {
1000 /* failure detected */
1001 disconnect_conn = TRUE;
1002 break;
1005 break;
1007 #ifndef CURL_DISABLE_HTTP
1008 case CURLM_STATE_WAITPROXYCONNECT:
1009 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1010 easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect);
1012 if(easy->easy_conn->bits.proxy_connect_closed) {
1013 /* reset the error buffer */
1014 if(easy->easy_handle->set.errorbuffer)
1015 easy->easy_handle->set.errorbuffer[0] = '\0';
1016 easy->easy_handle->state.errorbuf = FALSE;
1018 easy->result = CURLE_OK;
1019 result = CURLM_CALL_MULTI_PERFORM;
1020 multistate(easy, CURLM_STATE_CONNECT);
1022 else if (CURLE_OK == easy->result) {
1023 if(!easy->easy_conn->bits.tunnel_connecting)
1024 multistate(easy, CURLM_STATE_WAITCONNECT);
1026 break;
1027 #endif
1029 case CURLM_STATE_WAITCONNECT:
1030 /* awaiting a completion of an asynch connect */
1031 easy->result = Curl_is_connected(easy->easy_conn,
1032 FIRSTSOCKET,
1033 &connected);
1034 if(connected)
1035 easy->result = Curl_protocol_connect(easy->easy_conn,
1036 &protocol_connect);
1038 if(CURLE_OK != easy->result) {
1039 /* failure detected */
1040 /* Just break, the cleaning up is handled all in one place */
1041 disconnect_conn = TRUE;
1042 break;
1045 if(connected) {
1046 if(!protocol_connect) {
1047 /* We have a TCP connection, but 'protocol_connect' may be false
1048 and then we continue to 'STATE_PROTOCONNECT'. If protocol
1049 connect is TRUE, we move on to STATE_DO.
1050 BUT if we are using a proxy we must change to WAITPROXYCONNECT
1052 #ifndef CURL_DISABLE_HTTP
1053 if(easy->easy_conn->bits.tunnel_connecting)
1054 multistate(easy, CURLM_STATE_WAITPROXYCONNECT);
1055 else
1056 #endif
1057 multistate(easy, CURLM_STATE_PROTOCONNECT);
1059 else {
1060 /* after the connect has completed, go WAITDO or DO */
1061 multistate(easy, multi->pipelining_enabled?
1062 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1064 result = CURLM_CALL_MULTI_PERFORM;
1067 break;
1069 case CURLM_STATE_PROTOCONNECT:
1070 /* protocol-specific connect phase */
1071 easy->result = Curl_protocol_connecting(easy->easy_conn,
1072 &protocol_connect);
1073 if((easy->result == CURLE_OK) && protocol_connect) {
1074 /* after the connect has completed, go WAITDO or DO */
1075 multistate(easy, multi->pipelining_enabled?
1076 CURLM_STATE_WAITDO:CURLM_STATE_DO);
1077 result = CURLM_CALL_MULTI_PERFORM;
1079 else if(easy->result) {
1080 /* failure detected */
1081 Curl_posttransfer(easy->easy_handle);
1082 Curl_done(&easy->easy_conn, easy->result, FALSE);
1083 disconnect_conn = TRUE;
1085 break;
1087 case CURLM_STATE_WAITDO:
1088 /* Wait for our turn to DO when we're pipelining requests */
1089 #ifdef CURLDEBUG
1090 infof(easy->easy_handle, "Conn %d send pipe %d inuse %d athead %d\n",
1091 easy->easy_conn->connectindex,
1092 easy->easy_conn->send_pipe->size,
1093 easy->easy_conn->writechannel_inuse,
1094 isHandleAtHead(easy->easy_handle,
1095 easy->easy_conn->send_pipe));
1096 #endif
1097 if(!easy->easy_conn->writechannel_inuse &&
1098 isHandleAtHead(easy->easy_handle,
1099 easy->easy_conn->send_pipe)) {
1100 /* Grab the channel */
1101 easy->easy_conn->writechannel_inuse = TRUE;
1102 multistate(easy, CURLM_STATE_DO);
1103 result = CURLM_CALL_MULTI_PERFORM;
1105 break;
1107 case CURLM_STATE_DO:
1108 if(easy->easy_handle->set.connect_only) {
1109 /* keep connection open for application to use the socket */
1110 easy->easy_conn->bits.close = FALSE;
1111 multistate(easy, CURLM_STATE_DONE);
1112 easy->result = CURLE_OK;
1113 result = CURLM_OK;
1115 else {
1116 /* Perform the protocol's DO action */
1117 easy->result = Curl_do(&easy->easy_conn,
1118 &dophase_done);
1120 if(CURLE_OK == easy->result) {
1122 if(!dophase_done) {
1123 /* DO was not completed in one function call, we must continue
1124 DOING... */
1125 multistate(easy, CURLM_STATE_DOING);
1126 result = CURLM_OK;
1129 /* after DO, go DO_DONE... or DO_MORE */
1130 else if(easy->easy_conn->bits.do_more) {
1131 /* we're supposed to do more, but we need to sit down, relax
1132 and wait a little while first */
1133 multistate(easy, CURLM_STATE_DO_MORE);
1134 result = CURLM_OK;
1136 else {
1137 /* we're done with the DO, now DO_DONE */
1138 multistate(easy, CURLM_STATE_DO_DONE);
1139 result = CURLM_CALL_MULTI_PERFORM;
1142 else {
1143 /* failure detected */
1144 Curl_posttransfer(easy->easy_handle);
1145 Curl_done(&easy->easy_conn, easy->result, FALSE);
1146 disconnect_conn = TRUE;
1149 break;
1151 case CURLM_STATE_DOING:
1152 /* we continue DOING until the DO phase is complete */
1153 easy->result = Curl_protocol_doing(easy->easy_conn,
1154 &dophase_done);
1155 if(CURLE_OK == easy->result) {
1156 if(dophase_done) {
1157 /* after DO, go PERFORM... or DO_MORE */
1158 if(easy->easy_conn->bits.do_more) {
1159 /* we're supposed to do more, but we need to sit down, relax
1160 and wait a little while first */
1161 multistate(easy, CURLM_STATE_DO_MORE);
1162 result = CURLM_OK;
1164 else {
1165 /* we're done with the DO, now DO_DONE */
1166 multistate(easy, CURLM_STATE_DO_DONE);
1167 result = CURLM_CALL_MULTI_PERFORM;
1169 } /* dophase_done */
1171 else {
1172 /* failure detected */
1173 Curl_posttransfer(easy->easy_handle);
1174 Curl_done(&easy->easy_conn, easy->result, FALSE);
1175 disconnect_conn = TRUE;
1177 break;
1179 case CURLM_STATE_DO_MORE:
1180 /* Ready to do more? */
1181 easy->result = Curl_is_connected(easy->easy_conn,
1182 SECONDARYSOCKET,
1183 &connected);
1184 if(connected) {
1186 * When we are connected, DO MORE and then go DO_DONE
1188 easy->result = Curl_do_more(easy->easy_conn);
1190 /* No need to remove ourselves from the send pipeline here since that
1191 is done for us in Curl_done() */
1193 if(CURLE_OK == easy->result) {
1194 multistate(easy, CURLM_STATE_DO_DONE);
1195 result = CURLM_CALL_MULTI_PERFORM;
1197 else {
1198 /* failure detected */
1199 Curl_posttransfer(easy->easy_handle);
1200 Curl_done(&easy->easy_conn, easy->result, FALSE);
1201 disconnect_conn = TRUE;
1204 break;
1206 case CURLM_STATE_DO_DONE:
1207 /* Move ourselves from the send to recv pipeline */
1208 moveHandleFromSendToRecvPipeline(easy->easy_handle, easy->easy_conn);
1209 /* Check if we can move pending requests to send pipe */
1210 checkPendPipeline(easy->easy_conn);
1211 multistate(easy, CURLM_STATE_WAITPERFORM);
1212 result = CURLM_CALL_MULTI_PERFORM;
1213 break;
1215 case CURLM_STATE_WAITPERFORM:
1216 #ifdef CURLDEBUG
1217 infof(easy->easy_handle, "Conn %d recv pipe %d inuse %d athead %d\n",
1218 easy->easy_conn->connectindex,
1219 easy->easy_conn->recv_pipe->size,
1220 easy->easy_conn->readchannel_inuse,
1221 isHandleAtHead(easy->easy_handle,
1222 easy->easy_conn->recv_pipe));
1223 #endif
1224 /* Wait for our turn to PERFORM */
1225 if(!easy->easy_conn->readchannel_inuse &&
1226 isHandleAtHead(easy->easy_handle,
1227 easy->easy_conn->recv_pipe)) {
1228 /* Grab the channel */
1229 easy->easy_conn->readchannel_inuse = TRUE;
1230 multistate(easy, CURLM_STATE_PERFORM);
1231 result = CURLM_CALL_MULTI_PERFORM;
1233 break;
1235 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1236 /* if both rates are within spec, resume transfer */
1237 Curl_pgrsUpdate(easy->easy_conn);
1238 if( ( ( easy->easy_handle->set.max_send_speed == 0 ) ||
1239 ( easy->easy_handle->progress.ulspeed <
1240 easy->easy_handle->set.max_send_speed ) ) &&
1241 ( ( easy->easy_handle->set.max_recv_speed == 0 ) ||
1242 ( easy->easy_handle->progress.dlspeed <
1243 easy->easy_handle->set.max_recv_speed ) )
1245 multistate(easy, CURLM_STATE_PERFORM);
1246 break;
1248 case CURLM_STATE_PERFORM:
1249 /* check if over speed */
1250 if( ( ( easy->easy_handle->set.max_send_speed > 0 ) &&
1251 ( easy->easy_handle->progress.ulspeed >
1252 easy->easy_handle->set.max_send_speed ) ) ||
1253 ( ( easy->easy_handle->set.max_recv_speed > 0 ) &&
1254 ( easy->easy_handle->progress.dlspeed >
1255 easy->easy_handle->set.max_recv_speed ) )
1257 /* Transfer is over the speed limit. Change state. TODO: Call
1258 * Curl_expire() with the time left until we're targeted to be below
1259 * the speed limit again. */
1260 multistate(easy, CURLM_STATE_TOOFAST );
1261 break;
1264 /* read/write data if it is ready to do so */
1265 easy->result = Curl_readwrite(easy->easy_conn, &done);
1267 k = &easy->easy_handle->req;
1269 if(!(k->keepon & KEEP_READ)) {
1270 /* We're done reading */
1271 easy->easy_conn->readchannel_inuse = FALSE;
1274 if(!(k->keepon & KEEP_WRITE)) {
1275 /* We're done writing */
1276 easy->easy_conn->writechannel_inuse = FALSE;
1279 if(easy->result) {
1280 /* The transfer phase returned error, we mark the connection to get
1281 * closed to prevent being re-used. This is because we can't
1282 * possibly know if the connection is in a good shape or not now. */
1283 easy->easy_conn->bits.close = TRUE;
1284 Curl_removeHandleFromPipeline(easy->easy_handle,
1285 easy->easy_conn->recv_pipe);
1287 if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
1288 /* if we failed anywhere, we must clean up the secondary socket if
1289 it was used */
1290 sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
1291 easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
1293 Curl_posttransfer(easy->easy_handle);
1294 Curl_done(&easy->easy_conn, easy->result, FALSE);
1296 else if(TRUE == done) {
1297 char *newurl;
1298 bool retry = Curl_retry_request(easy->easy_conn, &newurl);
1299 followtype follow=FOLLOW_NONE;
1301 /* call this even if the readwrite function returned error */
1302 Curl_posttransfer(easy->easy_handle);
1304 /* we're no longer receving */
1305 Curl_removeHandleFromPipeline(easy->easy_handle,
1306 easy->easy_conn->recv_pipe);
1308 /* expire the new receiving pipeline head */
1309 if(easy->easy_conn->recv_pipe->head)
1310 Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1);
1312 /* Check if we can move pending requests to send pipe */
1313 checkPendPipeline(easy->easy_conn);
1315 /* When we follow redirects, must to go back to the CONNECT state */
1316 if(easy->easy_handle->req.newurl || retry) {
1317 if(!retry) {
1318 /* if the URL is a follow-location and not just a retried request
1319 then figure out the URL here */
1320 newurl = easy->easy_handle->req.newurl;
1321 easy->easy_handle->req.newurl = NULL;
1322 follow = FOLLOW_REDIR;
1324 else
1325 follow = FOLLOW_RETRY;
1326 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1327 if(easy->result == CURLE_OK)
1328 easy->result = Curl_follow(easy->easy_handle, newurl, follow);
1329 if(CURLE_OK == easy->result) {
1330 multistate(easy, CURLM_STATE_CONNECT);
1331 result = CURLM_CALL_MULTI_PERFORM;
1333 else
1334 /* Since we "took it", we are in charge of freeing this on
1335 failure */
1336 free(newurl);
1338 else {
1339 /* after the transfer is done, go DONE */
1340 multistate(easy, CURLM_STATE_DONE);
1341 result = CURLM_CALL_MULTI_PERFORM;
1345 break;
1347 case CURLM_STATE_DONE:
1348 /* Remove ourselves from the receive pipeline */
1349 Curl_removeHandleFromPipeline(easy->easy_handle,
1350 easy->easy_conn->recv_pipe);
1351 /* Check if we can move pending requests to send pipe */
1352 checkPendPipeline(easy->easy_conn);
1354 if(easy->easy_conn->bits.stream_was_rewound) {
1355 /* This request read past its response boundary so we quickly let the
1356 other requests consume those bytes since there is no guarantee that
1357 the socket will become active again */
1358 result = CURLM_CALL_MULTI_PERFORM;
1361 /* post-transfer command */
1362 easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
1364 /* after we have DONE what we're supposed to do, go COMPLETED, and
1365 it doesn't matter what the Curl_done() returned! */
1366 multistate(easy, CURLM_STATE_COMPLETED);
1368 break;
1370 case CURLM_STATE_COMPLETED:
1371 /* this is a completed transfer, it is likely to still be connected */
1373 /* This node should be delinked from the list now and we should post
1374 an information message that we are complete. */
1376 /* Important: reset the conn pointer so that we don't point to memory
1377 that could be freed anytime */
1378 easy->easy_conn = NULL;
1379 break;
1381 default:
1382 return CURLM_INTERNAL_ERROR;
1385 if(CURLM_STATE_COMPLETED != easy->state) {
1386 if(CURLE_OK != easy->result) {
1388 * If an error was returned, and we aren't in completed state now,
1389 * then we go to completed and consider this transfer aborted.
1392 /* NOTE: no attempt to disconnect connections must be made
1393 in the case blocks above - cleanup happens only here */
1395 easy->easy_handle->state.pipe_broke = FALSE;
1397 if(easy->easy_conn) {
1398 /* if this has a connection, unsubscribe from the pipelines */
1399 easy->easy_conn->writechannel_inuse = FALSE;
1400 easy->easy_conn->readchannel_inuse = FALSE;
1401 Curl_removeHandleFromPipeline(easy->easy_handle,
1402 easy->easy_conn->send_pipe);
1403 Curl_removeHandleFromPipeline(easy->easy_handle,
1404 easy->easy_conn->recv_pipe);
1405 /* Check if we can move pending requests to send pipe */
1406 checkPendPipeline(easy->easy_conn);
1409 if(disconnect_conn) {
1410 Curl_disconnect(easy->easy_conn); /* disconnect properly */
1412 /* This is where we make sure that the easy_conn pointer is reset.
1413 We don't have to do this in every case block above where a
1414 failure is detected */
1415 easy->easy_conn = NULL;
1418 multistate(easy, CURLM_STATE_COMPLETED);
1421 } while(0);
1422 if((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
1423 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1424 /* clear out the usage of the shared DNS cache */
1425 easy->easy_handle->dns.hostcache = NULL;
1426 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1429 /* now add a node to the Curl_message linked list with this info */
1430 msg = (struct Curl_message *)malloc(sizeof(struct Curl_message));
1432 if(!msg)
1433 return CURLM_OUT_OF_MEMORY;
1435 msg->extmsg.msg = CURLMSG_DONE;
1436 msg->extmsg.easy_handle = easy->easy_handle;
1437 msg->extmsg.data.result = easy->result;
1438 msg->next = NULL;
1440 easy->msg = msg;
1441 easy->msg_num = 1; /* there is one unread message here */
1443 multi->num_msgs++; /* increase message counter */
1446 if(CURLM_CALL_MULTI_PERFORM == result)
1447 /* Set the timeout for this handle to expire really soon so that it will
1448 be taken care of even when this handle is added in the midst of
1449 operation when only the curl_multi_socket() API is used. During that
1450 flow, only sockets that time-out or have actions will be dealt
1451 with. Since this handle has no action yet, we make sure it times out to
1452 get things to happen. Also, this makes it less important for callers of
1453 the curl_multi_* functions to bother about the CURLM_CALL_MULTI_PERFORM
1454 return code, as long as they deal with the timeouts properly. */
1455 Curl_expire(easy->easy_handle, 1);
1457 return result;
1461 CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
1463 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1464 struct Curl_one_easy *easy;
1465 CURLMcode returncode=CURLM_OK;
1466 struct Curl_tree *t;
1468 if(!GOOD_MULTI_HANDLE(multi))
1469 return CURLM_BAD_HANDLE;
1471 easy=multi->easy.next;
1472 while(easy != &multi->easy) {
1473 CURLMcode result;
1475 result = multi_runsingle(multi, easy);
1476 if(result)
1477 returncode = result;
1479 easy = easy->next; /* operate on next handle */
1483 * Simply remove all expired timers from the splay since handles are dealt
1484 * with unconditionally by this function and curl_multi_timeout() requires
1485 * that already passed/handled expire times are removed from the splay.
1487 do {
1488 struct timeval now = Curl_tvnow();
1490 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1491 if(t) {
1492 struct SessionHandle *d = t->payload;
1493 struct timeval* tv = &d->state.expiretime;
1495 /* clear the expire times within the handles that we remove from the
1496 splay tree */
1497 tv->tv_sec = 0;
1498 tv->tv_usec = 0;
1501 } while(t);
1503 *running_handles = multi->num_alive;
1505 if( CURLM_OK >= returncode )
1506 update_timer(multi);
1507 return returncode;
1510 /* This is called when an easy handle is cleanup'ed that is part of a multi
1511 handle */
1512 void Curl_multi_rmeasy(void *multi_handle, CURL *easy_handle)
1514 curl_multi_remove_handle(multi_handle, easy_handle);
1518 CURLMcode curl_multi_cleanup(CURLM *multi_handle)
1520 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1521 struct Curl_one_easy *easy;
1522 struct Curl_one_easy *nexteasy;
1523 int i;
1524 struct closure *cl;
1525 struct closure *n;
1527 if(GOOD_MULTI_HANDLE(multi)) {
1528 multi->type = 0; /* not good anymore */
1529 Curl_hash_destroy(multi->hostcache);
1530 Curl_hash_destroy(multi->sockhash);
1532 /* go over all connections that have close actions */
1533 for(i=0; i< multi->connc->num; i++) {
1534 if(multi->connc->connects[i] &&
1535 multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
1536 Curl_disconnect(multi->connc->connects[i]);
1537 multi->connc->connects[i] = NULL;
1540 /* now walk through the list of handles we kept around only to be
1541 able to close connections "properly" */
1542 cl = multi->closure;
1543 while(cl) {
1544 cl->easy_handle->state.shared_conn = NULL; /* no more shared */
1545 if(cl->easy_handle->state.closed)
1546 /* close handle only if curl_easy_cleanup() already has been called
1547 for this easy handle */
1548 Curl_close(cl->easy_handle);
1549 n = cl->next;
1550 free(cl);
1551 cl= n;
1554 Curl_rm_connc(multi->connc);
1556 /* remove all easy handles */
1557 easy = multi->easy.next;
1558 while(easy != &multi->easy) {
1559 nexteasy=easy->next;
1560 if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
1561 /* clear out the usage of the shared DNS cache */
1562 easy->easy_handle->dns.hostcache = NULL;
1563 easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
1566 /* Clear the pointer to the connection cache */
1567 easy->easy_handle->state.connc = NULL;
1569 Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */
1571 if(easy->msg)
1572 free(easy->msg);
1573 free(easy);
1574 easy = nexteasy;
1577 free(multi);
1579 return CURLM_OK;
1581 else
1582 return CURLM_BAD_HANDLE;
1585 CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
1587 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1589 *msgs_in_queue = 0; /* default to none */
1591 if(GOOD_MULTI_HANDLE(multi)) {
1592 struct Curl_one_easy *easy;
1594 if(!multi->num_msgs)
1595 return NULL; /* no messages left to return */
1597 easy=multi->easy.next;
1598 while(easy != &multi->easy) {
1599 if(easy->msg_num) {
1600 easy->msg_num--;
1601 break;
1603 easy = easy->next;
1605 if(!easy)
1606 return NULL; /* this means internal count confusion really */
1608 multi->num_msgs--;
1609 *msgs_in_queue = multi->num_msgs;
1611 return &easy->msg->extmsg;
1613 else
1614 return NULL;
1618 * singlesocket() checks what sockets we deal with and their "action state"
1619 * and if we have a different state in any of those sockets from last time we
1620 * call the callback accordingly.
1622 static void singlesocket(struct Curl_multi *multi,
1623 struct Curl_one_easy *easy)
1625 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
1626 int i;
1627 struct Curl_sh_entry *entry;
1628 curl_socket_t s;
1629 int num;
1630 unsigned int curraction;
1632 memset(&socks, 0, sizeof(socks));
1633 for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
1634 socks[i] = CURL_SOCKET_BAD;
1636 /* Fill in the 'current' struct with the state as it is now: what sockets to
1637 supervise and for what actions */
1638 curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE);
1640 /* We have 0 .. N sockets already and we get to know about the 0 .. M
1641 sockets we should have from now on. Detect the differences, remove no
1642 longer supervised ones and add new ones */
1644 /* walk over the sockets we got right now */
1645 for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
1646 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
1647 i++) {
1648 int action = CURL_POLL_NONE;
1650 s = socks[i];
1652 /* get it from the hash */
1653 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1655 if(curraction & GETSOCK_READSOCK(i))
1656 action |= CURL_POLL_IN;
1657 if(curraction & GETSOCK_WRITESOCK(i))
1658 action |= CURL_POLL_OUT;
1660 if(entry) {
1661 /* yeps, already present so check if it has the same action set */
1662 if(entry->action == action)
1663 /* same, continue */
1664 continue;
1666 else {
1667 /* this is a socket we didn't have before, add it! */
1668 entry = sh_addentry(multi->sockhash, s, easy->easy_handle);
1669 if(!entry)
1670 /* fatal */
1671 return;
1674 multi->socket_cb(easy->easy_handle,
1676 action,
1677 multi->socket_userp,
1678 entry ? entry->socketp : NULL);
1680 entry->action = action; /* store the current action state */
1683 num = i; /* number of sockets */
1685 /* when we've walked over all the sockets we should have right now, we must
1686 make sure to detect sockets that are removed */
1687 for(i=0; i< easy->numsocks; i++) {
1688 int j;
1689 s = easy->sockets[i];
1690 for(j=0; j<num; j++) {
1691 if(s == socks[j]) {
1692 /* this is still supervised */
1693 s = CURL_SOCKET_BAD;
1694 break;
1697 if(s != CURL_SOCKET_BAD) {
1698 /* this socket has been removed. Remove it */
1700 entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1701 if(entry) {
1702 /* just a precaution, this socket really SHOULD be in the hash already
1703 but in case it isn't, we don't have to tell the app to remove it
1704 either since it never got to know about it */
1705 multi->socket_cb(easy->easy_handle,
1707 CURL_POLL_REMOVE,
1708 multi->socket_userp,
1709 entry ? entry->socketp : NULL);
1711 sh_delentry(multi->sockhash, s);
1716 memcpy(easy->sockets, socks, num*sizeof(curl_socket_t));
1717 easy->numsocks = num;
1720 static CURLMcode multi_socket(struct Curl_multi *multi,
1721 bool checkall,
1722 curl_socket_t s,
1723 int ev_bitmask,
1724 int *running_handles)
1726 CURLMcode result = CURLM_OK;
1727 struct SessionHandle *data = NULL;
1728 struct Curl_tree *t;
1730 if(checkall) {
1731 struct Curl_one_easy *easyp;
1732 /* *perform() deals with running_handles on its own */
1733 result = curl_multi_perform(multi, running_handles);
1735 /* walk through each easy handle and do the socket state change magic
1736 and callbacks */
1737 easyp=multi->easy.next;
1738 while(easyp != &multi->easy) {
1739 singlesocket(multi, easyp);
1740 easyp = easyp->next;
1743 /* or should we fall-through and do the timer-based stuff? */
1744 return result;
1746 else if(s != CURL_SOCKET_TIMEOUT) {
1748 struct Curl_sh_entry *entry =
1749 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
1751 if(!entry)
1752 /* Unmatched socket, we can't act on it but we ignore this fact. In
1753 real-world tests it has been proved that libevent can in fact give
1754 the application actions even though the socket was just previously
1755 asked to get removed, so thus we better survive stray socket actions
1756 and just move on. */
1758 else {
1759 data = entry->easy;
1761 if(data->magic != CURLEASY_MAGIC_NUMBER)
1762 /* bad bad bad bad bad bad bad */
1763 return CURLM_INTERNAL_ERROR;
1765 if(data->set.one_easy->easy_conn) /* set socket event bitmask */
1766 data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
1768 result = multi_runsingle(multi, data->set.one_easy);
1770 if(data->set.one_easy->easy_conn)
1771 data->set.one_easy->easy_conn->cselect_bits = 0;
1773 if(CURLM_OK >= result)
1774 /* get the socket(s) and check if the state has been changed since
1775 last */
1776 singlesocket(multi, data->set.one_easy);
1778 /* Now we fall-through and do the timer-based stuff, since we don't want
1779 to force the user to have to deal with timeouts as long as at least
1780 one connection in fact has traffic. */
1782 data = NULL; /* set data to NULL again to avoid calling
1783 multi_runsingle() in case there's no need to */
1788 * The loop following here will go on as long as there are expire-times left
1789 * to process in the splay and 'data' will be re-assigned for every expired
1790 * handle we deal with.
1792 do {
1793 struct timeval now;
1795 /* the first loop lap 'data' can be NULL */
1796 if(data) {
1797 result = multi_runsingle(multi, data->set.one_easy);
1799 if(CURLM_OK >= result)
1800 /* get the socket(s) and check if the state has been changed since
1801 last */
1802 singlesocket(multi, data->set.one_easy);
1805 /* Check if there's one (more) expired timer to deal with! This function
1806 extracts a matching node if there is one */
1808 now = Curl_tvnow();
1809 now.tv_usec += 1000; /* to compensate for the truncating of 999us to 0ms,
1810 we always add time here to make the comparison
1811 below better */
1813 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
1814 if(t) {
1815 /* assign 'data' to be the easy handle we just removed from the splay
1816 tree */
1817 data = t->payload;
1818 /* clear the expire time within the handle we removed from the
1819 splay tree */
1820 data->state.expiretime.tv_sec = 0;
1821 data->state.expiretime.tv_usec = 0;
1824 } while(t);
1826 *running_handles = multi->num_alive;
1827 return result;
1830 #undef curl_multi_setopt
1831 CURLMcode curl_multi_setopt(CURLM *multi_handle,
1832 CURLMoption option, ...)
1834 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1835 CURLMcode res = CURLM_OK;
1836 va_list param;
1838 if(!GOOD_MULTI_HANDLE(multi))
1839 return CURLM_BAD_HANDLE;
1841 va_start(param, option);
1843 switch(option) {
1844 case CURLMOPT_SOCKETFUNCTION:
1845 multi->socket_cb = va_arg(param, curl_socket_callback);
1846 break;
1847 case CURLMOPT_SOCKETDATA:
1848 multi->socket_userp = va_arg(param, void *);
1849 break;
1850 case CURLMOPT_PIPELINING:
1851 multi->pipelining_enabled = (bool)(0 != va_arg(param, long));
1852 break;
1853 case CURLMOPT_TIMERFUNCTION:
1854 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
1855 break;
1856 case CURLMOPT_TIMERDATA:
1857 multi->timer_userp = va_arg(param, void *);
1858 break;
1859 case CURLMOPT_MAXCONNECTS:
1860 multi->maxconnects = va_arg(param, long);
1861 break;
1862 default:
1863 res = CURLM_UNKNOWN_OPTION;
1864 break;
1866 va_end(param);
1867 return res;
1870 /* we define curl_multi_socket() in the public multi.h header */
1871 #undef curl_multi_socket
1873 CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
1874 int *running_handles)
1876 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
1877 0, running_handles);
1878 if(CURLM_OK >= result)
1879 update_timer((struct Curl_multi *)multi_handle);
1880 return result;
1883 CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
1884 int ev_bitmask, int *running_handles)
1886 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
1887 ev_bitmask, running_handles);
1888 if(CURLM_OK >= result)
1889 update_timer((struct Curl_multi *)multi_handle);
1890 return result;
1893 CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
1896 CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
1897 TRUE, CURL_SOCKET_BAD, 0, running_handles);
1898 if(CURLM_OK >= result)
1899 update_timer((struct Curl_multi *)multi_handle);
1900 return result;
1903 static CURLMcode multi_timeout(struct Curl_multi *multi,
1904 long *timeout_ms)
1906 static struct timeval tv_zero = {0,0};
1908 if(multi->timetree) {
1909 /* we have a tree of expire times */
1910 struct timeval now = Curl_tvnow();
1912 /* splay the lowest to the bottom */
1913 multi->timetree = Curl_splay(tv_zero, multi->timetree);
1915 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0)
1916 /* some time left before expiration */
1917 *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
1918 else
1919 /* 0 means immediately */
1920 *timeout_ms = 0;
1922 else
1923 *timeout_ms = -1;
1925 return CURLM_OK;
1928 CURLMcode curl_multi_timeout(CURLM *multi_handle,
1929 long *timeout_ms)
1931 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
1933 /* First, make some basic checks that the CURLM handle is a good handle */
1934 if(!GOOD_MULTI_HANDLE(multi))
1935 return CURLM_BAD_HANDLE;
1937 return multi_timeout(multi, timeout_ms);
1941 * Tell the application it should update its timers, if it subscribes to the
1942 * update timer callback.
1944 static int update_timer(struct Curl_multi *multi)
1946 long timeout_ms;
1947 if(!multi->timer_cb)
1948 return 0;
1949 if( multi_timeout(multi, &timeout_ms) != CURLM_OK )
1950 return -1;
1951 if( timeout_ms < 0 )
1952 return 0;
1954 /* When multi_timeout() is done, multi->timetree points to the node with the
1955 * timeout we got the (relative) time-out time for. We can thus easily check
1956 * if this is the same (fixed) time as we got in a previous call and then
1957 * avoid calling the callback again. */
1958 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
1959 return 0;
1961 multi->timer_lastcall = multi->timetree->key;
1963 return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
1966 static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle,
1967 struct connectdata *conn)
1969 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
1970 struct curl_llist *pipeline;
1972 if(!Curl_isPipeliningEnabled(handle) ||
1973 pipeLen == 0)
1974 pipeline = conn->send_pipe;
1975 else {
1976 if(conn->server_supports_pipelining &&
1977 pipeLen < MAX_PIPELINE_LENGTH)
1978 pipeline = conn->send_pipe;
1979 else
1980 pipeline = conn->pend_pipe;
1983 return Curl_addHandleToPipeline(handle, pipeline);
1986 static int checkPendPipeline(struct connectdata *conn)
1988 int result = 0;
1989 struct curl_llist_element *sendhead = conn->send_pipe->head;
1991 if (conn->server_supports_pipelining) {
1992 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
1993 struct curl_llist_element *curr = conn->pend_pipe->head;
1995 while(pipeLen < MAX_PIPELINE_LENGTH && curr) {
1996 Curl_llist_move(conn->pend_pipe, curr,
1997 conn->send_pipe, conn->send_pipe->tail);
1998 Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER);
1999 ++result; /* count how many handles we moved */
2000 curr = conn->pend_pipe->head;
2001 ++pipeLen;
2003 if (result > 0)
2004 conn->now = Curl_tvnow();
2007 if(result) {
2008 /* something moved, check for a new send pipeline leader */
2009 if(sendhead != conn->send_pipe->head) {
2010 /* this is a new one as head, expire it */
2011 conn->writechannel_inuse = FALSE; /* not in use yet */
2012 infof(conn->data, "%p is at send pipe head!\n",
2013 conn->send_pipe->head->ptr);
2014 Curl_expire(conn->send_pipe->head->ptr, 1);
2018 return result;
2021 /* Move this transfer from the sending list to the receiving list.
2023 Pay special attention to the new sending list "leader" as it needs to get
2024 checked to update what sockets it acts on.
2027 static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle,
2028 struct connectdata *conn)
2030 struct curl_llist_element *curr;
2032 curr = conn->send_pipe->head;
2033 while(curr) {
2034 if(curr->ptr == handle) {
2035 Curl_llist_move(conn->send_pipe, curr,
2036 conn->recv_pipe, conn->recv_pipe->tail);
2038 if(conn->send_pipe->head) {
2039 /* Since there's a new easy handle at the start of the send pipeline,
2040 set its timeout value to 1ms to make it trigger instantly */
2041 conn->writechannel_inuse = FALSE; /* not used now */
2042 infof(conn->data, "%p is at send pipe head B!\n",
2043 conn->send_pipe->head->ptr);
2044 Curl_expire(conn->send_pipe->head->ptr, 1);
2047 /* The receiver's list is not really interesting here since either this
2048 handle is now first in the list and we'll deal with it soon, or
2049 another handle is already first and thus is already taken care of */
2051 break; /* we're done! */
2053 curr = curr->next;
2057 static bool isHandleAtHead(struct SessionHandle *handle,
2058 struct curl_llist *pipeline)
2060 struct curl_llist_element *curr = pipeline->head;
2061 if(curr)
2062 return (bool)(curr->ptr == handle);
2064 return FALSE;
2067 /* given a number of milliseconds from now to use to set the 'act before
2068 this'-time for the transfer, to be extracted by curl_multi_timeout() */
2069 void Curl_expire(struct SessionHandle *data, long milli)
2071 struct Curl_multi *multi = data->multi;
2072 struct timeval *nowp = &data->state.expiretime;
2073 int rc;
2075 /* this is only interesting for multi-interface using libcurl, and only
2076 while there is still a multi interface struct remaining! */
2077 if(!multi)
2078 return;
2080 if(!milli) {
2081 /* No timeout, clear the time data. */
2082 if(nowp->tv_sec || nowp->tv_usec) {
2083 /* Since this is an cleared time, we must remove the previous entry from
2084 the splay tree */
2085 rc = Curl_splayremovebyaddr(multi->timetree,
2086 &data->state.timenode,
2087 &multi->timetree);
2088 if(rc)
2089 infof(data, "Internal error clearing splay node = %d\n", rc);
2090 infof(data, "Expire cleared\n");
2091 nowp->tv_sec = 0;
2092 nowp->tv_usec = 0;
2095 else {
2096 struct timeval set;
2097 int rest;
2099 set = Curl_tvnow();
2100 set.tv_sec += milli/1000;
2101 set.tv_usec += (milli%1000)*1000;
2103 rest = (int)(set.tv_usec - 1000000);
2104 if(rest > 0) {
2105 /* bigger than a full microsec */
2106 set.tv_sec++;
2107 set.tv_usec -= 1000000;
2110 if(nowp->tv_sec || nowp->tv_usec) {
2111 /* This means that the struct is added as a node in the splay tree.
2112 Compare if the new time is earlier, and only remove-old/add-new if it
2113 is. */
2114 long diff = curlx_tvdiff(set, *nowp);
2115 if(diff > 0)
2116 /* the new expire time was later so we don't change this */
2117 return;
2119 /* Since this is an updated time, we must remove the previous entry from
2120 the splay tree first and then re-add the new value */
2121 rc = Curl_splayremovebyaddr(multi->timetree,
2122 &data->state.timenode,
2123 &multi->timetree);
2124 if(rc)
2125 infof(data, "Internal error removing splay node = %d\n", rc);
2128 *nowp = set;
2129 #if 0
2130 infof(data, "Expire at %ld / %ld (%ldms) %p\n",
2131 (long)nowp->tv_sec, (long)nowp->tv_usec, milli, data);
2132 #endif
2133 data->state.timenode.payload = data;
2134 multi->timetree = Curl_splayinsert(*nowp,
2135 multi->timetree,
2136 &data->state.timenode);
2138 #if 0
2139 Curl_splayprint(multi->timetree, 0, TRUE);
2140 #endif
2143 CURLMcode curl_multi_assign(CURLM *multi_handle,
2144 curl_socket_t s, void *hashp)
2146 struct Curl_sh_entry *there = NULL;
2147 struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
2149 if(s != CURL_SOCKET_BAD)
2150 there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
2152 if(!there)
2153 return CURLM_BAD_SOCKET;
2155 there->socketp = hashp;
2157 return CURLM_OK;
2160 static bool multi_conn_using(struct Curl_multi *multi,
2161 struct SessionHandle *data)
2163 /* any live CLOSEACTION-connections pointing to the give 'data' ? */
2164 int i;
2166 for(i=0; i< multi->connc->num; i++) {
2167 if(multi->connc->connects[i] &&
2168 (multi->connc->connects[i]->data == data) &&
2169 multi->connc->connects[i]->protocol & PROT_CLOSEACTION)
2170 return TRUE;
2173 return FALSE;
2176 /* Add the given data pointer to the list of 'closure handles' that are kept
2177 around only to be able to close some connections nicely - just make sure
2178 that this handle isn't already added, like for the cases when an easy
2179 handle is removed, added and removed again... */
2180 static void add_closure(struct Curl_multi *multi,
2181 struct SessionHandle *data)
2183 int i;
2184 struct closure *cl = (struct closure *)calloc(sizeof(struct closure), 1);
2185 struct closure *p=NULL;
2186 struct closure *n;
2187 if(cl) {
2188 cl->easy_handle = data;
2189 cl->next = multi->closure;
2190 multi->closure = cl;
2193 p = multi->closure;
2194 cl = p->next; /* start immediately on the second since the first is the one
2195 we just added and it is _very_ likely to actually exist
2196 used in the cache since that's the whole purpose of adding
2197 it to this list! */
2199 /* When adding, scan through all the other currently kept handles and see if
2200 there are any connections still referring to them and kill them if not. */
2201 while(cl) {
2202 bool inuse = FALSE;
2203 for(i=0; i< multi->connc->num; i++) {
2204 if(multi->connc->connects[i] &&
2205 (multi->connc->connects[i]->data == cl->easy_handle)) {
2206 inuse = TRUE;
2207 break;
2211 n = cl->next;
2213 if(!inuse) {
2214 /* cl->easy_handle is now killable */
2215 infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle);
2216 /* unmark it as not having a connection around that uses it anymore */
2217 cl->easy_handle->state.shared_conn= NULL;
2218 Curl_close(cl->easy_handle);
2219 if(p)
2220 p->next = n;
2221 else
2222 multi->closure = n;
2223 free(cl);
2225 else
2226 p = cl;
2228 cl = n;
2233 #ifdef CURLDEBUG
2234 void curl_multi_dump(CURLM *multi_handle)
2236 struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
2237 struct Curl_one_easy *easy;
2238 int i;
2239 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
2240 multi->num_easy, multi->num_alive);
2241 for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) {
2242 if(easy->state != CURLM_STATE_COMPLETED) {
2243 /* only display handles that are not completed */
2244 fprintf(stderr, "handle %p, state %s, %d sockets\n",
2245 (void *)easy->easy_handle,
2246 statename[easy->state], easy->numsocks);
2247 for(i=0; i < easy->numsocks; i++) {
2248 curl_socket_t s = easy->sockets[i];
2249 struct Curl_sh_entry *entry =
2250 Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
2252 fprintf(stderr, "%d ", (int)s);
2253 if(!entry) {
2254 fprintf(stderr, "INTERNAL CONFUSION\n");
2255 continue;
2257 fprintf(stderr, "[%s %s] ",
2258 entry->action&CURL_POLL_IN?"RECVING":"",
2259 entry->action&CURL_POLL_OUT?"SENDING":"");
2261 if(easy->numsocks)
2262 fprintf(stderr, "\n");
2266 #endif