1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, 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 https://curl.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 ***************************************************************************/
23 #include "curl_setup.h"
25 #include <curl/curl.h>
41 #include "speedcheck.h"
42 #include "conncache.h"
43 #include "multihandle.h"
45 #include "vtls/vtls.h"
47 #include "http_proxy.h"
49 #include "socketpair.h"
51 /* The last 3 #include files should be in this order */
52 #include "curl_printf.h"
53 #include "curl_memory.h"
57 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
58 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
59 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
61 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
62 #define CURL_SOCKET_HASH_TABLE_SIZE 911
65 #ifndef CURL_CONNECTION_HASH_SIZE
66 #define CURL_CONNECTION_HASH_SIZE 97
69 #define CURL_MULTI_HANDLE 0x000bab1e
71 #define GOOD_MULTI_HANDLE(x) \
72 ((x) && (x)->magic == CURL_MULTI_HANDLE)
74 static CURLMcode singlesocket(struct Curl_multi *multi,
75 struct Curl_easy *data);
76 static CURLMcode add_next_timeout(struct curltime now,
77 struct Curl_multi *multi,
79 static CURLMcode multi_timeout(struct Curl_multi *multi,
81 static void process_pending_handles(struct Curl_multi *multi);
84 static const char * const statename[]={
105 /* function pointer called once when switching TO a state */
106 typedef void (*init_multistate_func)(struct Curl_easy *data);
108 /* called in DID state, before PERFORMING state */
109 static void before_perform(struct Curl_easy *data)
111 data->req.chunk = FALSE;
112 Curl_pgrsTime(data, TIMER_PRETRANSFER);
115 static void init_completed(struct Curl_easy *data)
117 /* this is a completed transfer */
119 /* Important: reset the conn pointer so that we don't point to memory
120 that could be freed anytime */
121 Curl_detach_connection(data);
122 Curl_expire_clear(data); /* stop all timers */
125 /* always use this function to change state, to make debugging easier */
126 static void mstate(struct Curl_easy *data, CURLMstate state
132 CURLMstate oldstate = data->mstate;
133 static const init_multistate_func finit[MSTATE_LAST] = {
136 Curl_init_CONNECT, /* CONNECT */
137 NULL, /* RESOLVING */
138 NULL, /* CONNECTING */
139 NULL, /* TUNNELING */
140 NULL, /* PROTOCONNECT */
141 NULL, /* PROTOCONNECTING */
142 Curl_connect_free, /* DO */
144 NULL, /* DOING_MORE */
145 before_perform, /* DID */
146 NULL, /* PERFORMING */
147 NULL, /* RATELIMITING */
149 init_completed, /* COMPLETED */
153 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
157 if(oldstate == state)
158 /* don't bother when the new state is the same as the old state */
161 data->mstate = state;
163 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
164 if(data->mstate >= MSTATE_PENDING &&
165 data->mstate < MSTATE_COMPLETED) {
166 long connection_id = -5000;
169 connection_id = data->conn->connection_id;
172 "STATE: %s => %s handle %p; line %d (connection #%ld)",
173 statename[oldstate], statename[data->mstate],
174 (void *)data, lineno, connection_id);
178 if(state == MSTATE_COMPLETED) {
179 /* changing to COMPLETED means there's one less easy handle 'alive' */
180 DEBUGASSERT(data->multi->num_alive > 0);
181 data->multi->num_alive--;
184 /* if this state has an init-function, run it */
190 #define multistate(x,y) mstate(x,y)
192 #define multistate(x,y) mstate(x,y, __LINE__)
196 * We add one of these structs to the sockhash for each socket
199 struct Curl_sh_entry {
200 struct Curl_hash transfers; /* hash of transfers using this socket */
201 unsigned int action; /* what combined action READ/WRITE this socket waits
203 unsigned int users; /* number of transfers using this */
204 void *socketp; /* settable by users with curl_multi_assign() */
205 unsigned int readers; /* this many transfers want to read */
206 unsigned int writers; /* this many transfers want to write */
208 /* bits for 'action' having no bits means this socket is not expecting any
213 /* look up a given socket in the socket hash, skip invalid sockets */
214 static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
217 if(s != CURL_SOCKET_BAD) {
218 /* only look for proper sockets */
219 return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
224 #define TRHASH_SIZE 13
225 static size_t trhash(void *key, size_t key_length, size_t slots_num)
227 size_t keyval = (size_t)*(struct Curl_easy **)key;
230 return (keyval % slots_num);
233 static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
238 return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2;
241 static void trhash_dtor(void *nada)
247 * The sockhash has its own separate subhash in each entry that need to be
248 * safely destroyed first.
250 static void sockhash_destroy(struct Curl_hash *h)
252 struct Curl_hash_iterator iter;
253 struct Curl_hash_element *he;
256 Curl_hash_start_iterate(h, &iter);
257 he = Curl_hash_next_element(&iter);
259 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
260 Curl_hash_destroy(&sh->transfers);
261 he = Curl_hash_next_element(&iter);
263 Curl_hash_destroy(h);
267 /* make sure this socket is present in the hash for this handle */
268 static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
271 struct Curl_sh_entry *there = sh_getentry(sh, s);
272 struct Curl_sh_entry *check;
275 /* it is present, return fine */
279 /* not present, add it */
280 check = calloc(1, sizeof(struct Curl_sh_entry));
282 return NULL; /* major failure */
284 Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
287 /* make/add new hash entry */
288 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
289 Curl_hash_destroy(&check->transfers);
291 return NULL; /* major failure */
294 return check; /* things are good in sockhash land */
298 /* delete the given socket + handle from the hash */
299 static void sh_delentry(struct Curl_sh_entry *entry,
300 struct Curl_hash *sh, curl_socket_t s)
302 Curl_hash_destroy(&entry->transfers);
304 /* We remove the hash entry. This will end up in a call to
306 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
310 * free a sockhash entry
312 static void sh_freeentry(void *freethis)
314 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
319 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
321 (void) k1_len; (void) k2_len;
323 return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
326 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
328 curl_socket_t fd = *((curl_socket_t *) key);
331 return (fd % slots_num);
335 * sh_init() creates a new socket hash and returns the handle for it.
337 * Quote from README.multi_socket:
339 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
340 * is somewhat of a bottle neck. Its current implementation may be a bit too
341 * limiting. It simply has a fixed-size array, and on each entry in the array
342 * it has a linked list with entries. So the hash only checks which list to
343 * scan through. The code I had used so for used a list with merely 7 slots
344 * (as that is what the DNS hash uses) but with 7000 connections that would
345 * make an average of 1000 nodes in each list to run through. I upped that to
346 * 97 slots (I believe a prime is suitable) and noticed a significant speed
347 * increase. I need to reconsider the hash implementation or use a rather
348 * large default value like this. At 9000 connections I was still below 10us
352 static void sh_init(struct Curl_hash *hash, int hashsize)
354 Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
361 * Called when a transfer is completed. Adds the given msg pointer to
362 * the list kept in the multi handle.
364 static CURLMcode multi_addmsg(struct Curl_multi *multi,
365 struct Curl_message *msg)
367 Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
372 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
373 int chashsize) /* connection hash */
375 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
380 multi->magic = CURL_MULTI_HANDLE;
382 Curl_init_dnscache(&multi->hostcache);
384 sh_init(&multi->sockhash, hashsize);
386 if(Curl_conncache_init(&multi->conn_cache, chashsize))
389 Curl_llist_init(&multi->msglist, NULL);
390 Curl_llist_init(&multi->pending, NULL);
392 multi->multiplexing = TRUE;
394 /* -1 means it not set by user, use the default value */
395 multi->maxconnects = -1;
396 multi->max_concurrent_streams = 100;
397 multi->ipv6_works = Curl_ipv6works(NULL);
400 multi->wsa_event = WSACreateEvent();
401 if(multi->wsa_event == WSA_INVALID_EVENT)
405 if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
406 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
407 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
409 else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
410 curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
411 sclose(multi->wakeup_pair[0]);
412 sclose(multi->wakeup_pair[1]);
413 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
414 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
423 sockhash_destroy(&multi->sockhash);
424 Curl_hash_destroy(&multi->hostcache);
425 Curl_conncache_destroy(&multi->conn_cache);
426 Curl_llist_destroy(&multi->msglist, NULL);
427 Curl_llist_destroy(&multi->pending, NULL);
433 struct Curl_multi *curl_multi_init(void)
435 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
436 CURL_CONNECTION_HASH_SIZE);
439 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
440 struct Curl_easy *data)
443 /* First, make some basic checks that the CURLM handle is a good handle */
444 if(!GOOD_MULTI_HANDLE(multi))
445 return CURLM_BAD_HANDLE;
447 /* Verify that we got a somewhat good easy handle too */
448 if(!GOOD_EASY_HANDLE(data))
449 return CURLM_BAD_EASY_HANDLE;
451 /* Prevent users from adding same easy handle more than once and prevent
452 adding to more than one multi stack */
454 return CURLM_ADDED_ALREADY;
456 if(multi->in_callback)
457 return CURLM_RECURSIVE_API_CALL;
460 /* a "dead" handle cannot get added transfers while any existing easy
461 handles are still alive - but if there are none alive anymore, it is
462 fine to start over and unmark the "deadness" of this handle */
464 return CURLM_ABORTED_BY_CALLBACK;
468 /* Initialize timeout list for this handle */
469 Curl_llist_init(&data->state.timeoutlist, NULL);
472 * No failure allowed in this function beyond this point. And no
473 * modification of easy nor multi handle allowed before this except for
474 * potential multi's connection cache growing which won't be undone in this
475 * function no matter what.
477 if(data->set.errorbuffer)
478 data->set.errorbuffer[0] = 0;
480 /* make the Curl_easy refer back to this multi handle - before Curl_expire()
484 /* Set the timeout for this handle to expire really soon so that it will
485 be taken care of even when this handle is added in the midst of operation
486 when only the curl_multi_socket() API is used. During that flow, only
487 sockets that time-out or have actions will be dealt with. Since this
488 handle has no action yet, we make sure it times out to get things to
490 Curl_expire(data, 0, EXPIRE_RUN_NOW);
492 /* A somewhat crude work-around for a little glitch in Curl_update_timer()
493 that happens if the lastcall time is set to the same time when the handle
494 is removed as when the next handle is added, as then the check in
495 Curl_update_timer() that prevents calling the application multiple times
496 with the same timer info will not trigger and then the new handle's
497 timeout will not be notified to the app.
499 The work-around is thus simply to clear the 'lastcall' variable to force
500 Curl_update_timer() to always trigger a callback to the app when a new
501 easy handle is added */
502 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
504 rc = Curl_update_timer(multi);
508 /* set the easy handle */
509 multistate(data, MSTATE_INIT);
511 /* for multi interface connections, we share DNS cache automatically if the
512 easy handle's one is currently not set. */
513 if(!data->dns.hostcache ||
514 (data->dns.hostcachetype == HCACHE_NONE)) {
515 data->dns.hostcache = &multi->hostcache;
516 data->dns.hostcachetype = HCACHE_MULTI;
519 /* Point to the shared or multi handle connection cache */
520 if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
521 data->state.conn_cache = &data->share->conn_cache;
523 data->state.conn_cache = &multi->conn_cache;
524 data->state.lastconnect_id = -1;
527 /* Do the same for PSL. */
528 if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
529 data->psl = &data->share->psl;
531 data->psl = &multi->psl;
534 /* We add the new entry last in the list. */
535 data->next = NULL; /* end of the line */
537 struct Curl_easy *last = multi->easylp;
540 multi->easylp = data; /* the new last node */
543 /* first node, make prev NULL! */
545 multi->easylp = multi->easyp = data; /* both first and last */
548 /* increase the node-counter */
551 /* increase the alive-counter */
554 CONNCACHE_LOCK(data);
555 /* The closure handle only ever has default timeouts set. To improve the
556 state somewhat we clone the timeouts from each added handle so that the
557 closure handle always has the same timeouts as the most recently added
559 data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
560 data->state.conn_cache->closure_handle->set.server_response_timeout =
561 data->set.server_response_timeout;
562 data->state.conn_cache->closure_handle->set.no_signal =
564 CONNCACHE_UNLOCK(data);
570 /* Debug-function, used like this:
572 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
574 * Enable the hash print function first by editing hash.c
576 static void debug_print_sock_hash(void *p)
578 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
580 fprintf(stderr, " [readers %u][writers %u]",
581 sh->readers, sh->writers);
585 static CURLcode multi_done(struct Curl_easy *data,
586 CURLcode status, /* an error if this is called
587 after an error was detected */
591 struct connectdata *conn = data->conn;
594 DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
595 (int)status, (int)premature, data->state.done));
598 /* Stop if multi_done() has already been called */
601 /* Stop the resolver and free its own resources (but not dns_entry yet). */
602 Curl_resolver_kill(data);
604 /* Cleanup possible redirect junk */
605 Curl_safefree(data->req.newurl);
606 Curl_safefree(data->req.location);
609 case CURLE_ABORTED_BY_CALLBACK:
610 case CURLE_READ_ERROR:
611 case CURLE_WRITE_ERROR:
612 /* When we're aborted due to a callback return code it basically have to
613 be counted as premature as there is trouble ahead if we don't. We have
614 many callbacks and protocols work differently, we could potentially do
615 this more fine-grained in the future. */
621 /* this calls the protocol-specific function pointer previously set */
622 if(conn->handler->done)
623 result = conn->handler->done(data, status, premature);
627 if(CURLE_ABORTED_BY_CALLBACK != result) {
628 /* avoid this if we already aborted by callback to avoid this calling
630 CURLcode rc = Curl_pgrsDone(data);
632 result = CURLE_ABORTED_BY_CALLBACK;
635 process_pending_handles(data->multi); /* connection / multiplex */
637 CONNCACHE_LOCK(data);
638 Curl_detach_connection(data);
639 if(CONN_INUSE(conn)) {
640 /* Stop if still used. */
641 CONNCACHE_UNLOCK(data);
642 DEBUGF(infof(data, "Connection still in use %zu, "
643 "no more multi_done now!",
648 data->state.done = TRUE; /* called just now! */
650 if(conn->dns_entry) {
651 Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
652 conn->dns_entry = NULL;
654 Curl_hostcache_prune(data);
655 Curl_safefree(data->state.ulbuf);
657 /* if the transfer was completed in a paused state there can be buffered
659 for(i = 0; i < data->state.tempcount; i++) {
660 Curl_dyn_free(&data->state.tempwrite[i].b);
662 data->state.tempcount = 0;
664 /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
665 forced us to close this connection. This is ignored for requests taking
666 place in a NTLM/NEGOTIATE authentication handshake
668 if conn->bits.close is TRUE, it means that the connection should be
669 closed in spite of all our efforts to be nice, due to protocol
670 restrictions in our or the server's end
672 if premature is TRUE, it means this connection was said to be DONE before
673 the entire request operation is complete and thus we can't know in what
674 state it is for re-using, so we're forced to close it. In a perfect world
675 we can add code that keep track of if we really must close it here or not,
676 but currently we have no such detail knowledge.
679 if((data->set.reuse_forbid
680 #if defined(USE_NTLM)
681 && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
682 conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
684 #if defined(USE_SPNEGO)
685 && !(conn->http_negotiate_state == GSS_AUTHRECV ||
686 conn->proxy_negotiate_state == GSS_AUTHRECV)
688 ) || conn->bits.close
689 || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
690 connclose(conn, "disconnecting");
691 Curl_conncache_remove_conn(data, conn, FALSE);
692 CONNCACHE_UNLOCK(data);
693 Curl_disconnect(data, conn, premature);
698 #ifndef CURL_DISABLE_PROXY
699 conn->bits.socksproxy ?
700 conn->socks_proxy.host.dispname :
701 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
703 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
705 /* create string before returning the connection */
706 long connection_id = conn->connection_id;
707 msnprintf(buffer, sizeof(buffer),
708 "Connection #%ld to host %s left intact",
709 connection_id, host);
710 /* the connection is no longer in use by this transfer */
711 CONNCACHE_UNLOCK(data);
712 if(Curl_conncache_return_conn(data, conn)) {
713 /* remember the most recently used connection */
714 data->state.lastconnect_id = connection_id;
715 infof(data, "%s", buffer);
718 data->state.lastconnect_id = -1;
721 Curl_safefree(data->state.buffer);
725 static int close_connect_only(struct Curl_easy *data,
726 struct connectdata *conn, void *param)
729 if(data->state.lastconnect_id != conn->connection_id)
732 if(!conn->bits.connect_only)
735 connclose(conn, "Removing connect-only easy handle");
740 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
741 struct Curl_easy *data)
743 struct Curl_easy *easy = data;
745 struct Curl_llist_element *e;
748 /* First, make some basic checks that the CURLM handle is a good handle */
749 if(!GOOD_MULTI_HANDLE(multi))
750 return CURLM_BAD_HANDLE;
752 /* Verify that we got a somewhat good easy handle too */
753 if(!GOOD_EASY_HANDLE(data))
754 return CURLM_BAD_EASY_HANDLE;
756 /* Prevent users from trying to remove same easy handle more than once */
758 return CURLM_OK; /* it is already removed so let's say it is fine! */
760 /* Prevent users from trying to remove an easy handle from the wrong multi */
761 if(data->multi != multi)
762 return CURLM_BAD_EASY_HANDLE;
764 if(multi->in_callback)
765 return CURLM_RECURSIVE_API_CALL;
767 premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE;
769 /* If the 'state' is not INIT or COMPLETED, we might need to do something
770 nice to put the easy_handle in a good known state when this returns. */
772 /* this handle is "alive" so we need to count down the total number of
773 alive connections when this is removed */
778 data->mstate > MSTATE_DO &&
779 data->mstate < MSTATE_COMPLETED) {
780 /* Set connection owner so that the DONE function closes it. We can
781 safely do this here since connection is killed. */
782 streamclose(data->conn, "Removed with partial response");
786 /* multi_done() clears the association between the easy handle and the
789 Note that this ignores the return code simply because there's
790 nothing really useful to do with it anyway! */
791 (void)multi_done(data, data->result, premature);
794 /* The timer must be shut down before data->multi is set to NULL, else the
795 timenode will remain in the splay tree after curl_easy_cleanup is
796 called. Do it after multi_done() in case that sets another time! */
797 Curl_expire_clear(data);
799 if(data->connect_queue.ptr)
800 /* the handle was in the pending list waiting for an available connection,
801 so go ahead and remove it */
802 Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
804 if(data->dns.hostcachetype == HCACHE_MULTI) {
805 /* stop using the multi handle's DNS cache, *after* the possible
806 multi_done() call above */
807 data->dns.hostcache = NULL;
808 data->dns.hostcachetype = HCACHE_NONE;
811 Curl_wildcard_dtor(&data->wildcard);
813 /* destroy the timeout list that is held in the easy handle, do this *after*
814 multi_done() as that may actually call Curl_expire that uses this */
815 Curl_llist_destroy(&data->state.timeoutlist, NULL);
817 /* change state without using multistate(), only to make singlesocket() do
819 data->mstate = MSTATE_COMPLETED;
821 /* This ignores the return code even in case of problems because there's
822 nothing more to do about that, here */
823 (void)singlesocket(multi, easy); /* to let the application know what sockets
824 that vanish with this handle */
826 /* Remove the association between the connection and the handle */
827 Curl_detach_connection(data);
829 if(data->state.lastconnect_id != -1) {
830 /* Mark any connect-only connection for closure */
831 Curl_conncache_foreach(data, data->state.conn_cache,
832 NULL, close_connect_only);
836 /* Remove the PSL association. */
837 if(data->psl == &multi->psl)
841 /* as this was using a shared connection cache we clear the pointer to that
842 since we're not part of that multi handle anymore */
843 data->state.conn_cache = NULL;
845 data->multi = NULL; /* clear the association to this multi handle */
847 /* make sure there's no pending message in the queue sent from this easy
850 for(e = multi->msglist.head; e; e = e->next) {
851 struct Curl_message *msg = e->ptr;
853 if(msg->extmsg.easy_handle == easy) {
854 Curl_llist_remove(&multi->msglist, e, NULL);
855 /* there can only be one from this specific handle */
860 /* Remove from the pending list if it is there. Otherwise this will
861 remain on the pending list forever due to the state change. */
862 for(e = multi->pending.head; e; e = e->next) {
863 struct Curl_easy *curr_data = e->ptr;
865 if(curr_data == data) {
866 Curl_llist_remove(&multi->pending, e, NULL);
871 /* make the previous node point to our next */
873 data->prev->next = data->next;
875 multi->easyp = data->next; /* point to first node */
877 /* make our next point to our previous node */
879 data->next->prev = data->prev;
881 multi->easylp = data->prev; /* point to last node */
884 We do not touch the easy handle here! */
885 multi->num_easy--; /* one less to care about now */
887 process_pending_handles(multi);
889 rc = Curl_update_timer(multi);
895 /* Return TRUE if the application asked for multiplexing */
896 bool Curl_multiplex_wanted(const struct Curl_multi *multi)
898 return (multi && (multi->multiplexing));
902 * Curl_detach_connection() removes the given transfer from the connection.
904 * This is the only function that should clear data->conn. This will
905 * occasionally be called with the data->conn pointer already cleared.
907 void Curl_detach_connection(struct Curl_easy *data)
909 struct connectdata *conn = data->conn;
911 Curl_connect_done(data); /* if mid-CONNECT, shut it down */
912 Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
913 Curl_ssl_detach_conn(data, conn);
919 * Curl_attach_connection() attaches this transfer to this connection.
921 * This is the only function that should assign data->conn
923 void Curl_attach_connection(struct Curl_easy *data,
924 struct connectdata *conn)
926 DEBUGASSERT(!data->conn);
929 Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
931 if(conn->handler->attach)
932 conn->handler->attach(data, conn);
933 Curl_ssl_associate_conn(data, conn);
936 static int waitconnect_getsock(struct connectdata *conn,
944 #ifndef CURL_DISABLE_PROXY
945 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
946 return Curl_ssl->getsock(conn, sock);
950 if(SOCKS_STATE(conn->cnnct.state))
951 return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
953 for(i = 0; i<2; i++) {
954 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
955 sock[s] = conn->tempsock[i];
956 rc |= GETSOCK_WRITESOCK(s);
958 if(conn->transport == TRNSPRT_QUIC)
959 /* when connecting QUIC, we want to read the socket too */
960 rc |= GETSOCK_READSOCK(s);
969 static int waitproxyconnect_getsock(struct connectdata *conn,
972 sock[0] = conn->sock[FIRSTSOCKET];
974 if(conn->connect_state)
975 return Curl_connect_getsock(conn);
977 return GETSOCK_WRITESOCK(0);
980 static int domore_getsock(struct Curl_easy *data,
981 struct connectdata *conn,
982 curl_socket_t *socks)
984 if(conn && conn->handler->domore_getsock)
985 return conn->handler->domore_getsock(data, conn, socks);
986 return GETSOCK_BLANK;
989 static int doing_getsock(struct Curl_easy *data,
990 struct connectdata *conn,
991 curl_socket_t *socks)
993 if(conn && conn->handler->doing_getsock)
994 return conn->handler->doing_getsock(data, conn, socks);
995 return GETSOCK_BLANK;
998 static int protocol_getsock(struct Curl_easy *data,
999 struct connectdata *conn,
1000 curl_socket_t *socks)
1002 if(conn->handler->proto_getsock)
1003 return conn->handler->proto_getsock(data, conn, socks);
1004 /* Backup getsock logic. Since there is a live socket in use, we must wait
1005 for it or it will be removed from watching when the multi_socket API is
1007 socks[0] = conn->sock[FIRSTSOCKET];
1008 return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
1011 /* returns bitmapped flags for this handle and its sockets. The 'socks[]'
1012 array contains MAX_SOCKSPEREASYHANDLE entries. */
1013 static int multi_getsock(struct Curl_easy *data,
1014 curl_socket_t *socks)
1016 struct connectdata *conn = data->conn;
1017 /* The no connection case can happen when this is called from
1018 curl_multi_remove_handle() => singlesocket() => multi_getsock().
1023 switch(data->mstate) {
1027 case MSTATE_RESOLVING:
1028 return Curl_resolv_getsock(data, socks);
1030 case MSTATE_PROTOCONNECTING:
1031 case MSTATE_PROTOCONNECT:
1032 return protocol_getsock(data, conn, socks);
1036 return doing_getsock(data, conn, socks);
1038 case MSTATE_TUNNELING:
1039 return waitproxyconnect_getsock(conn, socks);
1041 case MSTATE_CONNECTING:
1042 return waitconnect_getsock(conn, socks);
1044 case MSTATE_DOING_MORE:
1045 return domore_getsock(data, conn, socks);
1047 case MSTATE_DID: /* since is set after DO is completed, we switch to
1048 waiting for the same as the PERFORMING state */
1049 case MSTATE_PERFORMING:
1050 return Curl_single_getsock(data, conn, socks);
1055 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
1056 fd_set *read_fd_set, fd_set *write_fd_set,
1057 fd_set *exc_fd_set, int *max_fd)
1059 /* Scan through all the easy handles to get the file descriptors set.
1060 Some easy handles may not have connected to the remote host yet,
1061 and then we must make sure that is done. */
1062 struct Curl_easy *data;
1063 int this_max_fd = -1;
1064 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1066 (void)exc_fd_set; /* not used */
1068 if(!GOOD_MULTI_HANDLE(multi))
1069 return CURLM_BAD_HANDLE;
1071 if(multi->in_callback)
1072 return CURLM_RECURSIVE_API_CALL;
1074 data = multi->easyp;
1077 #ifdef __clang_analyzer_
1078 /* to prevent "The left operand of '>=' is a garbage value" warnings */
1079 memset(sockbunch, 0, sizeof(sockbunch));
1081 bitmap = multi_getsock(data, sockbunch);
1083 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1084 curl_socket_t s = CURL_SOCKET_BAD;
1086 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
1087 if(!FDSET_SOCK(sockbunch[i]))
1088 /* pretend it doesn't exist */
1090 FD_SET(sockbunch[i], read_fd_set);
1093 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
1094 if(!FDSET_SOCK(sockbunch[i]))
1095 /* pretend it doesn't exist */
1097 FD_SET(sockbunch[i], write_fd_set);
1100 if(s == CURL_SOCKET_BAD)
1101 /* this socket is unused, break out of loop */
1103 if((int)s > this_max_fd)
1104 this_max_fd = (int)s;
1107 data = data->next; /* check next handle */
1110 *max_fd = this_max_fd;
1115 #define NUM_POLLS_ON_STACK 10
1117 static CURLMcode multi_wait(struct Curl_multi *multi,
1118 struct curl_waitfd extra_fds[],
1119 unsigned int extra_nfds,
1122 bool extrawait, /* when no socket, wait */
1125 struct Curl_easy *data;
1126 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1129 unsigned int nfds = 0;
1130 unsigned int curlfds;
1131 long timeout_internal;
1133 struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1134 struct pollfd *ufds = &a_few_on_stack[0];
1135 bool ufds_malloc = FALSE;
1137 WSANETWORKEVENTS wsa_events;
1138 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1140 #ifndef ENABLE_WAKEUP
1144 if(!GOOD_MULTI_HANDLE(multi))
1145 return CURLM_BAD_HANDLE;
1147 if(multi->in_callback)
1148 return CURLM_RECURSIVE_API_CALL;
1151 return CURLM_BAD_FUNCTION_ARGUMENT;
1153 /* Count up how many fds we have from the multi handle */
1154 data = multi->easyp;
1156 bitmap = multi_getsock(data, sockbunch);
1158 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1159 curl_socket_t s = CURL_SOCKET_BAD;
1161 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1165 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1169 if(s == CURL_SOCKET_BAD) {
1174 data = data->next; /* check next handle */
1177 /* If the internally desired timeout is actually shorter than requested from
1178 the outside, then use the shorter time! But only if the internal timer
1179 is actually larger than -1! */
1180 (void)multi_timeout(multi, &timeout_internal);
1181 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1182 timeout_ms = (int)timeout_internal;
1184 curlfds = nfds; /* number of internal file descriptors */
1185 nfds += extra_nfds; /* add the externally provided ones */
1187 #ifdef ENABLE_WAKEUP
1191 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1197 if(nfds > NUM_POLLS_ON_STACK) {
1198 /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1199 big, so at 2^29 sockets this value might wrap. When a process gets
1200 the capability to actually handle over 500 million sockets this
1201 calculation needs a integer overflow check. */
1202 ufds = malloc(nfds * sizeof(struct pollfd));
1204 return CURLM_OUT_OF_MEMORY;
1209 /* only do the second loop if we found descriptors in the first stage run
1213 /* Add the curl handles to our pollfds first */
1214 data = multi->easyp;
1216 bitmap = multi_getsock(data, sockbunch);
1218 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1219 curl_socket_t s = CURL_SOCKET_BAD;
1223 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1226 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1229 ufds[nfds].events = POLLIN;
1232 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1235 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1236 send(s, NULL, 0, 0); /* reset FD_WRITE */
1239 ufds[nfds].events = POLLOUT;
1242 /* s is only set if either being readable or writable is checked */
1243 if(s == CURL_SOCKET_BAD) {
1244 /* break on entry not checked for being readable or writable */
1248 if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
1251 return CURLM_INTERNAL_ERROR;
1256 data = data->next; /* check next handle */
1260 /* Add external file descriptions from poll-like struct curl_waitfd */
1261 for(i = 0; i < extra_nfds; i++) {
1264 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1265 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1266 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1268 if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1269 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1270 send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
1272 if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1275 return CURLM_INTERNAL_ERROR;
1278 ufds[nfds].fd = extra_fds[i].fd;
1279 ufds[nfds].events = 0;
1280 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1281 ufds[nfds].events |= POLLIN;
1282 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1283 ufds[nfds].events |= POLLPRI;
1284 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1285 ufds[nfds].events |= POLLOUT;
1289 #ifdef ENABLE_WAKEUP
1291 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1292 ufds[nfds].fd = multi->wakeup_pair[0];
1293 ufds[nfds].events = POLLIN;
1299 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1300 if(nfds || use_wakeup) {
1307 pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1310 if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
1311 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1313 pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1320 /* With WinSock, we have to run the following section unconditionally
1321 to call WSAEventSelect(fd, event, 0) on all the sockets */
1324 /* copy revents results from the poll to the curl_multi_wait poll
1325 struct, the bit values of the actual underlying poll() implementation
1326 may not be the same as the ones in the public libcurl API! */
1327 for(i = 0; i < extra_nfds; i++) {
1328 unsigned r = ufds[curlfds + i].revents;
1329 unsigned short mask = 0;
1331 wsa_events.lNetworkEvents = 0;
1332 if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
1333 if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1334 mask |= CURL_WAIT_POLLIN;
1335 if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1336 mask |= CURL_WAIT_POLLOUT;
1337 if(wsa_events.lNetworkEvents & FD_OOB)
1338 mask |= CURL_WAIT_POLLPRI;
1339 if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1342 WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
1347 mask |= CURL_WAIT_POLLIN;
1349 mask |= CURL_WAIT_POLLOUT;
1351 mask |= CURL_WAIT_POLLPRI;
1352 extra_fds[i].revents = mask;
1356 /* Count up all our own sockets that had activity,
1357 and remove them from the event. */
1359 data = multi->easyp;
1361 bitmap = multi_getsock(data, sockbunch);
1363 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1364 if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
1365 wsa_events.lNetworkEvents = 0;
1366 if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
1367 if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1370 WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1373 /* break on entry not checked for being readable or writable */
1382 WSAResetEvent(multi->wsa_event);
1384 #ifdef ENABLE_WAKEUP
1385 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1386 if(ufds[curlfds + extra_nfds].revents & POLLIN) {
1390 /* the reading socket is non-blocking, try to read
1391 data from it until it receives an error (except EINTR).
1392 In normal cases it will get EAGAIN or EWOULDBLOCK
1393 when there is no more data, breaking the loop. */
1394 nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
1396 if(nread < 0 && EINTR == SOCKERRNO)
1401 /* do not count the wakeup socket into the returned value */
1414 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1415 if(extrawait && !nfds && !use_wakeup) {
1417 if(extrawait && !nfds) {
1421 /* Avoid busy-looping when there's nothing particular to wait for */
1422 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1423 if(sleep_ms > timeout_ms)
1424 sleep_ms = timeout_ms;
1425 /* when there are no easy handles in the multi, this holds a -1
1427 else if(sleep_ms < 0)
1428 sleep_ms = timeout_ms;
1429 Curl_wait_ms(sleep_ms);
1436 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1437 struct curl_waitfd extra_fds[],
1438 unsigned int extra_nfds,
1442 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1446 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1447 struct curl_waitfd extra_fds[],
1448 unsigned int extra_nfds,
1452 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1456 CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1458 /* this function is usually called from another thread,
1459 it has to be careful only to access parts of the
1460 Curl_multi struct that are constant */
1462 /* GOOD_MULTI_HANDLE can be safely called */
1463 if(!GOOD_MULTI_HANDLE(multi))
1464 return CURLM_BAD_HANDLE;
1466 #ifdef ENABLE_WAKEUP
1468 if(WSASetEvent(multi->wsa_event))
1471 /* the wakeup_pair variable is only written during init and cleanup,
1472 making it safe to access from another thread after the init part
1473 and before cleanup */
1474 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1478 /* swrite() is not thread-safe in general, because concurrent calls
1479 can have their messages interleaved, but in this case the content
1480 of the messages does not matter, which makes it ok to call.
1482 The write socket is set to non-blocking, this way this function
1483 cannot block, making it safe to call even from the same thread
1484 that will call curl_multi_wait(). If swrite() returns that it
1485 would block, it's considered successful because it means that
1486 previous calls to this function will wake up the poll(). */
1487 if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1488 int err = SOCKERRNO;
1491 return_success = WSAEWOULDBLOCK == err;
1495 return_success = EWOULDBLOCK == err || EAGAIN == err;
1498 return CURLM_WAKEUP_FAILURE;
1505 return CURLM_WAKEUP_FAILURE;
1509 * multi_ischanged() is called
1511 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1512 * => CONNECT action.
1514 * Set 'clear' to TRUE to have it also clear the state variable.
1516 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1518 bool retval = multi->recheckstate;
1520 multi->recheckstate = FALSE;
1524 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1525 struct Curl_easy *data,
1526 struct connectdata *conn)
1530 if(multi->in_callback)
1531 return CURLM_RECURSIVE_API_CALL;
1533 rc = curl_multi_add_handle(multi, data);
1535 struct SingleRequest *k = &data->req;
1537 /* pass in NULL for 'conn' here since we don't want to init the
1538 connection, only this transfer */
1539 Curl_init_do(data, NULL);
1541 /* take this handle to the perform state right away */
1542 multistate(data, MSTATE_PERFORMING);
1543 Curl_attach_connection(data, conn);
1544 k->keepon |= KEEP_RECV; /* setup to receive! */
1549 static CURLcode multi_do(struct Curl_easy *data, bool *done)
1551 CURLcode result = CURLE_OK;
1552 struct connectdata *conn = data->conn;
1555 DEBUGASSERT(conn->handler);
1557 if(conn->handler->do_it)
1558 /* generic protocol-specific function pointer set in curl_connect() */
1559 result = conn->handler->do_it(data, done);
1565 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1566 * second stage DO state which (wrongly) was introduced to support FTP's
1567 * second connection.
1569 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1570 * DOING state there's more work to do!
1573 static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1575 CURLcode result = CURLE_OK;
1576 struct connectdata *conn = data->conn;
1580 if(conn->handler->do_more)
1581 result = conn->handler->do_more(data, complete);
1587 * Check whether a timeout occurred, and handle it if it did
1589 static bool multi_handle_timeout(struct Curl_easy *data,
1590 struct curltime *now,
1593 bool connect_timeout)
1595 timediff_t timeout_ms;
1596 timeout_ms = Curl_timeleft(data, now, connect_timeout);
1598 if(timeout_ms < 0) {
1599 /* Handle timed out */
1600 if(data->mstate == MSTATE_RESOLVING)
1601 failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1603 Curl_timediff(*now, data->progress.t_startsingle));
1604 else if(data->mstate == MSTATE_CONNECTING)
1605 failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1607 Curl_timediff(*now, data->progress.t_startsingle));
1609 struct SingleRequest *k = &data->req;
1611 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1612 " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1613 CURL_FORMAT_CURL_OFF_T " bytes received",
1614 Curl_timediff(*now, data->progress.t_startsingle),
1615 k->bytecount, k->size);
1618 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1619 " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1621 Curl_timediff(*now, data->progress.t_startsingle),
1626 /* Force connection closed if the connection has indeed been used */
1627 if(data->mstate > MSTATE_DO) {
1628 streamclose(data->conn, "Disconnected with pending data");
1629 *stream_error = TRUE;
1631 *result = CURLE_OPERATION_TIMEDOUT;
1632 (void)multi_done(data, *result, TRUE);
1635 return (timeout_ms < 0);
1639 * We are doing protocol-specific connecting and this is being called over and
1640 * over from the multi interface until the connection phase is done on
1644 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1646 CURLcode result = CURLE_OK;
1647 struct connectdata *conn = data->conn;
1649 if(conn && conn->handler->connecting) {
1651 result = conn->handler->connecting(data, done);
1660 * We are DOING this is being called over and over from the multi interface
1661 * until the DOING phase is done on protocol layer.
1664 static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1666 CURLcode result = CURLE_OK;
1667 struct connectdata *conn = data->conn;
1669 if(conn && conn->handler->doing) {
1671 result = conn->handler->doing(data, done);
1680 * We have discovered that the TCP connection has been successful, we can now
1681 * proceed with some action.
1684 static CURLcode protocol_connect(struct Curl_easy *data,
1685 bool *protocol_done)
1687 CURLcode result = CURLE_OK;
1688 struct connectdata *conn = data->conn;
1690 DEBUGASSERT(protocol_done);
1692 *protocol_done = FALSE;
1694 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1695 /* We already are connected, get back. This may happen when the connect
1696 worked fine in the first call, like when we connect to a local server
1697 or proxy. Note that we don't know if the protocol is actually done.
1699 Unless this protocol doesn't have any protocol-connect callback, as
1700 then we know we're done. */
1701 if(!conn->handler->connecting)
1702 *protocol_done = TRUE;
1707 if(!conn->bits.protoconnstart) {
1708 #ifndef CURL_DISABLE_PROXY
1709 result = Curl_proxy_connect(data, FIRSTSOCKET);
1713 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1714 /* wait for HTTPS proxy SSL initialization to complete */
1717 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1718 Curl_connect_ongoing(conn))
1719 /* when using an HTTP tunnel proxy, await complete tunnel establishment
1720 before proceeding further. Return CURLE_OK so we'll be called again */
1723 if(conn->handler->connect_it) {
1724 /* is there a protocol-specific connect() procedure? */
1726 /* Call the protocol-specific connect function */
1727 result = conn->handler->connect_it(data, protocol_done);
1730 *protocol_done = TRUE;
1732 /* it has started, possibly even completed but that knowledge isn't stored
1735 conn->bits.protoconnstart = TRUE;
1738 return result; /* pass back status */
1742 * Curl_preconnect() is called immediately before a connect starts. When a
1743 * redirect is followed, this is then called multiple times during a single
1746 CURLcode Curl_preconnect(struct Curl_easy *data)
1748 if(!data->state.buffer) {
1749 data->state.buffer = malloc(data->set.buffer_size + 1);
1750 if(!data->state.buffer)
1751 return CURLE_OUT_OF_MEMORY;
1756 static void set_in_callback(struct Curl_multi *multi, bool value)
1758 multi->in_callback = value;
1761 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1762 struct curltime *nowp,
1763 struct Curl_easy *data)
1765 struct Curl_message *msg = NULL;
1768 bool protocol_connected = FALSE;
1769 bool dophase_done = FALSE;
1772 CURLcode result = CURLE_OK;
1773 timediff_t recv_timeout_ms;
1774 timediff_t send_timeout_ms;
1777 if(!GOOD_EASY_HANDLE(data))
1778 return CURLM_BAD_EASY_HANDLE;
1781 /* a multi-level callback returned error before, meaning every individual
1782 transfer now has failed */
1783 result = CURLE_ABORTED_BY_CALLBACK;
1784 Curl_posttransfer(data);
1785 multi_done(data, result, FALSE);
1786 multistate(data, MSTATE_COMPLETED);
1790 /* A "stream" here is a logical stream if the protocol can handle that
1791 (HTTP/2), or the full connection for older protocols */
1792 bool stream_error = FALSE;
1795 if(multi_ischanged(multi, TRUE)) {
1796 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
1797 process_pending_handles(multi); /* multiplexed */
1800 if(data->mstate > MSTATE_CONNECT &&
1801 data->mstate < MSTATE_COMPLETED) {
1802 /* Make sure we set the connection's current owner */
1803 DEBUGASSERT(data->conn);
1805 return CURLM_INTERNAL_ERROR;
1809 (data->mstate >= MSTATE_CONNECT) &&
1810 (data->mstate < MSTATE_COMPLETED)) {
1811 /* Check for overall operation timeout here but defer handling the
1812 * connection timeout to later, to allow for a connection to be set up
1813 * in the window since we last checked timeout. This prevents us
1814 * tearing down a completed connection in the case where we were slow
1815 * to check the timeout (e.g. process descheduled during this loop).
1816 * We set connect_timeout=FALSE to do this. */
1818 /* we need to wait for the connect state as only then is the start time
1819 stored, but we must not check already completed handles */
1820 if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
1821 /* Skip the statemachine and go directly to error handling section. */
1822 goto statemachine_end;
1826 switch(data->mstate) {
1828 /* init this transfer. */
1829 result = Curl_pretransfer(data);
1832 /* after init, go CONNECT */
1833 multistate(data, MSTATE_CONNECT);
1834 *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
1835 rc = CURLM_CALL_MULTI_PERFORM;
1839 case MSTATE_PENDING:
1840 /* We will stay here until there is a connection available. Then
1841 we try again in the MSTATE_CONNECT state. */
1844 case MSTATE_CONNECT:
1845 /* Connect. We want to get a connection identifier filled in. */
1846 /* init this transfer. */
1847 result = Curl_preconnect(data);
1851 *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1852 if(data->set.timeout)
1853 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1855 if(data->set.connecttimeout)
1856 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1858 result = Curl_connect(data, &async, &protocol_connected);
1859 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1860 /* There was no connection available. We will go to the pending
1861 state and wait for an available connection. */
1862 multistate(data, MSTATE_PENDING);
1864 /* add this handle to the list of connect-pending handles */
1865 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1866 &data->connect_queue);
1870 else if(data->state.previouslypending) {
1871 /* this transfer comes from the pending queue so try move another */
1872 infof(data, "Transfer was pending, now try another");
1873 process_pending_handles(data->multi);
1878 /* We're now waiting for an asynchronous name lookup */
1879 multistate(data, MSTATE_RESOLVING);
1881 /* after the connect has been sent off, go WAITCONNECT unless the
1882 protocol connect is already done and we can go directly to
1884 rc = CURLM_CALL_MULTI_PERFORM;
1886 if(protocol_connected)
1887 multistate(data, MSTATE_DO);
1889 #ifndef CURL_DISABLE_HTTP
1890 if(Curl_connect_ongoing(data->conn))
1891 multistate(data, MSTATE_TUNNELING);
1894 multistate(data, MSTATE_CONNECTING);
1900 case MSTATE_RESOLVING:
1901 /* awaiting an asynch name resolve to complete */
1903 struct Curl_dns_entry *dns = NULL;
1904 struct connectdata *conn = data->conn;
1905 const char *hostname;
1908 #ifndef CURL_DISABLE_PROXY
1909 if(conn->bits.httpproxy)
1910 hostname = conn->http_proxy.host.name;
1913 if(conn->bits.conn_to_host)
1914 hostname = conn->conn_to_host.name;
1916 hostname = conn->host.name;
1918 /* check if we have the name resolved by now */
1919 dns = Curl_fetch_addr(data, hostname, (int)conn->port);
1922 #ifdef CURLRES_ASYNCH
1923 data->state.async.dns = dns;
1924 data->state.async.done = TRUE;
1927 infof(data, "Hostname '%s' was found in DNS cache", hostname);
1931 result = Curl_resolv_check(data, &dns);
1933 /* Update sockets here, because the socket(s) may have been
1934 closed and the application thus needs to be told, even if it
1935 is likely that the same socket(s) will again be used further
1936 down. If the name has not yet been resolved, it is likely
1937 that new sockets have been opened in an attempt to contact
1938 another resolver. */
1939 rc = singlesocket(multi, data);
1944 /* Perform the next step in the connection phase, and then move on
1945 to the WAITCONNECT state */
1946 result = Curl_once_resolved(data, &protocol_connected);
1949 /* if Curl_once_resolved() returns failure, the connection struct
1950 is already freed and gone */
1951 data->conn = NULL; /* no more connection */
1953 /* call again please so that we get the next socket setup */
1954 rc = CURLM_CALL_MULTI_PERFORM;
1955 if(protocol_connected)
1956 multistate(data, MSTATE_DO);
1958 #ifndef CURL_DISABLE_HTTP
1959 if(Curl_connect_ongoing(data->conn))
1960 multistate(data, MSTATE_TUNNELING);
1963 multistate(data, MSTATE_CONNECTING);
1969 /* failure detected */
1970 stream_error = TRUE;
1976 #ifndef CURL_DISABLE_HTTP
1977 case MSTATE_TUNNELING:
1978 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1979 DEBUGASSERT(data->conn);
1980 result = Curl_http_connect(data, &protocol_connected);
1981 #ifndef CURL_DISABLE_PROXY
1982 if(data->conn->bits.proxy_connect_closed) {
1983 rc = CURLM_CALL_MULTI_PERFORM;
1984 /* connect back to proxy again */
1986 multi_done(data, CURLE_OK, FALSE);
1987 multistate(data, MSTATE_CONNECT);
1993 #ifndef CURL_DISABLE_PROXY
1994 (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
1995 data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
1997 Curl_connect_complete(data->conn)) {
1998 rc = CURLM_CALL_MULTI_PERFORM;
1999 /* initiate protocol connect phase */
2000 multistate(data, MSTATE_PROTOCONNECT);
2004 stream_error = TRUE;
2008 case MSTATE_CONNECTING:
2009 /* awaiting a completion of an asynch TCP connect */
2010 DEBUGASSERT(data->conn);
2011 result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
2012 if(connected && !result) {
2013 #ifndef CURL_DISABLE_HTTP
2015 #ifndef CURL_DISABLE_PROXY
2016 (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
2017 !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
2019 Curl_connect_ongoing(data->conn)) {
2020 multistate(data, MSTATE_TUNNELING);
2024 rc = CURLM_CALL_MULTI_PERFORM;
2025 #ifndef CURL_DISABLE_PROXY
2027 data->conn->bits.tunnel_proxy?
2028 MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
2030 multistate(data, MSTATE_PROTOCONNECT);
2034 /* failure detected */
2035 Curl_posttransfer(data);
2036 multi_done(data, result, TRUE);
2037 stream_error = TRUE;
2042 case MSTATE_PROTOCONNECT:
2043 result = protocol_connect(data, &protocol_connected);
2044 if(!result && !protocol_connected)
2045 /* switch to waiting state */
2046 multistate(data, MSTATE_PROTOCONNECTING);
2048 /* protocol connect has completed, go WAITDO or DO */
2049 multistate(data, MSTATE_DO);
2050 rc = CURLM_CALL_MULTI_PERFORM;
2053 /* failure detected */
2054 Curl_posttransfer(data);
2055 multi_done(data, result, TRUE);
2056 stream_error = TRUE;
2060 case MSTATE_PROTOCONNECTING:
2061 /* protocol-specific connect phase */
2062 result = protocol_connecting(data, &protocol_connected);
2063 if(!result && protocol_connected) {
2064 /* after the connect has completed, go WAITDO or DO */
2065 multistate(data, MSTATE_DO);
2066 rc = CURLM_CALL_MULTI_PERFORM;
2069 /* failure detected */
2070 Curl_posttransfer(data);
2071 multi_done(data, result, TRUE);
2072 stream_error = TRUE;
2077 if(data->set.fprereq) {
2080 /* call the prerequest callback function */
2081 Curl_set_in_callback(data, true);
2082 prereq_rc = data->set.fprereq(data->set.prereq_userp,
2083 data->info.conn_primary_ip,
2084 data->info.conn_local_ip,
2085 data->info.conn_primary_port,
2086 data->info.conn_local_port);
2087 Curl_set_in_callback(data, false);
2088 if(prereq_rc != CURL_PREREQFUNC_OK) {
2089 failf(data, "operation aborted by pre-request callback");
2090 /* failure in pre-request callback - don't do any other processing */
2091 result = CURLE_ABORTED_BY_CALLBACK;
2092 Curl_posttransfer(data);
2093 multi_done(data, result, FALSE);
2094 stream_error = TRUE;
2099 if(data->set.connect_only) {
2100 /* keep connection open for application to use the socket */
2101 connkeep(data->conn, "CONNECT_ONLY");
2102 multistate(data, MSTATE_DONE);
2104 rc = CURLM_CALL_MULTI_PERFORM;
2107 /* Perform the protocol's DO action */
2108 result = multi_do(data, &dophase_done);
2110 /* When multi_do() returns failure, data->conn might be NULL! */
2114 #ifndef CURL_DISABLE_FTP
2115 /* some steps needed for wildcard matching */
2116 if(data->state.wildcardmatch) {
2117 struct WildcardData *wc = &data->wildcard;
2118 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2119 /* skip some states if it is important */
2120 multi_done(data, CURLE_OK, FALSE);
2122 /* if there's no connection left, skip the DONE state */
2123 multistate(data, data->conn ?
2124 MSTATE_DONE : MSTATE_COMPLETED);
2125 rc = CURLM_CALL_MULTI_PERFORM;
2130 /* DO was not completed in one function call, we must continue
2132 multistate(data, MSTATE_DOING);
2136 /* after DO, go DO_DONE... or DO_MORE */
2137 else if(data->conn->bits.do_more) {
2138 /* we're supposed to do more, but we need to sit down, relax
2139 and wait a little while first */
2140 multistate(data, MSTATE_DOING_MORE);
2144 /* we're done with the DO, now DID */
2145 multistate(data, MSTATE_DID);
2146 rc = CURLM_CALL_MULTI_PERFORM;
2149 else if((CURLE_SEND_ERROR == result) &&
2150 data->conn->bits.reuse) {
2152 * In this situation, a connection that we were trying to use
2153 * may have unexpectedly died. If possible, send the connection
2154 * back to the CONNECT phase so we can try again.
2156 char *newurl = NULL;
2157 followtype follow = FOLLOW_NONE;
2160 drc = Curl_retry_request(data, &newurl);
2162 /* a failure here pretty much implies an out of memory */
2164 stream_error = TRUE;
2167 Curl_posttransfer(data);
2168 drc = multi_done(data, result, FALSE);
2170 /* When set to retry the connection, we must go back to the CONNECT
2173 if(!drc || (drc == CURLE_SEND_ERROR)) {
2174 follow = FOLLOW_RETRY;
2175 drc = Curl_follow(data, newurl, follow);
2177 multistate(data, MSTATE_CONNECT);
2178 rc = CURLM_CALL_MULTI_PERFORM;
2187 /* done didn't return OK or SEND_ERROR */
2192 /* Have error handler disconnect conn if we can't retry */
2193 stream_error = TRUE;
2198 /* failure detected */
2199 Curl_posttransfer(data);
2201 multi_done(data, result, FALSE);
2202 stream_error = TRUE;
2208 /* we continue DOING until the DO phase is complete */
2209 DEBUGASSERT(data->conn);
2210 result = protocol_doing(data, &dophase_done);
2213 /* after DO, go DO_DONE or DO_MORE */
2214 multistate(data, data->conn->bits.do_more?
2215 MSTATE_DOING_MORE : MSTATE_DID);
2216 rc = CURLM_CALL_MULTI_PERFORM;
2217 } /* dophase_done */
2220 /* failure detected */
2221 Curl_posttransfer(data);
2222 multi_done(data, result, FALSE);
2223 stream_error = TRUE;
2227 case MSTATE_DOING_MORE:
2229 * When we are connected, DOING MORE and then go DID
2231 DEBUGASSERT(data->conn);
2232 result = multi_do_more(data, &control);
2236 /* if positive, advance to DO_DONE
2237 if negative, go back to DOING */
2238 multistate(data, control == 1?
2239 MSTATE_DID : MSTATE_DOING);
2240 rc = CURLM_CALL_MULTI_PERFORM;
2243 /* stay in DO_MORE */
2247 /* failure detected */
2248 Curl_posttransfer(data);
2249 multi_done(data, result, FALSE);
2250 stream_error = TRUE;
2255 DEBUGASSERT(data->conn);
2256 if(data->conn->bits.multiplex)
2257 /* Check if we can move pending requests to send pipe */
2258 process_pending_handles(multi); /* multiplexed */
2260 /* Only perform the transfer if there's a good socket to work with.
2261 Having both BAD is a signal to skip immediately to DONE */
2262 if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2263 (data->conn->writesockfd != CURL_SOCKET_BAD))
2264 multistate(data, MSTATE_PERFORMING);
2266 #ifndef CURL_DISABLE_FTP
2267 if(data->state.wildcardmatch &&
2268 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2269 data->wildcard.state = CURLWC_DONE;
2272 multistate(data, MSTATE_DONE);
2274 rc = CURLM_CALL_MULTI_PERFORM;
2277 case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2278 DEBUGASSERT(data->conn);
2279 /* if both rates are within spec, resume transfer */
2280 if(Curl_pgrsUpdate(data))
2281 result = CURLE_ABORTED_BY_CALLBACK;
2283 result = Curl_speedcheck(data, *nowp);
2286 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2287 result != CURLE_HTTP2_STREAM)
2288 streamclose(data->conn, "Transfer returned error");
2290 Curl_posttransfer(data);
2291 multi_done(data, result, TRUE);
2294 send_timeout_ms = 0;
2295 if(data->set.max_send_speed)
2297 Curl_pgrsLimitWaitTime(data->progress.uploaded,
2298 data->progress.ul_limit_size,
2299 data->set.max_send_speed,
2300 data->progress.ul_limit_start,
2303 recv_timeout_ms = 0;
2304 if(data->set.max_recv_speed)
2306 Curl_pgrsLimitWaitTime(data->progress.downloaded,
2307 data->progress.dl_limit_size,
2308 data->set.max_recv_speed,
2309 data->progress.dl_limit_start,
2312 if(!send_timeout_ms && !recv_timeout_ms) {
2313 multistate(data, MSTATE_PERFORMING);
2314 Curl_ratelimit(data, *nowp);
2316 else if(send_timeout_ms >= recv_timeout_ms)
2317 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2319 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2323 case MSTATE_PERFORMING:
2325 char *newurl = NULL;
2327 bool comeback = FALSE;
2328 DEBUGASSERT(data->state.buffer);
2329 /* check if over send speed */
2330 send_timeout_ms = 0;
2331 if(data->set.max_send_speed)
2332 send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2333 data->progress.ul_limit_size,
2334 data->set.max_send_speed,
2335 data->progress.ul_limit_start,
2338 /* check if over recv speed */
2339 recv_timeout_ms = 0;
2340 if(data->set.max_recv_speed)
2341 recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2342 data->progress.dl_limit_size,
2343 data->set.max_recv_speed,
2344 data->progress.dl_limit_start,
2347 if(send_timeout_ms || recv_timeout_ms) {
2348 Curl_ratelimit(data, *nowp);
2349 multistate(data, MSTATE_RATELIMITING);
2350 if(send_timeout_ms >= recv_timeout_ms)
2351 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2353 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2357 /* read/write data if it is ready to do so */
2358 result = Curl_readwrite(data->conn, data, &done, &comeback);
2360 if(done || (result == CURLE_RECV_ERROR)) {
2361 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2362 * condition and the server closed the re-used connection exactly when
2363 * we wanted to use it, so figure out if that is indeed the case.
2365 CURLcode ret = Curl_retry_request(data, &newurl);
2367 retry = (newurl)?TRUE:FALSE;
2372 /* if we are to retry, set the result to OK and consider the
2378 else if((CURLE_HTTP2_STREAM == result) &&
2379 Curl_h2_http_1_1_error(data)) {
2380 CURLcode ret = Curl_retry_request(data, &newurl);
2383 infof(data, "Downgrades to HTTP/1.1");
2384 streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2385 data->state.httpwant = CURL_HTTP_VERSION_1_1;
2386 /* clear the error message bit too as we ignore the one we got */
2387 data->state.errorbuf = FALSE;
2389 /* typically for HTTP_1_1_REQUIRED error on first flight */
2390 newurl = strdup(data->state.url);
2391 /* if we are to retry, set the result to OK and consider the request
2403 * The transfer phase returned error, we mark the connection to get
2404 * closed to prevent being re-used. This is because we can't possibly
2405 * know if the connection is in a good shape or not now. Unless it is
2406 * a protocol which uses two "channels" like FTP, as then the error
2407 * happened in the data connection.
2410 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2411 result != CURLE_HTTP2_STREAM)
2412 streamclose(data->conn, "Transfer returned error");
2414 Curl_posttransfer(data);
2415 multi_done(data, result, TRUE);
2419 /* call this even if the readwrite function returned error */
2420 Curl_posttransfer(data);
2422 /* When we follow redirects or is set to retry the connection, we must
2423 to go back to the CONNECT state */
2424 if(data->req.newurl || retry) {
2425 followtype follow = FOLLOW_NONE;
2427 /* if the URL is a follow-location and not just a retried request
2428 then figure out the URL here */
2430 newurl = data->req.newurl;
2431 data->req.newurl = NULL;
2432 follow = FOLLOW_REDIR;
2435 follow = FOLLOW_RETRY;
2436 (void)multi_done(data, CURLE_OK, FALSE);
2437 /* multi_done() might return CURLE_GOT_NOTHING */
2438 result = Curl_follow(data, newurl, follow);
2440 multistate(data, MSTATE_CONNECT);
2441 rc = CURLM_CALL_MULTI_PERFORM;
2446 /* after the transfer is done, go DONE */
2448 /* but first check to see if we got a location info even though we're
2449 not following redirects */
2450 if(data->req.location) {
2452 newurl = data->req.location;
2453 data->req.location = NULL;
2454 result = Curl_follow(data, newurl, FOLLOW_FAKE);
2457 stream_error = TRUE;
2458 result = multi_done(data, result, TRUE);
2463 multistate(data, MSTATE_DONE);
2464 rc = CURLM_CALL_MULTI_PERFORM;
2469 /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2470 won't get stuck on this transfer at the expense of other concurrent
2472 Curl_expire(data, 0, EXPIRE_RUN_NOW);
2479 /* this state is highly transient, so run another loop after this */
2480 rc = CURLM_CALL_MULTI_PERFORM;
2485 if(data->conn->bits.multiplex)
2486 /* Check if we can move pending requests to connection */
2487 process_pending_handles(multi); /* multiplexing */
2489 /* post-transfer command */
2490 res = multi_done(data, result, FALSE);
2492 /* allow a previously set error code take precedence */
2497 #ifndef CURL_DISABLE_FTP
2498 if(data->state.wildcardmatch) {
2499 if(data->wildcard.state != CURLWC_DONE) {
2500 /* if a wildcard is set and we are not ending -> lets start again
2502 multistate(data, MSTATE_INIT);
2507 /* after we have DONE what we're supposed to do, go COMPLETED, and
2508 it doesn't matter what the multi_done() returned! */
2509 multistate(data, MSTATE_COMPLETED);
2512 case MSTATE_COMPLETED:
2515 case MSTATE_MSGSENT:
2516 data->result = result;
2517 return CURLM_OK; /* do nothing */
2520 return CURLM_INTERNAL_ERROR;
2524 data->mstate >= MSTATE_CONNECT &&
2525 data->mstate < MSTATE_DO &&
2526 rc != CURLM_CALL_MULTI_PERFORM &&
2527 !multi_ischanged(multi, false)) {
2528 /* We now handle stream timeouts if and only if this will be the last
2529 * loop iteration. We only check this on the last iteration to ensure
2530 * that if we know we have additional work to do immediately
2531 * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2532 * declaring the connection timed out as we may almost have a completed
2534 multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
2539 if(data->mstate < MSTATE_COMPLETED) {
2542 * If an error was returned, and we aren't in completed state now,
2543 * then we go to completed and consider this transfer aborted.
2546 /* NOTE: no attempt to disconnect connections must be made
2547 in the case blocks above - cleanup happens only here */
2549 /* Check if we can move pending requests to send pipe */
2550 process_pending_handles(multi); /* connection */
2554 /* Don't attempt to send data over a connection that timed out */
2555 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2556 struct connectdata *conn = data->conn;
2558 /* This is where we make sure that the conn pointer is reset.
2559 We don't have to do this in every case block above where a
2560 failure is detected */
2561 Curl_detach_connection(data);
2563 /* remove connection from cache */
2564 Curl_conncache_remove_conn(data, conn, TRUE);
2566 /* disconnect properly */
2567 Curl_disconnect(data, conn, dead_connection);
2570 else if(data->mstate == MSTATE_CONNECT) {
2571 /* Curl_connect() failed */
2572 (void)Curl_posttransfer(data);
2575 multistate(data, MSTATE_COMPLETED);
2576 rc = CURLM_CALL_MULTI_PERFORM;
2578 /* if there's still a connection to use, call the progress function */
2579 else if(data->conn && Curl_pgrsUpdate(data)) {
2580 /* aborted due to progress callback return code must close the
2582 result = CURLE_ABORTED_BY_CALLBACK;
2583 streamclose(data->conn, "Aborted by callback");
2585 /* if not yet in DONE state, go there, otherwise COMPLETED */
2586 multistate(data, (data->mstate < MSTATE_DONE)?
2587 MSTATE_DONE: MSTATE_COMPLETED);
2588 rc = CURLM_CALL_MULTI_PERFORM;
2592 if(MSTATE_COMPLETED == data->mstate) {
2593 if(data->set.fmultidone) {
2594 /* signal via callback instead */
2595 data->set.fmultidone(data, result);
2598 /* now fill in the Curl_message with this info */
2601 msg->extmsg.msg = CURLMSG_DONE;
2602 msg->extmsg.easy_handle = data;
2603 msg->extmsg.data.result = result;
2605 rc = multi_addmsg(multi, msg);
2606 DEBUGASSERT(!data->conn);
2608 multistate(data, MSTATE_MSGSENT);
2610 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2612 data->result = result;
2617 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2619 struct Curl_easy *data;
2620 CURLMcode returncode = CURLM_OK;
2621 struct Curl_tree *t;
2622 struct curltime now = Curl_now();
2624 if(!GOOD_MULTI_HANDLE(multi))
2625 return CURLM_BAD_HANDLE;
2627 if(multi->in_callback)
2628 return CURLM_RECURSIVE_API_CALL;
2630 data = multi->easyp;
2633 SIGPIPE_VARIABLE(pipe_st);
2635 sigpipe_ignore(data, &pipe_st);
2636 result = multi_runsingle(multi, &now, data);
2637 sigpipe_restore(&pipe_st);
2640 returncode = result;
2642 data = data->next; /* operate on next handle */
2646 * Simply remove all expired timers from the splay since handles are dealt
2647 * with unconditionally by this function and curl_multi_timeout() requires
2648 * that already passed/handled expire times are removed from the splay.
2650 * It is important that the 'now' value is set at the entry of this function
2651 * and not for the current time as it may have ticked a little while since
2652 * then and then we risk this loop to remove timers that actually have not
2656 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2658 /* the removed may have another timeout in queue */
2659 (void)add_next_timeout(now, multi, t->payload);
2663 *running_handles = multi->num_alive;
2665 if(CURLM_OK >= returncode)
2666 returncode = Curl_update_timer(multi);
2671 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2673 struct Curl_easy *data;
2674 struct Curl_easy *nextdata;
2676 if(GOOD_MULTI_HANDLE(multi)) {
2677 if(multi->in_callback)
2678 return CURLM_RECURSIVE_API_CALL;
2680 multi->magic = 0; /* not good anymore */
2682 /* First remove all remaining easy handles */
2683 data = multi->easyp;
2685 nextdata = data->next;
2686 if(!data->state.done && data->conn)
2687 /* if DONE was never called for this handle */
2688 (void)multi_done(data, CURLE_OK, TRUE);
2689 if(data->dns.hostcachetype == HCACHE_MULTI) {
2690 /* clear out the usage of the shared DNS cache */
2691 Curl_hostcache_clean(data, data->dns.hostcache);
2692 data->dns.hostcache = NULL;
2693 data->dns.hostcachetype = HCACHE_NONE;
2696 /* Clear the pointer to the connection cache */
2697 data->state.conn_cache = NULL;
2698 data->multi = NULL; /* clear the association */
2701 if(data->psl == &multi->psl)
2708 /* Close all the connections in the connection cache */
2709 Curl_conncache_close_all_connections(&multi->conn_cache);
2711 sockhash_destroy(&multi->sockhash);
2712 Curl_conncache_destroy(&multi->conn_cache);
2713 Curl_llist_destroy(&multi->msglist, NULL);
2714 Curl_llist_destroy(&multi->pending, NULL);
2716 Curl_hash_destroy(&multi->hostcache);
2717 Curl_psl_destroy(&multi->psl);
2720 WSACloseEvent(multi->wsa_event);
2722 #ifdef ENABLE_WAKEUP
2723 sclose(multi->wakeup_pair[0]);
2724 sclose(multi->wakeup_pair[1]);
2731 return CURLM_BAD_HANDLE;
2735 * curl_multi_info_read()
2737 * This function is the primary way for a multi/multi_socket application to
2738 * figure out if a transfer has ended. We MUST make this function as fast as
2739 * possible as it will be polled frequently and we MUST NOT scan any lists in
2740 * here to figure out things. We must scale fine to thousands of handles and
2741 * beyond. The current design is fully O(1).
2744 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2746 struct Curl_message *msg;
2748 *msgs_in_queue = 0; /* default to none */
2750 if(GOOD_MULTI_HANDLE(multi) &&
2751 !multi->in_callback &&
2752 Curl_llist_count(&multi->msglist)) {
2753 /* there is one or more messages in the list */
2754 struct Curl_llist_element *e;
2756 /* extract the head of the list to return */
2757 e = multi->msglist.head;
2761 /* remove the extracted entry */
2762 Curl_llist_remove(&multi->msglist, e, NULL);
2764 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2766 return &msg->extmsg;
2772 * singlesocket() checks what sockets we deal with and their "action state"
2773 * and if we have a different state in any of those sockets from last time we
2774 * call the callback accordingly.
2776 static CURLMcode singlesocket(struct Curl_multi *multi,
2777 struct Curl_easy *data)
2779 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
2781 struct Curl_sh_entry *entry;
2784 unsigned int curraction;
2785 unsigned char actions[MAX_SOCKSPEREASYHANDLE];
2788 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
2789 socks[i] = CURL_SOCKET_BAD;
2791 /* Fill in the 'current' struct with the state as it is now: what sockets to
2792 supervise and for what actions */
2793 curraction = multi_getsock(data, socks);
2795 /* We have 0 .. N sockets already and we get to know about the 0 .. M
2796 sockets we should have from now on. Detect the differences, remove no
2797 longer supervised ones and add new ones */
2799 /* walk over the sockets we got right now */
2800 for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
2801 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2803 unsigned char action = CURL_POLL_NONE;
2804 unsigned char prevaction = 0;
2806 bool sincebefore = FALSE;
2810 /* get it from the hash */
2811 entry = sh_getentry(&multi->sockhash, s);
2813 if(curraction & GETSOCK_READSOCK(i))
2814 action |= CURL_POLL_IN;
2815 if(curraction & GETSOCK_WRITESOCK(i))
2816 action |= CURL_POLL_OUT;
2818 actions[i] = action;
2820 /* check if new for this transfer */
2822 for(j = 0; j< data->numsocks; j++) {
2823 if(s == data->sockets[j]) {
2824 prevaction = data->actions[j];
2831 /* this is a socket we didn't have before, add it to the hash! */
2832 entry = sh_addentry(&multi->sockhash, s);
2835 return CURLM_OUT_OF_MEMORY;
2837 if(sincebefore && (prevaction != action)) {
2838 /* Socket was used already, but different action now */
2839 if(prevaction & CURL_POLL_IN)
2841 if(prevaction & CURL_POLL_OUT)
2843 if(action & CURL_POLL_IN)
2845 if(action & CURL_POLL_OUT)
2848 else if(!sincebefore) {
2851 if(action & CURL_POLL_IN)
2853 if(action & CURL_POLL_OUT)
2856 /* add 'data' to the transfer hash on this socket! */
2857 if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2858 sizeof(struct Curl_easy *), data)) {
2859 Curl_hash_destroy(&entry->transfers);
2860 return CURLM_OUT_OF_MEMORY;
2864 comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2865 (entry->readers ? CURL_POLL_IN : 0);
2867 /* socket existed before and has the same action set as before */
2868 if(sincebefore && ((int)entry->action == comboaction))
2869 /* same, continue */
2872 if(multi->socket_cb) {
2873 set_in_callback(multi, TRUE);
2874 rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
2876 set_in_callback(multi, FALSE);
2879 return CURLM_ABORTED_BY_CALLBACK;
2883 entry->action = comboaction; /* store the current action state */
2886 num = i; /* number of sockets */
2888 /* when we've walked over all the sockets we should have right now, we must
2889 make sure to detect sockets that are removed */
2890 for(i = 0; i< data->numsocks; i++) {
2892 bool stillused = FALSE;
2893 s = data->sockets[i];
2894 for(j = 0; j < num; j++) {
2896 /* this is still supervised */
2904 entry = sh_getentry(&multi->sockhash, s);
2905 /* if this is NULL here, the socket has been closed and notified so
2906 already by Curl_multi_closed() */
2908 unsigned char oldactions = data->actions[i];
2909 /* this socket has been removed. Decrease user count */
2911 if(oldactions & CURL_POLL_OUT)
2913 if(oldactions & CURL_POLL_IN)
2916 if(multi->socket_cb) {
2917 set_in_callback(multi, TRUE);
2918 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
2919 multi->socket_userp, entry->socketp);
2920 set_in_callback(multi, FALSE);
2923 return CURLM_ABORTED_BY_CALLBACK;
2926 sh_delentry(entry, &multi->sockhash, s);
2929 /* still users, but remove this handle as a user of this socket */
2930 if(Curl_hash_delete(&entry->transfers, (char *)&data,
2931 sizeof(struct Curl_easy *))) {
2936 } /* for loop over numsocks */
2938 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2939 memcpy(data->actions, actions, num*sizeof(char));
2940 data->numsocks = num;
2944 CURLcode Curl_updatesocket(struct Curl_easy *data)
2946 if(singlesocket(data->multi, data))
2947 return CURLE_ABORTED_BY_CALLBACK;
2953 * Curl_multi_closed()
2955 * Used by the connect code to tell the multi_socket code that one of the
2956 * sockets we were using is about to be closed. This function will then
2957 * remove it from the sockethash for this handle to make the multi_socket API
2958 * behave properly, especially for the case when libcurl will create another
2959 * socket again and it gets the same file descriptor number.
2962 void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
2965 /* if there's still an easy handle associated with this connection */
2966 struct Curl_multi *multi = data->multi;
2968 /* this is set if this connection is part of a handle that is added to
2969 a multi handle, and only then this is necessary */
2970 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2974 if(multi->socket_cb) {
2975 set_in_callback(multi, TRUE);
2976 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
2977 multi->socket_userp, entry->socketp);
2978 set_in_callback(multi, FALSE);
2981 /* now remove it from the socket hash */
2982 sh_delentry(entry, &multi->sockhash, s);
2984 /* This just marks the multi handle as "dead" without returning an
2985 error code primarily because this function is used from many
2986 places where propagating an error back is tricky. */
2994 * add_next_timeout()
2996 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
2997 * when it has just been removed from the splay tree because the timeout has
2998 * expired. This function is then to advance in the list to pick the next
2999 * timeout to use (skip the already expired ones) and add this node back to
3000 * the splay tree again.
3002 * The splay tree only has each sessionhandle as a single node and the nearest
3003 * timeout is used to sort it on.
3005 static CURLMcode add_next_timeout(struct curltime now,
3006 struct Curl_multi *multi,
3007 struct Curl_easy *d)
3009 struct curltime *tv = &d->state.expiretime;
3010 struct Curl_llist *list = &d->state.timeoutlist;
3011 struct Curl_llist_element *e;
3012 struct time_node *node = NULL;
3014 /* move over the timeout list for this specific handle and remove all
3015 timeouts that are now passed tense and store the next pending
3017 for(e = list->head; e;) {
3018 struct Curl_llist_element *n = e->next;
3020 node = (struct time_node *)e->ptr;
3021 diff = Curl_timediff(node->time, now);
3023 /* remove outdated entry */
3024 Curl_llist_remove(list, e, NULL);
3026 /* the list is sorted so get out on the first mismatch */
3032 /* clear the expire times within the handles that we remove from the
3038 /* copy the first entry to 'tv' */
3039 memcpy(tv, &node->time, sizeof(*tv));
3041 /* Insert this node again into the splay. Keep the timer in the list in
3042 case we need to recompute future timers. */
3043 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3044 &d->state.timenode);
3049 static CURLMcode multi_socket(struct Curl_multi *multi,
3053 int *running_handles)
3055 CURLMcode result = CURLM_OK;
3056 struct Curl_easy *data = NULL;
3057 struct Curl_tree *t;
3058 struct curltime now = Curl_now();
3061 /* *perform() deals with running_handles on its own */
3062 result = curl_multi_perform(multi, running_handles);
3064 /* walk through each easy handle and do the socket state change magic
3066 if(result != CURLM_BAD_HANDLE) {
3067 data = multi->easyp;
3068 while(data && !result) {
3069 result = singlesocket(multi, data);
3074 /* or should we fall-through and do the timer-based stuff? */
3077 if(s != CURL_SOCKET_TIMEOUT) {
3078 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3081 /* Unmatched socket, we can't act on it but we ignore this fact. In
3082 real-world tests it has been proved that libevent can in fact give
3083 the application actions even though the socket was just previously
3084 asked to get removed, so thus we better survive stray socket actions
3085 and just move on. */
3088 struct Curl_hash_iterator iter;
3089 struct Curl_hash_element *he;
3091 /* the socket can be shared by many transfers, iterate */
3092 Curl_hash_start_iterate(&entry->transfers, &iter);
3093 for(he = Curl_hash_next_element(&iter); he;
3094 he = Curl_hash_next_element(&iter)) {
3095 data = (struct Curl_easy *)he->ptr;
3097 DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3099 if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3100 /* set socket event bitmask if they're not locked */
3101 data->conn->cselect_bits = ev_bitmask;
3103 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3106 /* Now we fall-through and do the timer-based stuff, since we don't want
3107 to force the user to have to deal with timeouts as long as at least
3108 one connection in fact has traffic. */
3110 data = NULL; /* set data to NULL again to avoid calling
3111 multi_runsingle() in case there's no need to */
3112 now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3113 may have taken some time */
3117 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3118 Curl_update_timer() to trigger a callback to the app again even if the
3119 same timeout is still the one to run after this call. That handles the
3120 case when the application asks libcurl to run the timeout
3122 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3126 * The loop following here will go on as long as there are expire-times left
3127 * to process in the splay and 'data' will be re-assigned for every expired
3128 * handle we deal with.
3131 /* the first loop lap 'data' can be NULL */
3133 SIGPIPE_VARIABLE(pipe_st);
3135 sigpipe_ignore(data, &pipe_st);
3136 result = multi_runsingle(multi, &now, data);
3137 sigpipe_restore(&pipe_st);
3139 if(CURLM_OK >= result) {
3140 /* get the socket(s) and check if the state has been changed since
3142 result = singlesocket(multi, data);
3148 /* Check if there's one (more) expired timer to deal with! This function
3149 extracts a matching node if there is one */
3151 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3153 data = t->payload; /* assign this for next loop */
3154 (void)add_next_timeout(now, multi, t->payload);
3159 *running_handles = multi->num_alive;
3163 #undef curl_multi_setopt
3164 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3165 CURLMoption option, ...)
3167 CURLMcode res = CURLM_OK;
3170 if(!GOOD_MULTI_HANDLE(multi))
3171 return CURLM_BAD_HANDLE;
3173 if(multi->in_callback)
3174 return CURLM_RECURSIVE_API_CALL;
3176 va_start(param, option);
3179 case CURLMOPT_SOCKETFUNCTION:
3180 multi->socket_cb = va_arg(param, curl_socket_callback);
3182 case CURLMOPT_SOCKETDATA:
3183 multi->socket_userp = va_arg(param, void *);
3185 case CURLMOPT_PUSHFUNCTION:
3186 multi->push_cb = va_arg(param, curl_push_callback);
3188 case CURLMOPT_PUSHDATA:
3189 multi->push_userp = va_arg(param, void *);
3191 case CURLMOPT_PIPELINING:
3192 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
3194 case CURLMOPT_TIMERFUNCTION:
3195 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3197 case CURLMOPT_TIMERDATA:
3198 multi->timer_userp = va_arg(param, void *);
3200 case CURLMOPT_MAXCONNECTS:
3201 multi->maxconnects = va_arg(param, long);
3203 case CURLMOPT_MAX_HOST_CONNECTIONS:
3204 multi->max_host_connections = va_arg(param, long);
3206 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3207 multi->max_total_connections = va_arg(param, long);
3209 /* options formerly used for pipelining */
3210 case CURLMOPT_MAX_PIPELINE_LENGTH:
3212 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3214 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3216 case CURLMOPT_PIPELINING_SITE_BL:
3218 case CURLMOPT_PIPELINING_SERVER_BL:
3220 case CURLMOPT_MAX_CONCURRENT_STREAMS:
3222 long streams = va_arg(param, long);
3225 multi->max_concurrent_streams = curlx_sltoui(streams);
3229 res = CURLM_UNKNOWN_OPTION;
3236 /* we define curl_multi_socket() in the public multi.h header */
3237 #undef curl_multi_socket
3239 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3240 int *running_handles)
3243 if(multi->in_callback)
3244 return CURLM_RECURSIVE_API_CALL;
3245 result = multi_socket(multi, FALSE, s, 0, running_handles);
3246 if(CURLM_OK >= result)
3247 result = Curl_update_timer(multi);
3251 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3252 int ev_bitmask, int *running_handles)
3255 if(multi->in_callback)
3256 return CURLM_RECURSIVE_API_CALL;
3257 result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3258 if(CURLM_OK >= result)
3259 result = Curl_update_timer(multi);
3263 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3266 if(multi->in_callback)
3267 return CURLM_RECURSIVE_API_CALL;
3268 result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3269 if(CURLM_OK >= result)
3270 result = Curl_update_timer(multi);
3274 static CURLMcode multi_timeout(struct Curl_multi *multi,
3277 static const struct curltime tv_zero = {0, 0};
3284 if(multi->timetree) {
3285 /* we have a tree of expire times */
3286 struct curltime now = Curl_now();
3288 /* splay the lowest to the bottom */
3289 multi->timetree = Curl_splay(tv_zero, multi->timetree);
3291 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3292 /* some time left before expiration */
3293 timediff_t diff = Curl_timediff(multi->timetree->key, now);
3296 * Since we only provide millisecond resolution on the returned value
3297 * and the diff might be less than one millisecond here, we don't
3298 * return zero as that may cause short bursts of busyloops on fast
3299 * processors while the diff is still present but less than one
3300 * millisecond! instead we return 1 until the time is ripe.
3304 /* this should be safe even on 64 bit archs, as we don't use that
3305 overly long timeouts */
3306 *timeout_ms = (long)diff;
3309 /* 0 means immediately */
3318 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3321 /* First, make some basic checks that the CURLM handle is a good handle */
3322 if(!GOOD_MULTI_HANDLE(multi))
3323 return CURLM_BAD_HANDLE;
3325 if(multi->in_callback)
3326 return CURLM_RECURSIVE_API_CALL;
3328 return multi_timeout(multi, timeout_ms);
3332 * Tell the application it should update its timers, if it subscribes to the
3333 * update timer callback.
3335 CURLMcode Curl_update_timer(struct Curl_multi *multi)
3340 if(!multi->timer_cb || multi->dead)
3342 if(multi_timeout(multi, &timeout_ms)) {
3345 if(timeout_ms < 0) {
3346 static const struct curltime none = {0, 0};
3347 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3348 multi->timer_lastcall = none;
3349 /* there's no timeout now but there was one previously, tell the app to
3351 set_in_callback(multi, TRUE);
3352 rc = multi->timer_cb(multi, -1, multi->timer_userp);
3353 set_in_callback(multi, FALSE);
3356 return CURLM_ABORTED_BY_CALLBACK;
3363 /* When multi_timeout() is done, multi->timetree points to the node with the
3364 * timeout we got the (relative) time-out time for. We can thus easily check
3365 * if this is the same (fixed) time as we got in a previous call and then
3366 * avoid calling the callback again. */
3367 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3370 multi->timer_lastcall = multi->timetree->key;
3372 set_in_callback(multi, TRUE);
3373 rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3374 set_in_callback(multi, FALSE);
3377 return CURLM_ABORTED_BY_CALLBACK;
3383 * multi_deltimeout()
3385 * Remove a given timestamp from the list of timeouts.
3388 multi_deltimeout(struct Curl_easy *data, expire_id eid)
3390 struct Curl_llist_element *e;
3391 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3392 /* find and remove the specific node from the list */
3393 for(e = timeoutlist->head; e; e = e->next) {
3394 struct time_node *n = (struct time_node *)e->ptr;
3396 Curl_llist_remove(timeoutlist, e, NULL);
3403 * multi_addtimeout()
3405 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3406 * of list is always the timeout nearest in time.
3410 multi_addtimeout(struct Curl_easy *data,
3411 struct curltime *stamp,
3414 struct Curl_llist_element *e;
3415 struct time_node *node;
3416 struct Curl_llist_element *prev = NULL;
3418 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3420 node = &data->state.expires[eid];
3422 /* copy the timestamp and id */
3423 memcpy(&node->time, stamp, sizeof(*stamp));
3424 node->eid = eid; /* also marks it as in use */
3426 n = Curl_llist_count(timeoutlist);
3428 /* find the correct spot in the list */
3429 for(e = timeoutlist->head; e; e = e->next) {
3430 struct time_node *check = (struct time_node *)e->ptr;
3431 timediff_t diff = Curl_timediff(check->time, node->time);
3439 this is the first timeout on the list */
3441 Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3448 * given a number of milliseconds from now to use to set the 'act before
3449 * this'-time for the transfer, to be extracted by curl_multi_timeout()
3451 * The timeout will be added to a queue of timeouts if it defines a moment in
3452 * time that is later than the current head of queue.
3454 * Expire replaces a former timeout using the same id if already set.
3456 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3458 struct Curl_multi *multi = data->multi;
3459 struct curltime *nowp = &data->state.expiretime;
3460 struct curltime set;
3462 /* this is only interesting while there is still an associated multi struct
3467 DEBUGASSERT(id < EXPIRE_LAST);
3470 set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3471 set.tv_usec += (unsigned int)(milli%1000)*1000;
3473 if(set.tv_usec >= 1000000) {
3475 set.tv_usec -= 1000000;
3478 /* Remove any timer with the same id just in case. */
3479 multi_deltimeout(data, id);
3481 /* Add it to the timer list. It must stay in the list until it has expired
3482 in case we need to recompute the minimum timer later. */
3483 multi_addtimeout(data, &set, id);
3485 if(nowp->tv_sec || nowp->tv_usec) {
3486 /* This means that the struct is added as a node in the splay tree.
3487 Compare if the new time is earlier, and only remove-old/add-new if it
3489 timediff_t diff = Curl_timediff(set, *nowp);
3493 /* The current splay tree entry is sooner than this new expiry time.
3494 We don't need to update our splay tree entry. */
3498 /* Since this is an updated time, we must remove the previous entry from
3499 the splay tree first and then re-add the new value */
3500 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3503 infof(data, "Internal error removing splay node = %d", rc);
3506 /* Indicate that we are in the splay tree and insert the new timer expiry
3507 value since it is our local minimum. */
3509 data->state.timenode.payload = data;
3510 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3511 &data->state.timenode);
3515 * Curl_expire_done()
3517 * Removes the expire timer. Marks it as done.
3520 void Curl_expire_done(struct Curl_easy *data, expire_id id)
3522 /* remove the timer, if there */
3523 multi_deltimeout(data, id);
3527 * Curl_expire_clear()
3529 * Clear ALL timeout values for this handle.
3531 void Curl_expire_clear(struct Curl_easy *data)
3533 struct Curl_multi *multi = data->multi;
3534 struct curltime *nowp = &data->state.expiretime;
3536 /* this is only interesting while there is still an associated multi struct
3541 if(nowp->tv_sec || nowp->tv_usec) {
3542 /* Since this is an cleared time, we must remove the previous entry from
3544 struct Curl_llist *list = &data->state.timeoutlist;
3547 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3550 infof(data, "Internal error clearing splay node = %d", rc);
3552 /* flush the timeout list too */
3553 while(list->size > 0) {
3554 Curl_llist_remove(list, list->tail, NULL);
3558 infof(data, "Expire cleared (transfer %p)", data);
3568 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3571 struct Curl_sh_entry *there = NULL;
3573 there = sh_getentry(&multi->sockhash, s);
3576 return CURLM_BAD_SOCKET;
3578 there->socketp = hashp;
3583 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3585 return multi ? multi->max_host_connections : 0;
3588 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3590 return multi ? multi->max_total_connections : 0;
3594 * When information about a connection has appeared, call this!
3597 void Curl_multiuse_state(struct Curl_easy *data,
3598 int bundlestate) /* use BUNDLE_* defines */
3600 struct connectdata *conn;
3602 DEBUGASSERT(data->multi);
3605 DEBUGASSERT(conn->bundle);
3607 conn->bundle->multiuse = bundlestate;
3608 process_pending_handles(data->multi);
3611 static void process_pending_handles(struct Curl_multi *multi)
3613 struct Curl_llist_element *e = multi->pending.head;
3615 struct Curl_easy *data = e->ptr;
3617 DEBUGASSERT(data->mstate == MSTATE_PENDING);
3619 multistate(data, MSTATE_CONNECT);
3621 /* Remove this node from the list */
3622 Curl_llist_remove(&multi->pending, e, NULL);
3624 /* Make sure that the handle will be processed soonish. */
3625 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3627 /* mark this as having been in the pending queue */
3628 data->state.previouslypending = TRUE;
3632 void Curl_set_in_callback(struct Curl_easy *data, bool value)
3634 /* might get called when there is no data pointer! */
3636 if(data->multi_easy)
3637 data->multi_easy->in_callback = value;
3638 else if(data->multi)
3639 data->multi->in_callback = value;
3643 bool Curl_is_in_callback(struct Curl_easy *easy)
3645 return ((easy->multi && easy->multi->in_callback) ||
3646 (easy->multi_easy && easy->multi_easy->in_callback));
3650 void Curl_multi_dump(struct Curl_multi *multi)
3652 struct Curl_easy *data;
3654 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
3655 multi->num_easy, multi->num_alive);
3656 for(data = multi->easyp; data; data = data->next) {
3657 if(data->mstate < MSTATE_COMPLETED) {
3658 /* only display handles that are not completed */
3659 fprintf(stderr, "handle %p, state %s, %d sockets\n",
3661 statename[data->mstate], data->numsocks);
3662 for(i = 0; i < data->numsocks; i++) {
3663 curl_socket_t s = data->sockets[i];
3664 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3666 fprintf(stderr, "%d ", (int)s);
3668 fprintf(stderr, "INTERNAL CONFUSION\n");
3671 fprintf(stderr, "[%s %s] ",
3672 (entry->action&CURL_POLL_IN)?"RECVING":"",
3673 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3676 fprintf(stderr, "\n");
3682 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3685 return multi->max_concurrent_streams;