1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, et al.
9 *
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.
13 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26
27#include <curl/curl.h>
28
29#include "urldata.h"
30#include "transfer.h"
31#include "url.h"
32#include "connect.h"
33#include "progress.h"
34#include "easyif.h"
35#include "share.h"
36#include "psl.h"
37#include "multiif.h"
38#include "sendf.h"
39#include "timeval.h"
40#include "http.h"
41#include "select.h"
42#include "warnless.h"
43#include "speedcheck.h"
44#include "conncache.h"
45#include "multihandle.h"
46#include "sigpipe.h"
47#include "vtls/vtls.h"
48#include "connect.h"
49#include "http_proxy.h"
50#include "http2.h"
51#include "socketpair.h"
52#include "socks.h"
53/* The last 3 #include files should be in this order */
54#include "curl_printf.h"
55#include "curl_memory.h"
56#include "memdebug.h"
57
58#ifdef __APPLE__
59
60#define wakeup_write write
61#define wakeup_read read
62#define wakeup_close close
63#define wakeup_create pipe
64
65#else /* __APPLE__ */
66
67#define wakeup_write swrite
68#define wakeup_read sread
69#define wakeup_close sclose
70#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
71
72#endif /* __APPLE__ */
73
74/*
75 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
76 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
77 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
78*/
79#ifndef CURL_SOCKET_HASH_TABLE_SIZE
80#define CURL_SOCKET_HASH_TABLE_SIZE 911
81#endif
82
83#ifndef CURL_CONNECTION_HASH_SIZE
84#define CURL_CONNECTION_HASH_SIZE 97
85#endif
86
87#ifndef CURL_DNS_HASH_SIZE
88#define CURL_DNS_HASH_SIZE 71
89#endif
90
91#define CURL_MULTI_HANDLE 0x000bab1e
92
93#define GOOD_MULTI_HANDLE(x) \
94 ((x) && (x)->magic == CURL_MULTI_HANDLE)
95
96static CURLMcode singlesocket(struct Curl_multi *multi,
97 struct Curl_easy *data);
98static CURLMcode add_next_timeout(struct curltime now,
99 struct Curl_multi *multi,
100 struct Curl_easy *d);
101static CURLMcode multi_timeout(struct Curl_multi *multi,
102 long *timeout_ms);
103static void process_pending_handles(struct Curl_multi *multi);
104
105#ifdef DEBUGBUILD
106static const char * const statename[]={
107 "INIT",
108 "PENDING",
109 "CONNECT",
110 "RESOLVING",
111 "CONNECTING",
112 "TUNNELING",
113 "PROTOCONNECT",
114 "PROTOCONNECTING",
115 "DO",
116 "DOING",
117 "DOING_MORE",
118 "DID",
119 "PERFORMING",
120 "RATELIMITING",
121 "DONE",
122 "COMPLETED",
123 "MSGSENT",
124};
125#endif
126
127/* function pointer called once when switching TO a state */
128typedef void (*init_multistate_func)(struct Curl_easy *data);
129
130/* called in DID state, before PERFORMING state */
131static void before_perform(struct Curl_easy *data)
132{
133 data->req.chunk = FALSE;
134 Curl_pgrsTime(data, TIMER_PRETRANSFER);
135}
136
137static void init_completed(struct Curl_easy *data)
138{
139 /* this is a completed transfer */
140
141 /* Important: reset the conn pointer so that we don't point to memory
142 that could be freed anytime */
143 Curl_detach_connection(data);
144 Curl_expire_clear(data); /* stop all timers */
145}
146
147/* always use this function to change state, to make debugging easier */
148static void mstate(struct Curl_easy *data, CURLMstate state
149#ifdef DEBUGBUILD
150 , int lineno
151#endif
152)
153{
154 CURLMstate oldstate = data->mstate;
155 static const init_multistate_func finit[MSTATE_LAST] = {
156 NULL, /* INIT */
157 NULL, /* PENDING */
158 Curl_init_CONNECT, /* CONNECT */
159 NULL, /* RESOLVING */
160 NULL, /* CONNECTING */
161 NULL, /* TUNNELING */
162 NULL, /* PROTOCONNECT */
163 NULL, /* PROTOCONNECTING */
164 Curl_connect_free, /* DO */
165 NULL, /* DOING */
166 NULL, /* DOING_MORE */
167 before_perform, /* DID */
168 NULL, /* PERFORMING */
169 NULL, /* RATELIMITING */
170 NULL, /* DONE */
171 init_completed, /* COMPLETED */
172 NULL /* MSGSENT */
173 };
174
175#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
176 (void) lineno;
177#endif
178
179 if(oldstate == state)
180 /* don't bother when the new state is the same as the old state */
181 return;
182
183 data->mstate = state;
184
185#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
186 if(data->mstate >= MSTATE_PENDING &&
187 data->mstate < MSTATE_COMPLETED) {
188 long connection_id = -5000;
189
190 if(data->conn)
191 connection_id = data->conn->connection_id;
192
193 infof(data,
194 "STATE: %s => %s handle %p; line %d (connection #%ld)",
195 statename[oldstate], statename[data->mstate],
196 (void *)data, lineno, connection_id);
197 }
198#endif
199
200 if(state == MSTATE_COMPLETED) {
201 /* changing to COMPLETED means there's one less easy handle 'alive' */
202 DEBUGASSERT(data->multi->num_alive > 0);
203 data->multi->num_alive--;
204 }
205
206 /* if this state has an init-function, run it */
207 if(finit[state])
208 finit[state](data);
209}
210
211#ifndef DEBUGBUILD
212#define multistate(x,y) mstate(x,y)
213#else
214#define multistate(x,y) mstate(x,y, __LINE__)
215#endif
216
217/*
218 * We add one of these structs to the sockhash for each socket
219 */
220
221struct Curl_sh_entry {
222 struct Curl_hash transfers; /* hash of transfers using this socket */
223 unsigned int action; /* what combined action READ/WRITE this socket waits
224 for */
225 unsigned int users; /* number of transfers using this */
226 void *socketp; /* settable by users with curl_multi_assign() */
227 unsigned int readers; /* this many transfers want to read */
228 unsigned int writers; /* this many transfers want to write */
229};
230/* bits for 'action' having no bits means this socket is not expecting any
231 action */
232#define SH_READ 1
233#define SH_WRITE 2
234
235/* look up a given socket in the socket hash, skip invalid sockets */
236static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
237 curl_socket_t s)
238{
239 if(s != CURL_SOCKET_BAD) {
240 /* only look for proper sockets */
241 return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
242 }
243 return NULL;
244}
245
246#define TRHASH_SIZE 13
247static size_t trhash(void *key, size_t key_length, size_t slots_num)
248{
249 size_t keyval = (size_t)*(struct Curl_easy **)key;
250 (void) key_length;
251
252 return (keyval % slots_num);
253}
254
255static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
256{
257 (void)k1_len;
258 (void)k2_len;
259
260 return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2;
261}
262
263static void trhash_dtor(void *nada)
264{
265 (void)nada;
266}
267
268/*
269 * The sockhash has its own separate subhash in each entry that need to be
270 * safely destroyed first.
271 */
272static void sockhash_destroy(struct Curl_hash *h)
273{
274 struct Curl_hash_iterator iter;
275 struct Curl_hash_element *he;
276
277 DEBUGASSERT(h);
278 Curl_hash_start_iterate(h, &iter);
279 he = Curl_hash_next_element(&iter);
280 while(he) {
281 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
282 Curl_hash_destroy(&sh->transfers);
283 he = Curl_hash_next_element(&iter);
284 }
285 Curl_hash_destroy(h);
286}
287
288
289/* make sure this socket is present in the hash for this handle */
290static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
291 curl_socket_t s)
292{
293 struct Curl_sh_entry *there = sh_getentry(sh, s);
294 struct Curl_sh_entry *check;
295
296 if(there) {
297 /* it is present, return fine */
298 return there;
299 }
300
301 /* not present, add it */
302 check = calloc(1, sizeof(struct Curl_sh_entry));
303 if(!check)
304 return NULL; /* major failure */
305
306 Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
307 trhash_dtor);
308
309 /* make/add new hash entry */
310 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
311 Curl_hash_destroy(&check->transfers);
312 free(check);
313 return NULL; /* major failure */
314 }
315
316 return check; /* things are good in sockhash land */
317}
318
319
320/* delete the given socket + handle from the hash */
321static void sh_delentry(struct Curl_sh_entry *entry,
322 struct Curl_hash *sh, curl_socket_t s)
323{
324 Curl_hash_destroy(&entry->transfers);
325
326 /* We remove the hash entry. This will end up in a call to
327 sh_freeentry(). */
328 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
329}
330
331/*
332 * free a sockhash entry
333 */
334static void sh_freeentry(void *freethis)
335{
336 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
337
338 free(p);
339}
340
341static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
342{
343 (void) k1_len; (void) k2_len;
344
345 return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
346}
347
348static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
349{
350 curl_socket_t fd = *((curl_socket_t *) key);
351 (void) key_length;
352
353 return (fd % slots_num);
354}
355
356/*
357 * sh_init() creates a new socket hash and returns the handle for it.
358 *
359 * Quote from README.multi_socket:
360 *
361 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
362 * is somewhat of a bottle neck. Its current implementation may be a bit too
363 * limiting. It simply has a fixed-size array, and on each entry in the array
364 * it has a linked list with entries. So the hash only checks which list to
365 * scan through. The code I had used so for used a list with merely 7 slots
366 * (as that is what the DNS hash uses) but with 7000 connections that would
367 * make an average of 1000 nodes in each list to run through. I upped that to
368 * 97 slots (I believe a prime is suitable) and noticed a significant speed
369 * increase. I need to reconsider the hash implementation or use a rather
370 * large default value like this. At 9000 connections I was still below 10us
371 * per call."
372 *
373 */
374static void sh_init(struct Curl_hash *hash, int hashsize)
375{
376 Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
377 sh_freeentry);
378}
379
380/*
381 * multi_addmsg()
382 *
383 * Called when a transfer is completed. Adds the given msg pointer to
384 * the list kept in the multi handle.
385 */
386static CURLMcode multi_addmsg(struct Curl_multi *multi,
387 struct Curl_message *msg)
388{
389 Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
390 &msg->list);
391 return CURLM_OK;
392}
393
394struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
395 int chashsize, /* connection hash */
396 int dnssize) /* dns hash */
397{
398 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
399
400 if(!multi)
401 return NULL;
402
403 multi->magic = CURL_MULTI_HANDLE;
404
405 Curl_init_dnscache(&multi->hostcache, dnssize);
406
407 sh_init(&multi->sockhash, hashsize);
408
409 if(Curl_conncache_init(&multi->conn_cache, chashsize))
410 goto error;
411
412 Curl_llist_init(&multi->msglist, NULL);
413 Curl_llist_init(&multi->pending, NULL);
414
415 multi->multiplexing = TRUE;
416
417 /* -1 means it not set by user, use the default value */
418 multi->maxconnects = -1;
419 multi->max_concurrent_streams = 100;
420 multi->ipv6_works = Curl_ipv6works(NULL);
421
422#ifdef USE_WINSOCK
423 multi->wsa_event = WSACreateEvent();
424 if(multi->wsa_event == WSA_INVALID_EVENT)
425 goto error;
426#else
427#ifdef ENABLE_WAKEUP
428 if(wakeup_create(multi->wakeup_pair) < 0) {
429 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
430 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
431 }
432 else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
433 curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
434 wakeup_close(multi->wakeup_pair[0]);
435 wakeup_close(multi->wakeup_pair[1]);
436 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
437 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
438 }
439#endif
440#endif
441
442 return multi;
443
444 error:
445
446 sockhash_destroy(&multi->sockhash);
447 Curl_hash_destroy(&multi->hostcache);
448 Curl_conncache_destroy(&multi->conn_cache);
449 Curl_llist_destroy(&multi->msglist, NULL);
450 Curl_llist_destroy(&multi->pending, NULL);
451
452 free(multi);
453 return NULL;
454}
455
456struct Curl_multi *curl_multi_init(void)
457{
458 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
459 CURL_CONNECTION_HASH_SIZE,
460 CURL_DNS_HASH_SIZE);
461}
462
463CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
464 struct Curl_easy *data)
465{
466 CURLMcode rc;
467 /* First, make some basic checks that the CURLM handle is a good handle */
468 if(!GOOD_MULTI_HANDLE(multi))
469 return CURLM_BAD_HANDLE;
470
471 /* Verify that we got a somewhat good easy handle too */
472 if(!GOOD_EASY_HANDLE(data))
473 return CURLM_BAD_EASY_HANDLE;
474
475 /* Prevent users from adding same easy handle more than once and prevent
476 adding to more than one multi stack */
477 if(data->multi)
478 return CURLM_ADDED_ALREADY;
479
480 if(multi->in_callback)
481 return CURLM_RECURSIVE_API_CALL;
482
483 if(multi->dead) {
484 /* a "dead" handle cannot get added transfers while any existing easy
485 handles are still alive - but if there are none alive anymore, it is
486 fine to start over and unmark the "deadness" of this handle */
487 if(multi->num_alive)
488 return CURLM_ABORTED_BY_CALLBACK;
489 multi->dead = FALSE;
490 }
491
492 /* Initialize timeout list for this handle */
493 Curl_llist_init(&data->state.timeoutlist, NULL);
494
495 /*
496 * No failure allowed in this function beyond this point. And no
497 * modification of easy nor multi handle allowed before this except for
498 * potential multi's connection cache growing which won't be undone in this
499 * function no matter what.
500 */
501 if(data->set.errorbuffer)
502 data->set.errorbuffer[0] = 0;
503
504 /* make the Curl_easy refer back to this multi handle - before Curl_expire()
505 is called. */
506 data->multi = multi;
507
508 /* Set the timeout for this handle to expire really soon so that it will
509 be taken care of even when this handle is added in the midst of operation
510 when only the curl_multi_socket() API is used. During that flow, only
511 sockets that time-out or have actions will be dealt with. Since this
512 handle has no action yet, we make sure it times out to get things to
513 happen. */
514 Curl_expire(data, 0, EXPIRE_RUN_NOW);
515
516 /* A somewhat crude work-around for a little glitch in Curl_update_timer()
517 that happens if the lastcall time is set to the same time when the handle
518 is removed as when the next handle is added, as then the check in
519 Curl_update_timer() that prevents calling the application multiple times
520 with the same timer info will not trigger and then the new handle's
521 timeout will not be notified to the app.
522
523 The work-around is thus simply to clear the 'lastcall' variable to force
524 Curl_update_timer() to always trigger a callback to the app when a new
525 easy handle is added */
526 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
527
528 rc = Curl_update_timer(multi);
529 if(rc)
530 return rc;
531
532 /* set the easy handle */
533 multistate(data, MSTATE_INIT);
534
535 /* for multi interface connections, we share DNS cache automatically if the
536 easy handle's one is currently not set. */
537 if(!data->dns.hostcache ||
538 (data->dns.hostcachetype == HCACHE_NONE)) {
539 data->dns.hostcache = &multi->hostcache;
540 data->dns.hostcachetype = HCACHE_MULTI;
541 }
542
543 /* Point to the shared or multi handle connection cache */
544 if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
545 data->state.conn_cache = &data->share->conn_cache;
546 else
547 data->state.conn_cache = &multi->conn_cache;
548 data->state.lastconnect_id = -1;
549
550#ifdef USE_LIBPSL
551 /* Do the same for PSL. */
552 if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
553 data->psl = &data->share->psl;
554 else
555 data->psl = &multi->psl;
556#endif
557
558 /* We add the new entry last in the list. */
559 data->next = NULL; /* end of the line */
560 if(multi->easyp) {
561 struct Curl_easy *last = multi->easylp;
562 last->next = data;
563 data->prev = last;
564 multi->easylp = data; /* the new last node */
565 }
566 else {
567 /* first node, make prev NULL! */
568 data->prev = NULL;
569 multi->easylp = multi->easyp = data; /* both first and last */
570 }
571
572 /* increase the node-counter */
573 multi->num_easy++;
574
575 /* increase the alive-counter */
576 multi->num_alive++;
577
578 CONNCACHE_LOCK(data);
579 /* The closure handle only ever has default timeouts set. To improve the
580 state somewhat we clone the timeouts from each added handle so that the
581 closure handle always has the same timeouts as the most recently added
582 easy handle. */
583 data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
584 data->state.conn_cache->closure_handle->set.server_response_timeout =
585 data->set.server_response_timeout;
586 data->state.conn_cache->closure_handle->set.no_signal =
587 data->set.no_signal;
588 CONNCACHE_UNLOCK(data);
589
590 return CURLM_OK;
591}
592
593#if 0
594/* Debug-function, used like this:
595 *
596 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
597 *
598 * Enable the hash print function first by editing hash.c
599 */
600static void debug_print_sock_hash(void *p)
601{
602 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
603
604 fprintf(stderr, " [readers %u][writers %u]",
605 sh->readers, sh->writers);
606}
607#endif
608
609static CURLcode multi_done(struct Curl_easy *data,
610 CURLcode status, /* an error if this is called
611 after an error was detected */
612 bool premature)
613{
614 CURLcode result;
615 struct connectdata *conn = data->conn;
616 unsigned int i;
617
618 DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
619 (int)status, (int)premature, data->state.done));
620
621 if(data->state.done)
622 /* Stop if multi_done() has already been called */
623 return CURLE_OK;
624
625 /* Stop the resolver and free its own resources (but not dns_entry yet). */
626 Curl_resolver_kill(data);
627
628 /* Cleanup possible redirect junk */
629 Curl_safefree(data->req.newurl);
630 Curl_safefree(data->req.location);
631
632 switch(status) {
633 case CURLE_ABORTED_BY_CALLBACK:
634 case CURLE_READ_ERROR:
635 case CURLE_WRITE_ERROR:
636 /* When we're aborted due to a callback return code it basically have to
637 be counted as premature as there is trouble ahead if we don't. We have
638 many callbacks and protocols work differently, we could potentially do
639 this more fine-grained in the future. */
640 premature = TRUE;
641 default:
642 break;
643 }
644
645 /* this calls the protocol-specific function pointer previously set */
646 if(conn->handler->done)
647 result = conn->handler->done(data, status, premature);
648 else
649 result = status;
650
651 if(CURLE_ABORTED_BY_CALLBACK != result) {
652 /* avoid this if we already aborted by callback to avoid this calling
653 another callback */
654 int rc = Curl_pgrsDone(data);
655 if(!result && rc)
656 result = CURLE_ABORTED_BY_CALLBACK;
657 }
658
659 process_pending_handles(data->multi); /* connection / multiplex */
660
661 CONNCACHE_LOCK(data);
662 Curl_detach_connection(data);
663 if(CONN_INUSE(conn)) {
664 /* Stop if still used. */
665 CONNCACHE_UNLOCK(data);
666 DEBUGF(infof(data, "Connection still in use %zu, "
667 "no more multi_done now!",
668 conn->easyq.size));
669 return CURLE_OK;
670 }
671
672 data->state.done = TRUE; /* called just now! */
673
674 if(conn->dns_entry) {
675 Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
676 conn->dns_entry = NULL;
677 }
678 Curl_hostcache_prune(data);
679 Curl_safefree(data->state.ulbuf);
680
681 /* if the transfer was completed in a paused state there can be buffered
682 data left to free */
683 for(i = 0; i < data->state.tempcount; i++) {
684 Curl_dyn_free(&data->state.tempwrite[i].b);
685 }
686 data->state.tempcount = 0;
687
688 /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
689 forced us to close this connection. This is ignored for requests taking
690 place in a NTLM/NEGOTIATE authentication handshake
691
692 if conn->bits.close is TRUE, it means that the connection should be
693 closed in spite of all our efforts to be nice, due to protocol
694 restrictions in our or the server's end
695
696 if premature is TRUE, it means this connection was said to be DONE before
697 the entire request operation is complete and thus we can't know in what
698 state it is for re-using, so we're forced to close it. In a perfect world
699 we can add code that keep track of if we really must close it here or not,
700 but currently we have no such detail knowledge.
701 */
702
703 if((data->set.reuse_forbid
704#if defined(USE_NTLM)
705 && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
706 conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
707#endif
708#if defined(USE_SPNEGO)
709 && !(conn->http_negotiate_state == GSS_AUTHRECV ||
710 conn->proxy_negotiate_state == GSS_AUTHRECV)
711#endif
712 ) || conn->bits.close
713 || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
714 connclose(conn, "disconnecting");
715 Curl_conncache_remove_conn(data, conn, FALSE);
716 CONNCACHE_UNLOCK(data);
717 Curl_disconnect(data, conn, premature);
718 }
719 else {
720 char buffer[256];
721 const char *host =
722#ifndef CURL_DISABLE_PROXY
723 conn->bits.socksproxy ?
724 conn->socks_proxy.host.dispname :
725 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
726#endif
727 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
728 conn->host.dispname;
729 /* create string before returning the connection */
730 long connection_id = conn->connection_id;
731 msnprintf(buffer, sizeof(buffer),
732 "Connection #%ld to host %s left intact",
733 connection_id, host);
734 /* the connection is no longer in use by this transfer */
735 CONNCACHE_UNLOCK(data);
736 if(Curl_conncache_return_conn(data, conn)) {
737 /* remember the most recently used connection */
738 data->state.lastconnect_id = connection_id;
739 infof(data, "%s", buffer);
740 }
741 else
742 data->state.lastconnect_id = -1;
743 }
744
745 Curl_safefree(data->state.buffer);
746 return result;
747}
748
749static int close_connect_only(struct Curl_easy *data,
750 struct connectdata *conn, void *param)
751{
752 (void)param;
753 if(data->state.lastconnect_id != conn->connection_id)
754 return 0;
755
756 if(!conn->bits.connect_only)
757 return 1;
758
759 connclose(conn, "Removing connect-only easy handle");
760
761 return 1;
762}
763
764CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
765 struct Curl_easy *data)
766{
767 struct Curl_easy *easy = data;
768 bool premature;
769 struct Curl_llist_element *e;
770 CURLMcode rc;
771
772 /* First, make some basic checks that the CURLM handle is a good handle */
773 if(!GOOD_MULTI_HANDLE(multi))
774 return CURLM_BAD_HANDLE;
775
776 /* Verify that we got a somewhat good easy handle too */
777 if(!GOOD_EASY_HANDLE(data))
778 return CURLM_BAD_EASY_HANDLE;
779
780 /* Prevent users from trying to remove same easy handle more than once */
781 if(!data->multi)
782 return CURLM_OK; /* it is already removed so let's say it is fine! */
783
784 /* Prevent users from trying to remove an easy handle from the wrong multi */
785 if(data->multi != multi)
786 return CURLM_BAD_EASY_HANDLE;
787
788 if(multi->in_callback)
789 return CURLM_RECURSIVE_API_CALL;
790
791 premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE;
792
793 /* If the 'state' is not INIT or COMPLETED, we might need to do something
794 nice to put the easy_handle in a good known state when this returns. */
795 if(premature) {
796 /* this handle is "alive" so we need to count down the total number of
797 alive connections when this is removed */
798 multi->num_alive--;
799 }
800
801 if(data->conn &&
802 data->mstate > MSTATE_DO &&
803 data->mstate < MSTATE_COMPLETED) {
804 /* Set connection owner so that the DONE function closes it. We can
805 safely do this here since connection is killed. */
806 streamclose(data->conn, "Removed with partial response");
807 }
808
809 if(data->conn) {
810 /* multi_done() clears the association between the easy handle and the
811 connection.
812
813 Note that this ignores the return code simply because there's
814 nothing really useful to do with it anyway! */
815 (void)multi_done(data, data->result, premature);
816 }
817
818 /* The timer must be shut down before data->multi is set to NULL, else the
819 timenode will remain in the splay tree after curl_easy_cleanup is
820 called. Do it after multi_done() in case that sets another time! */
821 Curl_expire_clear(data);
822
823 if(data->connect_queue.ptr)
824 /* the handle was in the pending list waiting for an available connection,
825 so go ahead and remove it */
826 Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
827
828 if(data->dns.hostcachetype == HCACHE_MULTI) {
829 /* stop using the multi handle's DNS cache, *after* the possible
830 multi_done() call above */
831 data->dns.hostcache = NULL;
832 data->dns.hostcachetype = HCACHE_NONE;
833 }
834
835 Curl_wildcard_dtor(&data->wildcard);
836
837 /* destroy the timeout list that is held in the easy handle, do this *after*
838 multi_done() as that may actually call Curl_expire that uses this */
839 Curl_llist_destroy(&data->state.timeoutlist, NULL);
840
841 /* change state without using multistate(), only to make singlesocket() do
842 what we want */
843 data->mstate = MSTATE_COMPLETED;
844
845 /* This ignores the return code even in case of problems because there's
846 nothing more to do about that, here */
847 (void)singlesocket(multi, easy); /* to let the application know what sockets
848 that vanish with this handle */
849
850 /* Remove the association between the connection and the handle */
851 Curl_detach_connection(data);
852
853 if(data->set.connect_only && !data->multi_easy) {
854 /* This removes a handle that was part the multi inteface that used
855 CONNECT_ONLY, that connection is now left alive but since this handle
856 has bits.close set nothing can use that transfer anymore and it is
857 forbidden from reuse. And this easy handle cannot find the connection
858 anymore once removed from the multi handle
859
860 Better close the connection here, at once.
861 */
862 struct connectdata *c;
863 curl_socket_t s;
864 s = Curl_getconnectinfo(data, &c);
865 if((s != CURL_SOCKET_BAD) && c) {
866 Curl_conncache_remove_conn(data, c, TRUE);
867 Curl_disconnect(data, c, TRUE);
868 }
869 }
870
871 if(data->state.lastconnect_id != -1) {
872 /* Mark any connect-only connection for closure */
873 Curl_conncache_foreach(data, data->state.conn_cache,
874 NULL, close_connect_only);
875 }
876
877#ifdef USE_LIBPSL
878 /* Remove the PSL association. */
879 if(data->psl == &multi->psl)
880 data->psl = NULL;
881#endif
882
883 /* as this was using a shared connection cache we clear the pointer to that
884 since we're not part of that multi handle anymore */
885 data->state.conn_cache = NULL;
886
887 data->multi = NULL; /* clear the association to this multi handle */
888
889 /* make sure there's no pending message in the queue sent from this easy
890 handle */
891
892 for(e = multi->msglist.head; e; e = e->next) {
893 struct Curl_message *msg = e->ptr;
894
895 if(msg->extmsg.easy_handle == easy) {
896 Curl_llist_remove(&multi->msglist, e, NULL);
897 /* there can only be one from this specific handle */
898 break;
899 }
900 }
901
902 /* Remove from the pending list if it is there. Otherwise this will
903 remain on the pending list forever due to the state change. */
904 for(e = multi->pending.head; e; e = e->next) {
905 struct Curl_easy *curr_data = e->ptr;
906
907 if(curr_data == data) {
908 Curl_llist_remove(&multi->pending, e, NULL);
909 break;
910 }
911 }
912
913 /* make the previous node point to our next */
914 if(data->prev)
915 data->prev->next = data->next;
916 else
917 multi->easyp = data->next; /* point to first node */
918
919 /* make our next point to our previous node */
920 if(data->next)
921 data->next->prev = data->prev;
922 else
923 multi->easylp = data->prev; /* point to last node */
924
925 /* NOTE NOTE NOTE
926 We do not touch the easy handle here! */
927 multi->num_easy--; /* one less to care about now */
928
929 process_pending_handles(multi);
930
931 rc = Curl_update_timer(multi);
932 if(rc)
933 return rc;
934 return CURLM_OK;
935}
936
937/* Return TRUE if the application asked for multiplexing */
938bool Curl_multiplex_wanted(const struct Curl_multi *multi)
939{
940 return (multi && (multi->multiplexing));
941}
942
943/*
944 * Curl_detach_connection() removes the given transfer from the connection.
945 *
946 * This is the only function that should clear data->conn. This will
947 * occasionally be called with the data->conn pointer already cleared.
948 */
949void Curl_detach_connection(struct Curl_easy *data)
950{
951 struct connectdata *conn = data->conn;
952 if(conn) {
953 Curl_connect_done(data); /* if mid-CONNECT, shut it down */
954 Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
955 Curl_ssl_detach_conn(data, conn);
956 }
957 data->conn = NULL;
958}
959
960/*
961 * Curl_attach_connection() attaches this transfer to this connection.
962 *
963 * This is the only function that should assign data->conn
964 */
965void Curl_attach_connection(struct Curl_easy *data,
966 struct connectdata *conn)
967{
968 DEBUGASSERT(!data->conn);
969 DEBUGASSERT(conn);
970 data->conn = conn;
971 Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
972 &data->conn_queue);
973 if(conn->handler->attach)
974 conn->handler->attach(data, conn);
975 Curl_ssl_associate_conn(data, conn);
976}
977
978static int waitconnect_getsock(struct connectdata *conn,
979 curl_socket_t *sock)
980{
981 int i;
982 int s = 0;
983 int rc = 0;
984
985#ifdef USE_SSL
986#ifndef CURL_DISABLE_PROXY
987 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
988 return Curl_ssl->getsock(conn, sock);
989#endif
990#endif
991
992 if(SOCKS_STATE(conn->cnnct.state))
993 return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
994
995 for(i = 0; i<2; i++) {
996 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
997 sock[s] = conn->tempsock[i];
998 rc |= GETSOCK_WRITESOCK(s);
999#ifdef ENABLE_QUIC
1000 if(conn->transport == TRNSPRT_QUIC)
1001 /* when connecting QUIC, we want to read the socket too */
1002 rc |= GETSOCK_READSOCK(s);
1003#endif
1004 s++;
1005 }
1006 }
1007
1008 return rc;
1009}
1010
1011static int waitproxyconnect_getsock(struct connectdata *conn,
1012 curl_socket_t *sock)
1013{
1014 sock[0] = conn->sock[FIRSTSOCKET];
1015
1016 if(conn->connect_state)
1017 return Curl_connect_getsock(conn);
1018
1019 return GETSOCK_WRITESOCK(0);
1020}
1021
1022static int domore_getsock(struct Curl_easy *data,
1023 struct connectdata *conn,
1024 curl_socket_t *socks)
1025{
1026 if(conn && conn->handler->domore_getsock)
1027 return conn->handler->domore_getsock(data, conn, socks);
1028 return GETSOCK_BLANK;
1029}
1030
1031static int doing_getsock(struct Curl_easy *data,
1032 struct connectdata *conn,
1033 curl_socket_t *socks)
1034{
1035 if(conn && conn->handler->doing_getsock)
1036 return conn->handler->doing_getsock(data, conn, socks);
1037 return GETSOCK_BLANK;
1038}
1039
1040static int protocol_getsock(struct Curl_easy *data,
1041 struct connectdata *conn,
1042 curl_socket_t *socks)
1043{
1044 if(conn->handler->proto_getsock)
1045 return conn->handler->proto_getsock(data, conn, socks);
1046 /* Backup getsock logic. Since there is a live socket in use, we must wait
1047 for it or it will be removed from watching when the multi_socket API is
1048 used. */
1049 socks[0] = conn->sock[FIRSTSOCKET];
1050 return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
1051}
1052
1053/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
1054 array contains MAX_SOCKSPEREASYHANDLE entries. */
1055static int multi_getsock(struct Curl_easy *data,
1056 curl_socket_t *socks)
1057{
1058 struct connectdata *conn = data->conn;
1059 /* The no connection case can happen when this is called from
1060 curl_multi_remove_handle() => singlesocket() => multi_getsock().
1061 */
1062 if(!conn)
1063 return 0;
1064
1065 switch(data->mstate) {
1066 default:
1067 return 0;
1068
1069 case MSTATE_RESOLVING:
1070 return Curl_resolv_getsock(data, socks);
1071
1072 case MSTATE_PROTOCONNECTING:
1073 case MSTATE_PROTOCONNECT:
1074 return protocol_getsock(data, conn, socks);
1075
1076 case MSTATE_DO:
1077 case MSTATE_DOING:
1078 return doing_getsock(data, conn, socks);
1079
1080 case MSTATE_TUNNELING:
1081 return waitproxyconnect_getsock(conn, socks);
1082
1083 case MSTATE_CONNECTING:
1084 return waitconnect_getsock(conn, socks);
1085
1086 case MSTATE_DOING_MORE:
1087 return domore_getsock(data, conn, socks);
1088
1089 case MSTATE_DID: /* since is set after DO is completed, we switch to
1090 waiting for the same as the PERFORMING state */
1091 case MSTATE_PERFORMING:
1092 return Curl_single_getsock(data, conn, socks);
1093 }
1094
1095}
1096
1097CURLMcode curl_multi_fdset(struct Curl_multi *multi,
1098 fd_set *read_fd_set, fd_set *write_fd_set,
1099 fd_set *exc_fd_set, int *max_fd)
1100{
1101 /* Scan through all the easy handles to get the file descriptors set.
1102 Some easy handles may not have connected to the remote host yet,
1103 and then we must make sure that is done. */
1104 struct Curl_easy *data;
1105 int this_max_fd = -1;
1106 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1107 int i;
1108 (void)exc_fd_set; /* not used */
1109
1110 if(!GOOD_MULTI_HANDLE(multi))
1111 return CURLM_BAD_HANDLE;
1112
1113 if(multi->in_callback)
1114 return CURLM_RECURSIVE_API_CALL;
1115
1116 data = multi->easyp;
1117 while(data) {
1118 int bitmap;
1119#ifdef __clang_analyzer_
1120 /* to prevent "The left operand of '>=' is a garbage value" warnings */
1121 memset(sockbunch, 0, sizeof(sockbunch));
1122#endif
1123 bitmap = multi_getsock(data, sockbunch);
1124
1125 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1126 curl_socket_t s = CURL_SOCKET_BAD;
1127
1128 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
1129 if(!FDSET_SOCK(sockbunch[i]))
1130 /* pretend it doesn't exist */
1131 continue;
1132 FD_SET(sockbunch[i], read_fd_set);
1133 s = sockbunch[i];
1134 }
1135 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
1136 if(!FDSET_SOCK(sockbunch[i]))
1137 /* pretend it doesn't exist */
1138 continue;
1139 FD_SET(sockbunch[i], write_fd_set);
1140 s = sockbunch[i];
1141 }
1142 if(s == CURL_SOCKET_BAD)
1143 /* this socket is unused, break out of loop */
1144 break;
1145 if((int)s > this_max_fd)
1146 this_max_fd = (int)s;
1147 }
1148
1149 data = data->next; /* check next handle */
1150 }
1151
1152 *max_fd = this_max_fd;
1153
1154 return CURLM_OK;
1155}
1156
1157#define NUM_POLLS_ON_STACK 10
1158
1159static CURLMcode multi_wait(struct Curl_multi *multi,
1160 struct curl_waitfd extra_fds[],
1161 unsigned int extra_nfds,
1162 int timeout_ms,
1163 int *ret,
1164 bool extrawait, /* when no socket, wait */
1165 bool use_wakeup)
1166{
1167 struct Curl_easy *data;
1168 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1169 int bitmap;
1170 unsigned int i;
1171 unsigned int nfds = 0;
1172 unsigned int curlfds;
1173 long timeout_internal;
1174 int retcode = 0;
1175 struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1176 struct pollfd *ufds = &a_few_on_stack[0];
1177 bool ufds_malloc = FALSE;
1178#ifdef USE_WINSOCK
1179 WSANETWORKEVENTS wsa_events;
1180 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1181#endif
1182#ifndef ENABLE_WAKEUP
1183 (void)use_wakeup;
1184#endif
1185
1186 if(!GOOD_MULTI_HANDLE(multi))
1187 return CURLM_BAD_HANDLE;
1188
1189 if(multi->in_callback)
1190 return CURLM_RECURSIVE_API_CALL;
1191
1192 if(timeout_ms < 0)
1193 return CURLM_BAD_FUNCTION_ARGUMENT;
1194
1195 /* Count up how many fds we have from the multi handle */
1196 data = multi->easyp;
1197 while(data) {
1198 bitmap = multi_getsock(data, sockbunch);
1199
1200 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1201 curl_socket_t s = CURL_SOCKET_BAD;
1202
1203 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1204 ++nfds;
1205 s = sockbunch[i];
1206 }
1207 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1208 ++nfds;
1209 s = sockbunch[i];
1210 }
1211 if(s == CURL_SOCKET_BAD) {
1212 break;
1213 }
1214 }
1215
1216 data = data->next; /* check next handle */
1217 }
1218
1219 /* If the internally desired timeout is actually shorter than requested from
1220 the outside, then use the shorter time! But only if the internal timer
1221 is actually larger than -1! */
1222 (void)multi_timeout(multi, &timeout_internal);
1223 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1224 timeout_ms = (int)timeout_internal;
1225
1226 curlfds = nfds; /* number of internal file descriptors */
1227 nfds += extra_nfds; /* add the externally provided ones */
1228
1229#ifdef ENABLE_WAKEUP
1230#ifdef USE_WINSOCK
1231 if(use_wakeup) {
1232#else
1233 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1234#endif
1235 ++nfds;
1236 }
1237#endif
1238
1239 if(nfds > NUM_POLLS_ON_STACK) {
1240 /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1241 big, so at 2^29 sockets this value might wrap. When a process gets
1242 the capability to actually handle over 500 million sockets this
1243 calculation needs a integer overflow check. */
1244 ufds = malloc(nfds * sizeof(struct pollfd));
1245 if(!ufds)
1246 return CURLM_OUT_OF_MEMORY;
1247 ufds_malloc = TRUE;
1248 }
1249 nfds = 0;
1250
1251 /* only do the second loop if we found descriptors in the first stage run
1252 above */
1253
1254 if(curlfds) {
1255 /* Add the curl handles to our pollfds first */
1256 data = multi->easyp;
1257 while(data) {
1258 bitmap = multi_getsock(data, sockbunch);
1259
1260 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1261 curl_socket_t s = CURL_SOCKET_BAD;
1262#ifdef USE_WINSOCK
1263 long mask = 0;
1264#endif
1265 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1266 s = sockbunch[i];
1267#ifdef USE_WINSOCK
1268 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1269#endif
1270 ufds[nfds].fd = s;
1271 ufds[nfds].events = POLLIN;
1272 ++nfds;
1273 }
1274 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1275 s = sockbunch[i];
1276#ifdef USE_WINSOCK
1277 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1278 send(s, NULL, 0, 0); /* reset FD_WRITE */
1279#endif
1280 ufds[nfds].fd = s;
1281 ufds[nfds].events = POLLOUT;
1282 ++nfds;
1283 }
1284 /* s is only set if either being readable or writable is checked */
1285 if(s == CURL_SOCKET_BAD) {
1286 /* break on entry not checked for being readable or writable */
1287 break;
1288 }
1289#ifdef USE_WINSOCK
1290 if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
1291 if(ufds_malloc)
1292 free(ufds);
1293 return CURLM_INTERNAL_ERROR;
1294 }
1295#endif
1296 }
1297
1298 data = data->next; /* check next handle */
1299 }
1300 }
1301
1302 /* Add external file descriptions from poll-like struct curl_waitfd */
1303 for(i = 0; i < extra_nfds; i++) {
1304#ifdef USE_WINSOCK
1305 long mask = 0;
1306 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1307 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1308 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1309 mask |= FD_OOB;
1310 if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1311 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1312 send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
1313 }
1314 if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1315 if(ufds_malloc)
1316 free(ufds);
1317 return CURLM_INTERNAL_ERROR;
1318 }
1319#endif
1320 ufds[nfds].fd = extra_fds[i].fd;
1321 ufds[nfds].events = 0;
1322 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1323 ufds[nfds].events |= POLLIN;
1324 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1325 ufds[nfds].events |= POLLPRI;
1326 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1327 ufds[nfds].events |= POLLOUT;
1328 ++nfds;
1329 }
1330
1331#ifdef ENABLE_WAKEUP
1332#ifndef USE_WINSOCK
1333 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1334 ufds[nfds].fd = multi->wakeup_pair[0];
1335 ufds[nfds].events = POLLIN;
1336 ++nfds;
1337 }
1338#endif
1339#endif
1340
1341#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1342 if(nfds || use_wakeup) {
1343#else
1344 if(nfds) {
1345#endif
1346 int pollrc;
1347#ifdef USE_WINSOCK
1348 if(nfds)
1349 pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1350 else
1351 pollrc = 0;
1352#else
1353 pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1354#endif
1355 if(pollrc < 0)
1356 return CURLM_UNRECOVERABLE_POLL;
1357
1358 if(pollrc > 0) {
1359 retcode = pollrc;
1360#ifdef USE_WINSOCK
1361 }
1362 else { /* now wait... if not ready during the pre-check (pollrc == 0) */
1363 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1364 }
1365 /* With WinSock, we have to run the following section unconditionally
1366 to call WSAEventSelect(fd, event, 0) on all the sockets */
1367 {
1368#endif
1369 /* copy revents results from the poll to the curl_multi_wait poll
1370 struct, the bit values of the actual underlying poll() implementation
1371 may not be the same as the ones in the public libcurl API! */
1372 for(i = 0; i < extra_nfds; i++) {
1373 unsigned r = ufds[curlfds + i].revents;
1374 unsigned short mask = 0;
1375#ifdef USE_WINSOCK
1376 curl_socket_t s = extra_fds[i].fd;
1377 wsa_events.lNetworkEvents = 0;
1378 if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
1379 if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1380 mask |= CURL_WAIT_POLLIN;
1381 if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1382 mask |= CURL_WAIT_POLLOUT;
1383 if(wsa_events.lNetworkEvents & FD_OOB)
1384 mask |= CURL_WAIT_POLLPRI;
1385 if(ret && !pollrc && wsa_events.lNetworkEvents)
1386 retcode++;
1387 }
1388 WSAEventSelect(s, multi->wsa_event, 0);
1389 if(!pollrc) {
1390 extra_fds[i].revents = mask;
1391 continue;
1392 }
1393#endif
1394 if(r & POLLIN)
1395 mask |= CURL_WAIT_POLLIN;
1396 if(r & POLLOUT)
1397 mask |= CURL_WAIT_POLLOUT;
1398 if(r & POLLPRI)
1399 mask |= CURL_WAIT_POLLPRI;
1400 extra_fds[i].revents = mask;
1401 }
1402
1403#ifdef USE_WINSOCK
1404 /* Count up all our own sockets that had activity,
1405 and remove them from the event. */
1406 if(curlfds) {
1407 data = multi->easyp;
1408 while(data) {
1409 bitmap = multi_getsock(data, sockbunch);
1410
1411 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1412 if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
1413 wsa_events.lNetworkEvents = 0;
1414 if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
1415 if(ret && !pollrc && wsa_events.lNetworkEvents)
1416 retcode++;
1417 }
1418 WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1419 }
1420 else {
1421 /* break on entry not checked for being readable or writable */
1422 break;
1423 }
1424 }
1425
1426 data = data->next;
1427 }
1428 }
1429
1430 WSAResetEvent(multi->wsa_event);
1431#else
1432#ifdef ENABLE_WAKEUP
1433 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1434 if(ufds[curlfds + extra_nfds].revents & POLLIN) {
1435 char buf[64];
1436 ssize_t nread;
1437 while(1) {
1438 /* the reading socket is non-blocking, try to read
1439 data from it until it receives an error (except EINTR).
1440 In normal cases it will get EAGAIN or EWOULDBLOCK
1441 when there is no more data, breaking the loop. */
1442 nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1443 if(nread <= 0) {
1444 if(nread < 0 && EINTR == SOCKERRNO)
1445 continue;
1446 break;
1447 }
1448 }
1449 /* do not count the wakeup socket into the returned value */
1450 retcode--;
1451 }
1452 }
1453#endif
1454#endif
1455 }
1456 }
1457
1458 if(ufds_malloc)
1459 free(ufds);
1460 if(ret)
1461 *ret = retcode;
1462#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1463 if(extrawait && !nfds && !use_wakeup) {
1464#else
1465 if(extrawait && !nfds) {
1466#endif
1467 long sleep_ms = 0;
1468
1469 /* Avoid busy-looping when there's nothing particular to wait for */
1470 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1471 if(sleep_ms > timeout_ms)
1472 sleep_ms = timeout_ms;
1473 /* when there are no easy handles in the multi, this holds a -1
1474 timeout */
1475 else if(sleep_ms < 0)
1476 sleep_ms = timeout_ms;
1477 Curl_wait_ms(sleep_ms);
1478 }
1479 }
1480
1481 return CURLM_OK;
1482}
1483
1484CURLMcode curl_multi_wait(struct Curl_multi *multi,
1485 struct curl_waitfd extra_fds[],
1486 unsigned int extra_nfds,
1487 int timeout_ms,
1488 int *ret)
1489{
1490 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1491 FALSE);
1492}
1493
1494CURLMcode curl_multi_poll(struct Curl_multi *multi,
1495 struct curl_waitfd extra_fds[],
1496 unsigned int extra_nfds,
1497 int timeout_ms,
1498 int *ret)
1499{
1500 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1501 TRUE);
1502}
1503
1504CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1505{
1506 /* this function is usually called from another thread,
1507 it has to be careful only to access parts of the
1508 Curl_multi struct that are constant */
1509
1510 /* GOOD_MULTI_HANDLE can be safely called */
1511 if(!GOOD_MULTI_HANDLE(multi))
1512 return CURLM_BAD_HANDLE;
1513
1514#ifdef ENABLE_WAKEUP
1515#ifdef USE_WINSOCK
1516 if(WSASetEvent(multi->wsa_event))
1517 return CURLM_OK;
1518#else
1519 /* the wakeup_pair variable is only written during init and cleanup,
1520 making it safe to access from another thread after the init part
1521 and before cleanup */
1522 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1523 char buf[1];
1524 buf[0] = 1;
1525 while(1) {
1526 /* swrite() is not thread-safe in general, because concurrent calls
1527 can have their messages interleaved, but in this case the content
1528 of the messages does not matter, which makes it ok to call.
1529
1530 The write socket is set to non-blocking, this way this function
1531 cannot block, making it safe to call even from the same thread
1532 that will call curl_multi_wait(). If swrite() returns that it
1533 would block, it's considered successful because it means that
1534 previous calls to this function will wake up the poll(). */
1535 if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1536 int err = SOCKERRNO;
1537 int return_success;
1538#ifdef USE_WINSOCK
1539 return_success = WSAEWOULDBLOCK == err;
1540#else
1541 if(EINTR == err)
1542 continue;
1543 return_success = EWOULDBLOCK == err || EAGAIN == err;
1544#endif
1545 if(!return_success)
1546 return CURLM_WAKEUP_FAILURE;
1547 }
1548 return CURLM_OK;
1549 }
1550 }
1551#endif
1552#endif
1553 return CURLM_WAKEUP_FAILURE;
1554}
1555
1556/*
1557 * multi_ischanged() is called
1558 *
1559 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1560 * => CONNECT action.
1561 *
1562 * Set 'clear' to TRUE to have it also clear the state variable.
1563 */
1564static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1565{
1566 bool retval = multi->recheckstate;
1567 if(clear)
1568 multi->recheckstate = FALSE;
1569 return retval;
1570}
1571
1572CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1573 struct Curl_easy *data,
1574 struct connectdata *conn)
1575{
1576 CURLMcode rc;
1577
1578 if(multi->in_callback)
1579 return CURLM_RECURSIVE_API_CALL;
1580
1581 rc = curl_multi_add_handle(multi, data);
1582 if(!rc) {
1583 struct SingleRequest *k = &data->req;
1584
1585 /* pass in NULL for 'conn' here since we don't want to init the
1586 connection, only this transfer */
1587 Curl_init_do(data, NULL);
1588
1589 /* take this handle to the perform state right away */
1590 multistate(data, MSTATE_PERFORMING);
1591 Curl_attach_connection(data, conn);
1592 k->keepon |= KEEP_RECV; /* setup to receive! */
1593 }
1594 return rc;
1595}
1596
1597static CURLcode multi_do(struct Curl_easy *data, bool *done)
1598{
1599 CURLcode result = CURLE_OK;
1600 struct connectdata *conn = data->conn;
1601
1602 DEBUGASSERT(conn);
1603 DEBUGASSERT(conn->handler);
1604
1605 if(conn->handler->do_it)
1606 /* generic protocol-specific function pointer set in curl_connect() */
1607 result = conn->handler->do_it(data, done);
1608
1609 return result;
1610}
1611
1612/*
1613 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1614 * second stage DO state which (wrongly) was introduced to support FTP's
1615 * second connection.
1616 *
1617 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1618 * DOING state there's more work to do!
1619 */
1620
1621static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1622{
1623 CURLcode result = CURLE_OK;
1624 struct connectdata *conn = data->conn;
1625
1626 *complete = 0;
1627
1628 if(conn->handler->do_more)
1629 result = conn->handler->do_more(data, complete);
1630
1631 return result;
1632}
1633
1634/*
1635 * Check whether a timeout occurred, and handle it if it did
1636 */
1637static bool multi_handle_timeout(struct Curl_easy *data,
1638 struct curltime *now,
1639 bool *stream_error,
1640 CURLcode *result,
1641 bool connect_timeout)
1642{
1643 timediff_t timeout_ms;
1644 timeout_ms = Curl_timeleft(data, now, connect_timeout);
1645
1646 if(timeout_ms < 0) {
1647 /* Handle timed out */
1648 if(data->mstate == MSTATE_RESOLVING)
1649 failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1650 " milliseconds",
1651 Curl_timediff(*now, data->progress.t_startsingle));
1652 else if(data->mstate == MSTATE_CONNECTING)
1653 failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1654 " milliseconds",
1655 Curl_timediff(*now, data->progress.t_startsingle));
1656 else {
1657 struct SingleRequest *k = &data->req;
1658 if(k->size != -1) {
1659 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1660 " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1661 CURL_FORMAT_CURL_OFF_T " bytes received",
1662 Curl_timediff(*now, data->progress.t_startsingle),
1663 k->bytecount, k->size);
1664 }
1665 else {
1666 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1667 " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1668 " bytes received",
1669 Curl_timediff(*now, data->progress.t_startsingle),
1670 k->bytecount);
1671 }
1672 }
1673
1674 /* Force connection closed if the connection has indeed been used */
1675 if(data->mstate > MSTATE_DO) {
1676 streamclose(data->conn, "Disconnected with pending data");
1677 *stream_error = TRUE;
1678 }
1679 *result = CURLE_OPERATION_TIMEDOUT;
1680 (void)multi_done(data, *result, TRUE);
1681 }
1682
1683 return (timeout_ms < 0);
1684}
1685
1686/*
1687 * We are doing protocol-specific connecting and this is being called over and
1688 * over from the multi interface until the connection phase is done on
1689 * protocol layer.
1690 */
1691
1692static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1693{
1694 CURLcode result = CURLE_OK;
1695 struct connectdata *conn = data->conn;
1696
1697 if(conn && conn->handler->connecting) {
1698 *done = FALSE;
1699 result = conn->handler->connecting(data, done);
1700 }
1701 else
1702 *done = TRUE;
1703
1704 return result;
1705}
1706
1707/*
1708 * We are DOING this is being called over and over from the multi interface
1709 * until the DOING phase is done on protocol layer.
1710 */
1711
1712static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1713{
1714 CURLcode result = CURLE_OK;
1715 struct connectdata *conn = data->conn;
1716
1717 if(conn && conn->handler->doing) {
1718 *done = FALSE;
1719 result = conn->handler->doing(data, done);
1720 }
1721 else
1722 *done = TRUE;
1723
1724 return result;
1725}
1726
1727/*
1728 * We have discovered that the TCP connection has been successful, we can now
1729 * proceed with some action.
1730 *
1731 */
1732static CURLcode protocol_connect(struct Curl_easy *data,
1733 bool *protocol_done)
1734{
1735 CURLcode result = CURLE_OK;
1736 struct connectdata *conn = data->conn;
1737 DEBUGASSERT(conn);
1738 DEBUGASSERT(protocol_done);
1739
1740 *protocol_done = FALSE;
1741
1742 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1743 /* We already are connected, get back. This may happen when the connect
1744 worked fine in the first call, like when we connect to a local server
1745 or proxy. Note that we don't know if the protocol is actually done.
1746
1747 Unless this protocol doesn't have any protocol-connect callback, as
1748 then we know we're done. */
1749 if(!conn->handler->connecting)
1750 *protocol_done = TRUE;
1751
1752 return CURLE_OK;
1753 }
1754
1755 if(!conn->bits.protoconnstart) {
1756#ifndef CURL_DISABLE_PROXY
1757 result = Curl_proxy_connect(data, FIRSTSOCKET);
1758 if(result)
1759 return result;
1760
1761 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1762 /* wait for HTTPS proxy SSL initialization to complete */
1763 return CURLE_OK;
1764
1765 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1766 Curl_connect_ongoing(conn))
1767 /* when using an HTTP tunnel proxy, await complete tunnel establishment
1768 before proceeding further. Return CURLE_OK so we'll be called again */
1769 return CURLE_OK;
1770#endif
1771 if(conn->handler->connect_it) {
1772 /* is there a protocol-specific connect() procedure? */
1773
1774 /* Call the protocol-specific connect function */
1775 result = conn->handler->connect_it(data, protocol_done);
1776 }
1777 else
1778 *protocol_done = TRUE;
1779
1780 /* it has started, possibly even completed but that knowledge isn't stored
1781 in this bit! */
1782 if(!result)
1783 conn->bits.protoconnstart = TRUE;
1784 }
1785
1786 return result; /* pass back status */
1787}
1788
1789/*
1790 * Curl_preconnect() is called immediately before a connect starts. When a
1791 * redirect is followed, this is then called multiple times during a single
1792 * transfer.
1793 */
1794CURLcode Curl_preconnect(struct Curl_easy *data)
1795{
1796 if(!data->state.buffer) {
1797 data->state.buffer = malloc(data->set.buffer_size + 1);
1798 if(!data->state.buffer)
1799 return CURLE_OUT_OF_MEMORY;
1800 }
1801 return CURLE_OK;
1802}
1803
1804static void set_in_callback(struct Curl_multi *multi, bool value)
1805{
1806 multi->in_callback = value;
1807}
1808
1809static CURLMcode multi_runsingle(struct Curl_multi *multi,
1810 struct curltime *nowp,
1811 struct Curl_easy *data)
1812{
1813 struct Curl_message *msg = NULL;
1814 bool connected;
1815 bool async;
1816 bool protocol_connected = FALSE;
1817 bool dophase_done = FALSE;
1818 bool done = FALSE;
1819 CURLMcode rc;
1820 CURLcode result = CURLE_OK;
1821 timediff_t recv_timeout_ms;
1822 timediff_t send_timeout_ms;
1823 int control;
1824
1825 if(!GOOD_EASY_HANDLE(data))
1826 return CURLM_BAD_EASY_HANDLE;
1827
1828 if(multi->dead) {
1829 /* a multi-level callback returned error before, meaning every individual
1830 transfer now has failed */
1831 result = CURLE_ABORTED_BY_CALLBACK;
1832 Curl_posttransfer(data);
1833 multi_done(data, result, FALSE);
1834 multistate(data, MSTATE_COMPLETED);
1835 }
1836
1837 do {
1838 /* A "stream" here is a logical stream if the protocol can handle that
1839 (HTTP/2), or the full connection for older protocols */
1840 bool stream_error = FALSE;
1841 rc = CURLM_OK;
1842
1843 if(multi_ischanged(multi, TRUE)) {
1844 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
1845 process_pending_handles(multi); /* multiplexed */
1846 }
1847
1848 if(data->mstate > MSTATE_CONNECT &&
1849 data->mstate < MSTATE_COMPLETED) {
1850 /* Make sure we set the connection's current owner */
1851 DEBUGASSERT(data->conn);
1852 if(!data->conn)
1853 return CURLM_INTERNAL_ERROR;
1854 }
1855
1856 if(data->conn &&
1857 (data->mstate >= MSTATE_CONNECT) &&
1858 (data->mstate < MSTATE_COMPLETED)) {
1859 /* Check for overall operation timeout here but defer handling the
1860 * connection timeout to later, to allow for a connection to be set up
1861 * in the window since we last checked timeout. This prevents us
1862 * tearing down a completed connection in the case where we were slow
1863 * to check the timeout (e.g. process descheduled during this loop).
1864 * We set connect_timeout=FALSE to do this. */
1865
1866 /* we need to wait for the connect state as only then is the start time
1867 stored, but we must not check already completed handles */
1868 if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
1869 /* Skip the statemachine and go directly to error handling section. */
1870 goto statemachine_end;
1871 }
1872 }
1873
1874 switch(data->mstate) {
1875 case MSTATE_INIT:
1876 /* init this transfer. */
1877 result = Curl_pretransfer(data);
1878
1879 if(!result) {
1880 /* after init, go CONNECT */
1881 multistate(data, MSTATE_CONNECT);
1882 *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
1883 rc = CURLM_CALL_MULTI_PERFORM;
1884 }
1885 break;
1886
1887 case MSTATE_PENDING:
1888 /* We will stay here until there is a connection available. Then
1889 we try again in the MSTATE_CONNECT state. */
1890 break;
1891
1892 case MSTATE_CONNECT:
1893 /* Connect. We want to get a connection identifier filled in. */
1894 /* init this transfer. */
1895 result = Curl_preconnect(data);
1896 if(result)
1897 break;
1898
1899 *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1900 if(data->set.timeout)
1901 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1902
1903 if(data->set.connecttimeout)
1904 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1905
1906 result = Curl_connect(data, &async, &protocol_connected);
1907 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1908 /* There was no connection available. We will go to the pending
1909 state and wait for an available connection. */
1910 multistate(data, MSTATE_PENDING);
1911
1912 /* add this handle to the list of connect-pending handles */
1913 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1914 &data->connect_queue);
1915 result = CURLE_OK;
1916 break;
1917 }
1918 else if(data->state.previouslypending) {
1919 /* this transfer comes from the pending queue so try move another */
1920 infof(data, "Transfer was pending, now try another");
1921 process_pending_handles(data->multi);
1922 }
1923
1924 if(!result) {
1925 if(async)
1926 /* We're now waiting for an asynchronous name lookup */
1927 multistate(data, MSTATE_RESOLVING);
1928 else {
1929 /* after the connect has been sent off, go WAITCONNECT unless the
1930 protocol connect is already done and we can go directly to
1931 WAITDO or DO! */
1932 rc = CURLM_CALL_MULTI_PERFORM;
1933
1934 if(protocol_connected)
1935 multistate(data, MSTATE_DO);
1936 else {
1937#ifndef CURL_DISABLE_HTTP
1938 if(Curl_connect_ongoing(data->conn))
1939 multistate(data, MSTATE_TUNNELING);
1940 else
1941#endif
1942 multistate(data, MSTATE_CONNECTING);
1943 }
1944 }
1945 }
1946 break;
1947
1948 case MSTATE_RESOLVING:
1949 /* awaiting an asynch name resolve to complete */
1950 {
1951 struct Curl_dns_entry *dns = NULL;
1952 struct connectdata *conn = data->conn;
1953 const char *hostname;
1954
1955 DEBUGASSERT(conn);
1956#ifndef CURL_DISABLE_PROXY
1957 if(conn->bits.httpproxy)
1958 hostname = conn->http_proxy.host.name;
1959 else
1960#endif
1961 if(conn->bits.conn_to_host)
1962 hostname = conn->conn_to_host.name;
1963 else
1964 hostname = conn->host.name;
1965
1966 /* check if we have the name resolved by now */
1967 dns = Curl_fetch_addr(data, hostname, (int)conn->port);
1968
1969 if(dns) {
1970#ifdef CURLRES_ASYNCH
1971 data->state.async.dns = dns;
1972 data->state.async.done = TRUE;
1973#endif
1974 result = CURLE_OK;
1975 infof(data, "Hostname '%s' was found in DNS cache", hostname);
1976 }
1977
1978 if(!dns)
1979 result = Curl_resolv_check(data, &dns);
1980
1981 /* Update sockets here, because the socket(s) may have been
1982 closed and the application thus needs to be told, even if it
1983 is likely that the same socket(s) will again be used further
1984 down. If the name has not yet been resolved, it is likely
1985 that new sockets have been opened in an attempt to contact
1986 another resolver. */
1987 rc = singlesocket(multi, data);
1988 if(rc)
1989 return rc;
1990
1991 if(dns) {
1992 /* Perform the next step in the connection phase, and then move on
1993 to the WAITCONNECT state */
1994 result = Curl_once_resolved(data, &protocol_connected);
1995
1996 if(result)
1997 /* if Curl_once_resolved() returns failure, the connection struct
1998 is already freed and gone */
1999 data->conn = NULL; /* no more connection */
2000 else {
2001 /* call again please so that we get the next socket setup */
2002 rc = CURLM_CALL_MULTI_PERFORM;
2003 if(protocol_connected)
2004 multistate(data, MSTATE_DO);
2005 else {
2006#ifndef CURL_DISABLE_HTTP
2007 if(Curl_connect_ongoing(data->conn))
2008 multistate(data, MSTATE_TUNNELING);
2009 else
2010#endif
2011 multistate(data, MSTATE_CONNECTING);
2012 }
2013 }
2014 }
2015
2016 if(result) {
2017 /* failure detected */
2018 stream_error = TRUE;
2019 break;
2020 }
2021 }
2022 break;
2023
2024#ifndef CURL_DISABLE_HTTP
2025 case MSTATE_TUNNELING:
2026 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
2027 DEBUGASSERT(data->conn);
2028 result = Curl_http_connect(data, &protocol_connected);
2029#ifndef CURL_DISABLE_PROXY
2030 if(data->conn->bits.proxy_connect_closed) {
2031 rc = CURLM_CALL_MULTI_PERFORM;
2032 /* connect back to proxy again */
2033 result = CURLE_OK;
2034 multi_done(data, CURLE_OK, FALSE);
2035 multistate(data, MSTATE_CONNECT);
2036 }
2037 else
2038#endif
2039 if(!result) {
2040 if(
2041#ifndef CURL_DISABLE_PROXY
2042 (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
2043 data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
2044#endif
2045 Curl_connect_complete(data->conn)) {
2046 rc = CURLM_CALL_MULTI_PERFORM;
2047 /* initiate protocol connect phase */
2048 multistate(data, MSTATE_PROTOCONNECT);
2049 }
2050 }
2051 else
2052 stream_error = TRUE;
2053 break;
2054#endif
2055
2056 case MSTATE_CONNECTING:
2057 /* awaiting a completion of an asynch TCP connect */
2058 DEBUGASSERT(data->conn);
2059 result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
2060 if(connected && !result) {
2061#ifndef CURL_DISABLE_HTTP
2062 if(
2063#ifndef CURL_DISABLE_PROXY
2064 (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
2065 !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
2066#endif
2067 Curl_connect_ongoing(data->conn)) {
2068 multistate(data, MSTATE_TUNNELING);
2069 break;
2070 }
2071#endif
2072 rc = CURLM_CALL_MULTI_PERFORM;
2073#ifndef CURL_DISABLE_PROXY
2074 multistate(data,
2075 data->conn->bits.tunnel_proxy?
2076 MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
2077#else
2078 multistate(data, MSTATE_PROTOCONNECT);
2079#endif
2080 }
2081 else if(result) {
2082 /* failure detected */
2083 Curl_posttransfer(data);
2084 multi_done(data, result, TRUE);
2085 stream_error = TRUE;
2086 break;
2087 }
2088 break;
2089
2090 case MSTATE_PROTOCONNECT:
2091 result = protocol_connect(data, &protocol_connected);
2092 if(!result && !protocol_connected)
2093 /* switch to waiting state */
2094 multistate(data, MSTATE_PROTOCONNECTING);
2095 else if(!result) {
2096 /* protocol connect has completed, go WAITDO or DO */
2097 multistate(data, MSTATE_DO);
2098 rc = CURLM_CALL_MULTI_PERFORM;
2099 }
2100 else {
2101 /* failure detected */
2102 Curl_posttransfer(data);
2103 multi_done(data, result, TRUE);
2104 stream_error = TRUE;
2105 }
2106 break;
2107
2108 case MSTATE_PROTOCONNECTING:
2109 /* protocol-specific connect phase */
2110 result = protocol_connecting(data, &protocol_connected);
2111 if(!result && protocol_connected) {
2112 /* after the connect has completed, go WAITDO or DO */
2113 multistate(data, MSTATE_DO);
2114 rc = CURLM_CALL_MULTI_PERFORM;
2115 }
2116 else if(result) {
2117 /* failure detected */
2118 Curl_posttransfer(data);
2119 multi_done(data, result, TRUE);
2120 stream_error = TRUE;
2121 }
2122 break;
2123
2124 case MSTATE_DO:
2125 if(data->set.fprereq) {
2126 int prereq_rc;
2127
2128 /* call the prerequest callback function */
2129 Curl_set_in_callback(data, true);
2130 prereq_rc = data->set.fprereq(data->set.prereq_userp,
2131 data->info.conn_primary_ip,
2132 data->info.conn_local_ip,
2133 data->info.conn_primary_port,
2134 data->info.conn_local_port);
2135 Curl_set_in_callback(data, false);
2136 if(prereq_rc != CURL_PREREQFUNC_OK) {
2137 failf(data, "operation aborted by pre-request callback");
2138 /* failure in pre-request callback - don't do any other processing */
2139 result = CURLE_ABORTED_BY_CALLBACK;
2140 Curl_posttransfer(data);
2141 multi_done(data, result, FALSE);
2142 stream_error = TRUE;
2143 break;
2144 }
2145 }
2146
2147 if(data->set.connect_only) {
2148 /* keep connection open for application to use the socket */
2149 connkeep(data->conn, "CONNECT_ONLY");
2150 multistate(data, MSTATE_DONE);
2151 result = CURLE_OK;
2152 rc = CURLM_CALL_MULTI_PERFORM;
2153 }
2154 else {
2155 /* Perform the protocol's DO action */
2156 result = multi_do(data, &dophase_done);
2157
2158 /* When multi_do() returns failure, data->conn might be NULL! */
2159
2160 if(!result) {
2161 if(!dophase_done) {
2162#ifndef CURL_DISABLE_FTP
2163 /* some steps needed for wildcard matching */
2164 if(data->state.wildcardmatch) {
2165 struct WildcardData *wc = &data->wildcard;
2166 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2167 /* skip some states if it is important */
2168 multi_done(data, CURLE_OK, FALSE);
2169
2170 /* if there's no connection left, skip the DONE state */
2171 multistate(data, data->conn ?
2172 MSTATE_DONE : MSTATE_COMPLETED);
2173 rc = CURLM_CALL_MULTI_PERFORM;
2174 break;
2175 }
2176 }
2177#endif
2178 /* DO was not completed in one function call, we must continue
2179 DOING... */
2180 multistate(data, MSTATE_DOING);
2181 rc = CURLM_OK;
2182 }
2183
2184 /* after DO, go DO_DONE... or DO_MORE */
2185 else if(data->conn->bits.do_more) {
2186 /* we're supposed to do more, but we need to sit down, relax
2187 and wait a little while first */
2188 multistate(data, MSTATE_DOING_MORE);
2189 rc = CURLM_OK;
2190 }
2191 else {
2192 /* we're done with the DO, now DID */
2193 multistate(data, MSTATE_DID);
2194 rc = CURLM_CALL_MULTI_PERFORM;
2195 }
2196 }
2197 else if((CURLE_SEND_ERROR == result) &&
2198 data->conn->bits.reuse) {
2199 /*
2200 * In this situation, a connection that we were trying to use
2201 * may have unexpectedly died. If possible, send the connection
2202 * back to the CONNECT phase so we can try again.
2203 */
2204 char *newurl = NULL;
2205 followtype follow = FOLLOW_NONE;
2206 CURLcode drc;
2207
2208 drc = Curl_retry_request(data, &newurl);
2209 if(drc) {
2210 /* a failure here pretty much implies an out of memory */
2211 result = drc;
2212 stream_error = TRUE;
2213 }
2214
2215 Curl_posttransfer(data);
2216 drc = multi_done(data, result, FALSE);
2217
2218 /* When set to retry the connection, we must go back to the CONNECT
2219 * state */
2220 if(newurl) {
2221 if(!drc || (drc == CURLE_SEND_ERROR)) {
2222 follow = FOLLOW_RETRY;
2223 drc = Curl_follow(data, newurl, follow);
2224 if(!drc) {
2225 multistate(data, MSTATE_CONNECT);
2226 rc = CURLM_CALL_MULTI_PERFORM;
2227 result = CURLE_OK;
2228 }
2229 else {
2230 /* Follow failed */
2231 result = drc;
2232 }
2233 }
2234 else {
2235 /* done didn't return OK or SEND_ERROR */
2236 result = drc;
2237 }
2238 }
2239 else {
2240 /* Have error handler disconnect conn if we can't retry */
2241 stream_error = TRUE;
2242 }
2243 free(newurl);
2244 }
2245 else {
2246 /* failure detected */
2247 Curl_posttransfer(data);
2248 if(data->conn)
2249 multi_done(data, result, FALSE);
2250 stream_error = TRUE;
2251 }
2252 }
2253 break;
2254
2255 case MSTATE_DOING:
2256 /* we continue DOING until the DO phase is complete */
2257 DEBUGASSERT(data->conn);
2258 result = protocol_doing(data, &dophase_done);
2259 if(!result) {
2260 if(dophase_done) {
2261 /* after DO, go DO_DONE or DO_MORE */
2262 multistate(data, data->conn->bits.do_more?
2263 MSTATE_DOING_MORE : MSTATE_DID);
2264 rc = CURLM_CALL_MULTI_PERFORM;
2265 } /* dophase_done */
2266 }
2267 else {
2268 /* failure detected */
2269 Curl_posttransfer(data);
2270 multi_done(data, result, FALSE);
2271 stream_error = TRUE;
2272 }
2273 break;
2274
2275 case MSTATE_DOING_MORE:
2276 /*
2277 * When we are connected, DOING MORE and then go DID
2278 */
2279 DEBUGASSERT(data->conn);
2280 result = multi_do_more(data, &control);
2281
2282 if(!result) {
2283 if(control) {
2284 /* if positive, advance to DO_DONE
2285 if negative, go back to DOING */
2286 multistate(data, control == 1?
2287 MSTATE_DID : MSTATE_DOING);
2288 rc = CURLM_CALL_MULTI_PERFORM;
2289 }
2290 else
2291 /* stay in DO_MORE */
2292 rc = CURLM_OK;
2293 }
2294 else {
2295 /* failure detected */
2296 Curl_posttransfer(data);
2297 multi_done(data, result, FALSE);
2298 stream_error = TRUE;
2299 }
2300 break;
2301
2302 case MSTATE_DID:
2303 DEBUGASSERT(data->conn);
2304 if(data->conn->bits.multiplex)
2305 /* Check if we can move pending requests to send pipe */
2306 process_pending_handles(multi); /* multiplexed */
2307
2308 /* Only perform the transfer if there's a good socket to work with.
2309 Having both BAD is a signal to skip immediately to DONE */
2310 if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2311 (data->conn->writesockfd != CURL_SOCKET_BAD))
2312 multistate(data, MSTATE_PERFORMING);
2313 else {
2314#ifndef CURL_DISABLE_FTP
2315 if(data->state.wildcardmatch &&
2316 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2317 data->wildcard.state = CURLWC_DONE;
2318 }
2319#endif
2320 multistate(data, MSTATE_DONE);
2321 }
2322 rc = CURLM_CALL_MULTI_PERFORM;
2323 break;
2324
2325 case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2326 DEBUGASSERT(data->conn);
2327 /* if both rates are within spec, resume transfer */
2328 if(Curl_pgrsUpdate(data))
2329 result = CURLE_ABORTED_BY_CALLBACK;
2330 else
2331 result = Curl_speedcheck(data, *nowp);
2332
2333 if(result) {
2334 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2335 result != CURLE_HTTP2_STREAM)
2336 streamclose(data->conn, "Transfer returned error");
2337
2338 Curl_posttransfer(data);
2339 multi_done(data, result, TRUE);
2340 }
2341 else {
2342 send_timeout_ms = 0;
2343 if(data->set.max_send_speed)
2344 send_timeout_ms =
2345 Curl_pgrsLimitWaitTime(data->progress.uploaded,
2346 data->progress.ul_limit_size,
2347 data->set.max_send_speed,
2348 data->progress.ul_limit_start,
2349 *nowp);
2350
2351 recv_timeout_ms = 0;
2352 if(data->set.max_recv_speed)
2353 recv_timeout_ms =
2354 Curl_pgrsLimitWaitTime(data->progress.downloaded,
2355 data->progress.dl_limit_size,
2356 data->set.max_recv_speed,
2357 data->progress.dl_limit_start,
2358 *nowp);
2359
2360 if(!send_timeout_ms && !recv_timeout_ms) {
2361 multistate(data, MSTATE_PERFORMING);
2362 Curl_ratelimit(data, *nowp);
2363 }
2364 else if(send_timeout_ms >= recv_timeout_ms)
2365 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2366 else
2367 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2368 }
2369 break;
2370
2371 case MSTATE_PERFORMING:
2372 {
2373 char *newurl = NULL;
2374 bool retry = FALSE;
2375 bool comeback = FALSE;
2376 DEBUGASSERT(data->state.buffer);
2377 /* check if over send speed */
2378 send_timeout_ms = 0;
2379 if(data->set.max_send_speed)
2380 send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2381 data->progress.ul_limit_size,
2382 data->set.max_send_speed,
2383 data->progress.ul_limit_start,
2384 *nowp);
2385
2386 /* check if over recv speed */
2387 recv_timeout_ms = 0;
2388 if(data->set.max_recv_speed)
2389 recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2390 data->progress.dl_limit_size,
2391 data->set.max_recv_speed,
2392 data->progress.dl_limit_start,
2393 *nowp);
2394
2395 if(send_timeout_ms || recv_timeout_ms) {
2396 Curl_ratelimit(data, *nowp);
2397 multistate(data, MSTATE_RATELIMITING);
2398 if(send_timeout_ms >= recv_timeout_ms)
2399 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2400 else
2401 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2402 break;
2403 }
2404
2405 /* read/write data if it is ready to do so */
2406 result = Curl_readwrite(data->conn, data, &done, &comeback);
2407
2408 if(done || (result == CURLE_RECV_ERROR)) {
2409 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2410 * condition and the server closed the re-used connection exactly when
2411 * we wanted to use it, so figure out if that is indeed the case.
2412 */
2413 CURLcode ret = Curl_retry_request(data, &newurl);
2414 if(!ret)
2415 retry = (newurl)?TRUE:FALSE;
2416 else if(!result)
2417 result = ret;
2418
2419 if(retry) {
2420 /* if we are to retry, set the result to OK and consider the
2421 request as done */
2422 result = CURLE_OK;
2423 done = TRUE;
2424 }
2425 }
2426 else if((CURLE_HTTP2_STREAM == result) &&
2427 Curl_h2_http_1_1_error(data)) {
2428 CURLcode ret = Curl_retry_request(data, &newurl);
2429
2430 if(!ret) {
2431 infof(data, "Downgrades to HTTP/1.1");
2432 streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2433 data->state.httpwant = CURL_HTTP_VERSION_1_1;
2434 /* clear the error message bit too as we ignore the one we got */
2435 data->state.errorbuf = FALSE;
2436 if(!newurl)
2437 /* typically for HTTP_1_1_REQUIRED error on first flight */
2438 newurl = strdup(data->state.url);
2439 /* if we are to retry, set the result to OK and consider the request
2440 as done */
2441 retry = TRUE;
2442 result = CURLE_OK;
2443 done = TRUE;
2444 }
2445 else
2446 result = ret;
2447 }
2448
2449 if(result) {
2450 /*
2451 * The transfer phase returned error, we mark the connection to get
2452 * closed to prevent being re-used. This is because we can't possibly
2453 * know if the connection is in a good shape or not now. Unless it is
2454 * a protocol which uses two "channels" like FTP, as then the error
2455 * happened in the data connection.
2456 */
2457
2458 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2459 result != CURLE_HTTP2_STREAM)
2460 streamclose(data->conn, "Transfer returned error");
2461
2462 Curl_posttransfer(data);
2463 multi_done(data, result, TRUE);
2464 }
2465 else if(done) {
2466
2467 /* call this even if the readwrite function returned error */
2468 Curl_posttransfer(data);
2469
2470 /* When we follow redirects or is set to retry the connection, we must
2471 to go back to the CONNECT state */
2472 if(data->req.newurl || retry) {
2473 followtype follow = FOLLOW_NONE;
2474 if(!retry) {
2475 /* if the URL is a follow-location and not just a retried request
2476 then figure out the URL here */
2477 free(newurl);
2478 newurl = data->req.newurl;
2479 data->req.newurl = NULL;
2480 follow = FOLLOW_REDIR;
2481 }
2482 else
2483 follow = FOLLOW_RETRY;
2484 (void)multi_done(data, CURLE_OK, FALSE);
2485 /* multi_done() might return CURLE_GOT_NOTHING */
2486 result = Curl_follow(data, newurl, follow);
2487 if(!result) {
2488 multistate(data, MSTATE_CONNECT);
2489 rc = CURLM_CALL_MULTI_PERFORM;
2490 }
2491 free(newurl);
2492 }
2493 else {
2494 /* after the transfer is done, go DONE */
2495
2496 /* but first check to see if we got a location info even though we're
2497 not following redirects */
2498 if(data->req.location) {
2499 free(newurl);
2500 newurl = data->req.location;
2501 data->req.location = NULL;
2502 result = Curl_follow(data, newurl, FOLLOW_FAKE);
2503 free(newurl);
2504 if(result) {
2505 stream_error = TRUE;
2506 result = multi_done(data, result, TRUE);
2507 }
2508 }
2509
2510 if(!result) {
2511 multistate(data, MSTATE_DONE);
2512 rc = CURLM_CALL_MULTI_PERFORM;
2513 }
2514 }
2515 }
2516 else if(comeback) {
2517 /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2518 won't get stuck on this transfer at the expense of other concurrent
2519 transfers */
2520 Curl_expire(data, 0, EXPIRE_RUN_NOW);
2521 rc = CURLM_OK;
2522 }
2523 break;
2524 }
2525
2526 case MSTATE_DONE:
2527 /* this state is highly transient, so run another loop after this */
2528 rc = CURLM_CALL_MULTI_PERFORM;
2529
2530 if(data->conn) {
2531 CURLcode res;
2532
2533 if(data->conn->bits.multiplex)
2534 /* Check if we can move pending requests to connection */
2535 process_pending_handles(multi); /* multiplexing */
2536
2537 /* post-transfer command */
2538 res = multi_done(data, result, FALSE);
2539
2540 /* allow a previously set error code take precedence */
2541 if(!result)
2542 result = res;
2543 }
2544
2545#ifndef CURL_DISABLE_FTP
2546 if(data->state.wildcardmatch) {
2547 if(data->wildcard.state != CURLWC_DONE) {
2548 /* if a wildcard is set and we are not ending -> lets start again
2549 with MSTATE_INIT */
2550 multistate(data, MSTATE_INIT);
2551 break;
2552 }
2553 }
2554#endif
2555 /* after we have DONE what we're supposed to do, go COMPLETED, and
2556 it doesn't matter what the multi_done() returned! */
2557 multistate(data, MSTATE_COMPLETED);
2558 break;
2559
2560 case MSTATE_COMPLETED:
2561 break;
2562
2563 case MSTATE_MSGSENT:
2564 data->result = result;
2565 return CURLM_OK; /* do nothing */
2566
2567 default:
2568 return CURLM_INTERNAL_ERROR;
2569 }
2570
2571 if(data->conn &&
2572 data->mstate >= MSTATE_CONNECT &&
2573 data->mstate < MSTATE_DO &&
2574 rc != CURLM_CALL_MULTI_PERFORM &&
2575 !multi_ischanged(multi, false)) {
2576 /* We now handle stream timeouts if and only if this will be the last
2577 * loop iteration. We only check this on the last iteration to ensure
2578 * that if we know we have additional work to do immediately
2579 * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2580 * declaring the connection timed out as we may almost have a completed
2581 * connection. */
2582 multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
2583 }
2584
2585 statemachine_end:
2586
2587 if(data->mstate < MSTATE_COMPLETED) {
2588 if(result) {
2589 /*
2590 * If an error was returned, and we aren't in completed state now,
2591 * then we go to completed and consider this transfer aborted.
2592 */
2593
2594 /* NOTE: no attempt to disconnect connections must be made
2595 in the case blocks above - cleanup happens only here */
2596
2597 /* Check if we can move pending requests to send pipe */
2598 process_pending_handles(multi); /* connection */
2599
2600 if(data->conn) {
2601 if(stream_error) {
2602 /* Don't attempt to send data over a connection that timed out */
2603 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2604 struct connectdata *conn = data->conn;
2605
2606 /* This is where we make sure that the conn pointer is reset.
2607 We don't have to do this in every case block above where a
2608 failure is detected */
2609 Curl_detach_connection(data);
2610
2611 /* remove connection from cache */
2612 Curl_conncache_remove_conn(data, conn, TRUE);
2613
2614 /* disconnect properly */
2615 Curl_disconnect(data, conn, dead_connection);
2616 }
2617 }
2618 else if(data->mstate == MSTATE_CONNECT) {
2619 /* Curl_connect() failed */
2620 (void)Curl_posttransfer(data);
2621 }
2622
2623 multistate(data, MSTATE_COMPLETED);
2624 rc = CURLM_CALL_MULTI_PERFORM;
2625 }
2626 /* if there's still a connection to use, call the progress function */
2627 else if(data->conn && Curl_pgrsUpdate(data)) {
2628 /* aborted due to progress callback return code must close the
2629 connection */
2630 result = CURLE_ABORTED_BY_CALLBACK;
2631 streamclose(data->conn, "Aborted by callback");
2632
2633 /* if not yet in DONE state, go there, otherwise COMPLETED */
2634 multistate(data, (data->mstate < MSTATE_DONE)?
2635 MSTATE_DONE: MSTATE_COMPLETED);
2636 rc = CURLM_CALL_MULTI_PERFORM;
2637 }
2638 }
2639
2640 if(MSTATE_COMPLETED == data->mstate) {
2641 if(data->set.fmultidone) {
2642 /* signal via callback instead */
2643 data->set.fmultidone(data, result);
2644 }
2645 else {
2646 /* now fill in the Curl_message with this info */
2647 msg = &data->msg;
2648
2649 msg->extmsg.msg = CURLMSG_DONE;
2650 msg->extmsg.easy_handle = data;
2651 msg->extmsg.data.result = result;
2652
2653 rc = multi_addmsg(multi, msg);
2654 DEBUGASSERT(!data->conn);
2655 }
2656 multistate(data, MSTATE_MSGSENT);
2657 }
2658 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2659
2660 data->result = result;
2661 return rc;
2662}
2663
2664
2665CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2666{
2667 struct Curl_easy *data;
2668 CURLMcode returncode = CURLM_OK;
2669 struct Curl_tree *t;
2670 struct curltime now = Curl_now();
2671
2672 if(!GOOD_MULTI_HANDLE(multi))
2673 return CURLM_BAD_HANDLE;
2674
2675 if(multi->in_callback)
2676 return CURLM_RECURSIVE_API_CALL;
2677
2678 data = multi->easyp;
2679 while(data) {
2680 CURLMcode result;
2681 SIGPIPE_VARIABLE(pipe_st);
2682
2683 sigpipe_ignore(data, &pipe_st);
2684 result = multi_runsingle(multi, &now, data);
2685 sigpipe_restore(&pipe_st);
2686
2687 if(result)
2688 returncode = result;
2689
2690 data = data->next; /* operate on next handle */
2691 }
2692
2693 /*
2694 * Simply remove all expired timers from the splay since handles are dealt
2695 * with unconditionally by this function and curl_multi_timeout() requires
2696 * that already passed/handled expire times are removed from the splay.
2697 *
2698 * It is important that the 'now' value is set at the entry of this function
2699 * and not for the current time as it may have ticked a little while since
2700 * then and then we risk this loop to remove timers that actually have not
2701 * been handled!
2702 */
2703 do {
2704 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2705 if(t)
2706 /* the removed may have another timeout in queue */
2707 (void)add_next_timeout(now, multi, t->payload);
2708
2709 } while(t);
2710
2711 *running_handles = multi->num_alive;
2712
2713 if(CURLM_OK >= returncode)
2714 returncode = Curl_update_timer(multi);
2715
2716 return returncode;
2717}
2718
2719CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2720{
2721 struct Curl_easy *data;
2722 struct Curl_easy *nextdata;
2723
2724 if(GOOD_MULTI_HANDLE(multi)) {
2725 if(multi->in_callback)
2726 return CURLM_RECURSIVE_API_CALL;
2727
2728 multi->magic = 0; /* not good anymore */
2729
2730 /* First remove all remaining easy handles */
2731 data = multi->easyp;
2732 while(data) {
2733 nextdata = data->next;
2734 if(!data->state.done && data->conn)
2735 /* if DONE was never called for this handle */
2736 (void)multi_done(data, CURLE_OK, TRUE);
2737 if(data->dns.hostcachetype == HCACHE_MULTI) {
2738 /* clear out the usage of the shared DNS cache */
2739 Curl_hostcache_clean(data, data->dns.hostcache);
2740 data->dns.hostcache = NULL;
2741 data->dns.hostcachetype = HCACHE_NONE;
2742 }
2743
2744 /* Clear the pointer to the connection cache */
2745 data->state.conn_cache = NULL;
2746 data->multi = NULL; /* clear the association */
2747
2748#ifdef USE_LIBPSL
2749 if(data->psl == &multi->psl)
2750 data->psl = NULL;
2751#endif
2752
2753 data = nextdata;
2754 }
2755
2756 /* Close all the connections in the connection cache */
2757 Curl_conncache_close_all_connections(&multi->conn_cache);
2758
2759 sockhash_destroy(&multi->sockhash);
2760 Curl_conncache_destroy(&multi->conn_cache);
2761 Curl_llist_destroy(&multi->msglist, NULL);
2762 Curl_llist_destroy(&multi->pending, NULL);
2763
2764 Curl_hash_destroy(&multi->hostcache);
2765 Curl_psl_destroy(&multi->psl);
2766
2767#ifdef USE_WINSOCK
2768 WSACloseEvent(multi->wsa_event);
2769#else
2770#ifdef ENABLE_WAKEUP
2771 wakeup_close(multi->wakeup_pair[0]);
2772 wakeup_close(multi->wakeup_pair[1]);
2773#endif
2774#endif
2775 free(multi);
2776
2777 return CURLM_OK;
2778 }
2779 return CURLM_BAD_HANDLE;
2780}
2781
2782/*
2783 * curl_multi_info_read()
2784 *
2785 * This function is the primary way for a multi/multi_socket application to
2786 * figure out if a transfer has ended. We MUST make this function as fast as
2787 * possible as it will be polled frequently and we MUST NOT scan any lists in
2788 * here to figure out things. We must scale fine to thousands of handles and
2789 * beyond. The current design is fully O(1).
2790 */
2791
2792CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2793{
2794 struct Curl_message *msg;
2795
2796 *msgs_in_queue = 0; /* default to none */
2797
2798 if(GOOD_MULTI_HANDLE(multi) &&
2799 !multi->in_callback &&
2800 Curl_llist_count(&multi->msglist)) {
2801 /* there is one or more messages in the list */
2802 struct Curl_llist_element *e;
2803
2804 /* extract the head of the list to return */
2805 e = multi->msglist.head;
2806
2807 msg = e->ptr;
2808
2809 /* remove the extracted entry */
2810 Curl_llist_remove(&multi->msglist, e, NULL);
2811
2812 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2813
2814 return &msg->extmsg;
2815 }
2816 return NULL;
2817}
2818
2819/*
2820 * singlesocket() checks what sockets we deal with and their "action state"
2821 * and if we have a different state in any of those sockets from last time we
2822 * call the callback accordingly.
2823 */
2824static CURLMcode singlesocket(struct Curl_multi *multi,
2825 struct Curl_easy *data)
2826{
2827 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
2828 int i;
2829 struct Curl_sh_entry *entry;
2830 curl_socket_t s;
2831 int num;
2832 unsigned int curraction;
2833 unsigned char actions[MAX_SOCKSPEREASYHANDLE];
2834 int rc;
2835
2836 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
2837 socks[i] = CURL_SOCKET_BAD;
2838
2839 /* Fill in the 'current' struct with the state as it is now: what sockets to
2840 supervise and for what actions */
2841 curraction = multi_getsock(data, socks);
2842
2843 /* We have 0 .. N sockets already and we get to know about the 0 .. M
2844 sockets we should have from now on. Detect the differences, remove no
2845 longer supervised ones and add new ones */
2846
2847 /* walk over the sockets we got right now */
2848 for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
2849 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2850 i++) {
2851 unsigned char action = CURL_POLL_NONE;
2852 unsigned char prevaction = 0;
2853 int comboaction;
2854 bool sincebefore = FALSE;
2855
2856 s = socks[i];
2857
2858 /* get it from the hash */
2859 entry = sh_getentry(&multi->sockhash, s);
2860
2861 if(curraction & GETSOCK_READSOCK(i))
2862 action |= CURL_POLL_IN;
2863 if(curraction & GETSOCK_WRITESOCK(i))
2864 action |= CURL_POLL_OUT;
2865
2866 actions[i] = action;
2867 if(entry) {
2868 /* check if new for this transfer */
2869 int j;
2870 for(j = 0; j< data->numsocks; j++) {
2871 if(s == data->sockets[j]) {
2872 prevaction = data->actions[j];
2873 sincebefore = TRUE;
2874 break;
2875 }
2876 }
2877 }
2878 else {
2879 /* this is a socket we didn't have before, add it to the hash! */
2880 entry = sh_addentry(&multi->sockhash, s);
2881 if(!entry)
2882 /* fatal */
2883 return CURLM_OUT_OF_MEMORY;
2884 }
2885 if(sincebefore && (prevaction != action)) {
2886 /* Socket was used already, but different action now */
2887 if(prevaction & CURL_POLL_IN)
2888 entry->readers--;
2889 if(prevaction & CURL_POLL_OUT)
2890 entry->writers--;
2891 if(action & CURL_POLL_IN)
2892 entry->readers++;
2893 if(action & CURL_POLL_OUT)
2894 entry->writers++;
2895 }
2896 else if(!sincebefore) {
2897 /* a new user */
2898 entry->users++;
2899 if(action & CURL_POLL_IN)
2900 entry->readers++;
2901 if(action & CURL_POLL_OUT)
2902 entry->writers++;
2903
2904 /* add 'data' to the transfer hash on this socket! */
2905 if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2906 sizeof(struct Curl_easy *), data)) {
2907 Curl_hash_destroy(&entry->transfers);
2908 return CURLM_OUT_OF_MEMORY;
2909 }
2910 }
2911
2912 comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2913 (entry->readers ? CURL_POLL_IN : 0);
2914
2915 /* socket existed before and has the same action set as before */
2916 if(sincebefore && ((int)entry->action == comboaction))
2917 /* same, continue */
2918 continue;
2919
2920 if(multi->socket_cb) {
2921 set_in_callback(multi, TRUE);
2922 rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
2923 entry->socketp);
2924 set_in_callback(multi, FALSE);
2925 if(rc == -1) {
2926 multi->dead = TRUE;
2927 return CURLM_ABORTED_BY_CALLBACK;
2928 }
2929 }
2930
2931 entry->action = comboaction; /* store the current action state */
2932 }
2933
2934 num = i; /* number of sockets */
2935
2936 /* when we've walked over all the sockets we should have right now, we must
2937 make sure to detect sockets that are removed */
2938 for(i = 0; i< data->numsocks; i++) {
2939 int j;
2940 bool stillused = FALSE;
2941 s = data->sockets[i];
2942 for(j = 0; j < num; j++) {
2943 if(s == socks[j]) {
2944 /* this is still supervised */
2945 stillused = TRUE;
2946 break;
2947 }
2948 }
2949 if(stillused)
2950 continue;
2951
2952 entry = sh_getentry(&multi->sockhash, s);
2953 /* if this is NULL here, the socket has been closed and notified so
2954 already by Curl_multi_closed() */
2955 if(entry) {
2956 unsigned char oldactions = data->actions[i];
2957 /* this socket has been removed. Decrease user count */
2958 entry->users--;
2959 if(oldactions & CURL_POLL_OUT)
2960 entry->writers--;
2961 if(oldactions & CURL_POLL_IN)
2962 entry->readers--;
2963 if(!entry->users) {
2964 if(multi->socket_cb) {
2965 set_in_callback(multi, TRUE);
2966 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
2967 multi->socket_userp, entry->socketp);
2968 set_in_callback(multi, FALSE);
2969 if(rc == -1) {
2970 multi->dead = TRUE;
2971 return CURLM_ABORTED_BY_CALLBACK;
2972 }
2973 }
2974 sh_delentry(entry, &multi->sockhash, s);
2975 }
2976 else {
2977 /* still users, but remove this handle as a user of this socket */
2978 if(Curl_hash_delete(&entry->transfers, (char *)&data,
2979 sizeof(struct Curl_easy *))) {
2980 DEBUGASSERT(NULL);
2981 }
2982 }
2983 }
2984 } /* for loop over numsocks */
2985
2986 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2987 memcpy(data->actions, actions, num*sizeof(char));
2988 data->numsocks = num;
2989 return CURLM_OK;
2990}
2991
2992CURLcode Curl_updatesocket(struct Curl_easy *data)
2993{
2994 if(singlesocket(data->multi, data))
2995 return CURLE_ABORTED_BY_CALLBACK;
2996 return CURLE_OK;
2997}
2998
2999
3000/*
3001 * Curl_multi_closed()
3002 *
3003 * Used by the connect code to tell the multi_socket code that one of the
3004 * sockets we were using is about to be closed. This function will then
3005 * remove it from the sockethash for this handle to make the multi_socket API
3006 * behave properly, especially for the case when libcurl will create another
3007 * socket again and it gets the same file descriptor number.
3008 */
3009
3010void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
3011{
3012 if(data) {
3013 /* if there's still an easy handle associated with this connection */
3014 struct Curl_multi *multi = data->multi;
3015 if(multi) {
3016 /* this is set if this connection is part of a handle that is added to
3017 a multi handle, and only then this is necessary */
3018 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3019
3020 if(entry) {
3021 int rc = 0;
3022 if(multi->socket_cb) {
3023 set_in_callback(multi, TRUE);
3024 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3025 multi->socket_userp, entry->socketp);
3026 set_in_callback(multi, FALSE);
3027 }
3028
3029 /* now remove it from the socket hash */
3030 sh_delentry(entry, &multi->sockhash, s);
3031 if(rc == -1)
3032 /* This just marks the multi handle as "dead" without returning an
3033 error code primarily because this function is used from many
3034 places where propagating an error back is tricky. */
3035 multi->dead = TRUE;
3036 }
3037 }
3038 }
3039}
3040
3041/*
3042 * add_next_timeout()
3043 *
3044 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
3045 * when it has just been removed from the splay tree because the timeout has
3046 * expired. This function is then to advance in the list to pick the next
3047 * timeout to use (skip the already expired ones) and add this node back to
3048 * the splay tree again.
3049 *
3050 * The splay tree only has each sessionhandle as a single node and the nearest
3051 * timeout is used to sort it on.
3052 */
3053static CURLMcode add_next_timeout(struct curltime now,
3054 struct Curl_multi *multi,
3055 struct Curl_easy *d)
3056{
3057 struct curltime *tv = &d->state.expiretime;
3058 struct Curl_llist *list = &d->state.timeoutlist;
3059 struct Curl_llist_element *e;
3060 struct time_node *node = NULL;
3061
3062 /* move over the timeout list for this specific handle and remove all
3063 timeouts that are now passed tense and store the next pending
3064 timeout in *tv */
3065 for(e = list->head; e;) {
3066 struct Curl_llist_element *n = e->next;
3067 timediff_t diff;
3068 node = (struct time_node *)e->ptr;
3069 diff = Curl_timediff(node->time, now);
3070 if(diff <= 0)
3071 /* remove outdated entry */
3072 Curl_llist_remove(list, e, NULL);
3073 else
3074 /* the list is sorted so get out on the first mismatch */
3075 break;
3076 e = n;
3077 }
3078 e = list->head;
3079 if(!e) {
3080 /* clear the expire times within the handles that we remove from the
3081 splay tree */
3082 tv->tv_sec = 0;
3083 tv->tv_usec = 0;
3084 }
3085 else {
3086 /* copy the first entry to 'tv' */
3087 memcpy(tv, &node->time, sizeof(*tv));
3088
3089 /* Insert this node again into the splay. Keep the timer in the list in
3090 case we need to recompute future timers. */
3091 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3092 &d->state.timenode);
3093 }
3094 return CURLM_OK;
3095}
3096
3097static CURLMcode multi_socket(struct Curl_multi *multi,
3098 bool checkall,
3099 curl_socket_t s,
3100 int ev_bitmask,
3101 int *running_handles)
3102{
3103 CURLMcode result = CURLM_OK;
3104 struct Curl_easy *data = NULL;
3105 struct Curl_tree *t;
3106 struct curltime now = Curl_now();
3107
3108 if(checkall) {
3109 /* *perform() deals with running_handles on its own */
3110 result = curl_multi_perform(multi, running_handles);
3111
3112 /* walk through each easy handle and do the socket state change magic
3113 and callbacks */
3114 if(result != CURLM_BAD_HANDLE) {
3115 data = multi->easyp;
3116 while(data && !result) {
3117 result = singlesocket(multi, data);
3118 data = data->next;
3119 }
3120 }
3121
3122 /* or should we fall-through and do the timer-based stuff? */
3123 return result;
3124 }
3125 if(s != CURL_SOCKET_TIMEOUT) {
3126 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3127
3128 if(!entry)
3129 /* Unmatched socket, we can't act on it but we ignore this fact. In
3130 real-world tests it has been proved that libevent can in fact give
3131 the application actions even though the socket was just previously
3132 asked to get removed, so thus we better survive stray socket actions
3133 and just move on. */
3134 ;
3135 else {
3136 struct Curl_hash_iterator iter;
3137 struct Curl_hash_element *he;
3138
3139 /* the socket can be shared by many transfers, iterate */
3140 Curl_hash_start_iterate(&entry->transfers, &iter);
3141 for(he = Curl_hash_next_element(&iter); he;
3142 he = Curl_hash_next_element(&iter)) {
3143 data = (struct Curl_easy *)he->ptr;
3144 DEBUGASSERT(data);
3145 DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
3146
3147 if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
3148 /* set socket event bitmask if they're not locked */
3149 data->conn->cselect_bits = ev_bitmask;
3150
3151 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3152 }
3153
3154 /* Now we fall-through and do the timer-based stuff, since we don't want
3155 to force the user to have to deal with timeouts as long as at least
3156 one connection in fact has traffic. */
3157
3158 data = NULL; /* set data to NULL again to avoid calling
3159 multi_runsingle() in case there's no need to */
3160 now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3161 may have taken some time */
3162 }
3163 }
3164 else {
3165 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3166 Curl_update_timer() to trigger a callback to the app again even if the
3167 same timeout is still the one to run after this call. That handles the
3168 case when the application asks libcurl to run the timeout
3169 prematurely. */
3170 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3171 }
3172
3173 /*
3174 * The loop following here will go on as long as there are expire-times left
3175 * to process in the splay and 'data' will be re-assigned for every expired
3176 * handle we deal with.
3177 */
3178 do {
3179 /* the first loop lap 'data' can be NULL */
3180 if(data) {
3181 SIGPIPE_VARIABLE(pipe_st);
3182
3183 sigpipe_ignore(data, &pipe_st);
3184 result = multi_runsingle(multi, &now, data);
3185 sigpipe_restore(&pipe_st);
3186
3187 if(CURLM_OK >= result) {
3188 /* get the socket(s) and check if the state has been changed since
3189 last */
3190 result = singlesocket(multi, data);
3191 if(result)
3192 return result;
3193 }
3194 }
3195
3196 /* Check if there's one (more) expired timer to deal with! This function
3197 extracts a matching node if there is one */
3198
3199 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3200 if(t) {
3201 data = t->payload; /* assign this for next loop */
3202 (void)add_next_timeout(now, multi, t->payload);
3203 }
3204
3205 } while(t);
3206
3207 *running_handles = multi->num_alive;
3208 return result;
3209}
3210
3211#undef curl_multi_setopt
3212CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3213 CURLMoption option, ...)
3214{
3215 CURLMcode res = CURLM_OK;
3216 va_list param;
3217
3218 if(!GOOD_MULTI_HANDLE(multi))
3219 return CURLM_BAD_HANDLE;
3220
3221 if(multi->in_callback)
3222 return CURLM_RECURSIVE_API_CALL;
3223
3224 va_start(param, option);
3225
3226 switch(option) {
3227 case CURLMOPT_SOCKETFUNCTION:
3228 multi->socket_cb = va_arg(param, curl_socket_callback);
3229 break;
3230 case CURLMOPT_SOCKETDATA:
3231 multi->socket_userp = va_arg(param, void *);
3232 break;
3233 case CURLMOPT_PUSHFUNCTION:
3234 multi->push_cb = va_arg(param, curl_push_callback);
3235 break;
3236 case CURLMOPT_PUSHDATA:
3237 multi->push_userp = va_arg(param, void *);
3238 break;
3239 case CURLMOPT_PIPELINING:
3240 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
3241 break;
3242 case CURLMOPT_TIMERFUNCTION:
3243 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3244 break;
3245 case CURLMOPT_TIMERDATA:
3246 multi->timer_userp = va_arg(param, void *);
3247 break;
3248 case CURLMOPT_MAXCONNECTS:
3249 multi->maxconnects = va_arg(param, long);
3250 break;
3251 case CURLMOPT_MAX_HOST_CONNECTIONS:
3252 multi->max_host_connections = va_arg(param, long);
3253 break;
3254 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3255 multi->max_total_connections = va_arg(param, long);
3256 break;
3257 /* options formerly used for pipelining */
3258 case CURLMOPT_MAX_PIPELINE_LENGTH:
3259 break;
3260 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3261 break;
3262 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3263 break;
3264 case CURLMOPT_PIPELINING_SITE_BL:
3265 break;
3266 case CURLMOPT_PIPELINING_SERVER_BL:
3267 break;
3268 case CURLMOPT_MAX_CONCURRENT_STREAMS:
3269 {
3270 long streams = va_arg(param, long);
3271 if(streams < 1)
3272 streams = 100;
3273 multi->max_concurrent_streams = curlx_sltoui(streams);
3274 }
3275 break;
3276 default:
3277 res = CURLM_UNKNOWN_OPTION;
3278 break;
3279 }
3280 va_end(param);
3281 return res;
3282}
3283
3284/* we define curl_multi_socket() in the public multi.h header */
3285#undef curl_multi_socket
3286
3287CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3288 int *running_handles)
3289{
3290 CURLMcode result;
3291 if(multi->in_callback)
3292 return CURLM_RECURSIVE_API_CALL;
3293 result = multi_socket(multi, FALSE, s, 0, running_handles);
3294 if(CURLM_OK >= result)
3295 result = Curl_update_timer(multi);
3296 return result;
3297}
3298
3299CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3300 int ev_bitmask, int *running_handles)
3301{
3302 CURLMcode result;
3303 if(multi->in_callback)
3304 return CURLM_RECURSIVE_API_CALL;
3305 result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3306 if(CURLM_OK >= result)
3307 result = Curl_update_timer(multi);
3308 return result;
3309}
3310
3311CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3312{
3313 CURLMcode result;
3314 if(multi->in_callback)
3315 return CURLM_RECURSIVE_API_CALL;
3316 result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3317 if(CURLM_OK >= result)
3318 result = Curl_update_timer(multi);
3319 return result;
3320}
3321
3322static CURLMcode multi_timeout(struct Curl_multi *multi,
3323 long *timeout_ms)
3324{
3325 static const struct curltime tv_zero = {0, 0};
3326
3327 if(multi->dead) {
3328 *timeout_ms = 0;
3329 return CURLM_OK;
3330 }
3331
3332 if(multi->timetree) {
3333 /* we have a tree of expire times */
3334 struct curltime now = Curl_now();
3335
3336 /* splay the lowest to the bottom */
3337 multi->timetree = Curl_splay(tv_zero, multi->timetree);
3338
3339 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3340 /* some time left before expiration */
3341 timediff_t diff = Curl_timediff(multi->timetree->key, now);
3342 if(diff <= 0)
3343 /*
3344 * Since we only provide millisecond resolution on the returned value
3345 * and the diff might be less than one millisecond here, we don't
3346 * return zero as that may cause short bursts of busyloops on fast
3347 * processors while the diff is still present but less than one
3348 * millisecond! instead we return 1 until the time is ripe.
3349 */
3350 *timeout_ms = 1;
3351 else
3352 /* this should be safe even on 64 bit archs, as we don't use that
3353 overly long timeouts */
3354 *timeout_ms = (long)diff;
3355 }
3356 else
3357 /* 0 means immediately */
3358 *timeout_ms = 0;
3359 }
3360 else
3361 *timeout_ms = -1;
3362
3363 return CURLM_OK;
3364}
3365
3366CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3367 long *timeout_ms)
3368{
3369 /* First, make some basic checks that the CURLM handle is a good handle */
3370 if(!GOOD_MULTI_HANDLE(multi))
3371 return CURLM_BAD_HANDLE;
3372
3373 if(multi->in_callback)
3374 return CURLM_RECURSIVE_API_CALL;
3375
3376 return multi_timeout(multi, timeout_ms);
3377}
3378
3379/*
3380 * Tell the application it should update its timers, if it subscribes to the
3381 * update timer callback.
3382 */
3383CURLMcode Curl_update_timer(struct Curl_multi *multi)
3384{
3385 long timeout_ms;
3386 int rc;
3387
3388 if(!multi->timer_cb || multi->dead)
3389 return CURLM_OK;
3390 if(multi_timeout(multi, &timeout_ms)) {
3391 return CURLM_OK;
3392 }
3393 if(timeout_ms < 0) {
3394 static const struct curltime none = {0, 0};
3395 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3396 multi->timer_lastcall = none;
3397 /* there's no timeout now but there was one previously, tell the app to
3398 disable it */
3399 set_in_callback(multi, TRUE);
3400 rc = multi->timer_cb(multi, -1, multi->timer_userp);
3401 set_in_callback(multi, FALSE);
3402 if(rc == -1) {
3403 multi->dead = TRUE;
3404 return CURLM_ABORTED_BY_CALLBACK;
3405 }
3406 return CURLM_OK;
3407 }
3408 return CURLM_OK;
3409 }
3410
3411 /* When multi_timeout() is done, multi->timetree points to the node with the
3412 * timeout we got the (relative) time-out time for. We can thus easily check
3413 * if this is the same (fixed) time as we got in a previous call and then
3414 * avoid calling the callback again. */
3415 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3416 return CURLM_OK;
3417
3418 multi->timer_lastcall = multi->timetree->key;
3419
3420 set_in_callback(multi, TRUE);
3421 rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3422 set_in_callback(multi, FALSE);
3423 if(rc == -1) {
3424 multi->dead = TRUE;
3425 return CURLM_ABORTED_BY_CALLBACK;
3426 }
3427 return CURLM_OK;
3428}
3429
3430/*
3431 * multi_deltimeout()
3432 *
3433 * Remove a given timestamp from the list of timeouts.
3434 */
3435static void
3436multi_deltimeout(struct Curl_easy *data, expire_id eid)
3437{
3438 struct Curl_llist_element *e;
3439 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3440 /* find and remove the specific node from the list */
3441 for(e = timeoutlist->head; e; e = e->next) {
3442 struct time_node *n = (struct time_node *)e->ptr;
3443 if(n->eid == eid) {
3444 Curl_llist_remove(timeoutlist, e, NULL);
3445 return;
3446 }
3447 }
3448}
3449
3450/*
3451 * multi_addtimeout()
3452 *
3453 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3454 * of list is always the timeout nearest in time.
3455 *
3456 */
3457static CURLMcode
3458multi_addtimeout(struct Curl_easy *data,
3459 struct curltime *stamp,
3460 expire_id eid)
3461{
3462 struct Curl_llist_element *e;
3463 struct time_node *node;
3464 struct Curl_llist_element *prev = NULL;
3465 size_t n;
3466 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3467
3468 node = &data->state.expires[eid];
3469
3470 /* copy the timestamp and id */
3471 memcpy(&node->time, stamp, sizeof(*stamp));
3472 node->eid = eid; /* also marks it as in use */
3473
3474 n = Curl_llist_count(timeoutlist);
3475 if(n) {
3476 /* find the correct spot in the list */
3477 for(e = timeoutlist->head; e; e = e->next) {
3478 struct time_node *check = (struct time_node *)e->ptr;
3479 timediff_t diff = Curl_timediff(check->time, node->time);
3480 if(diff > 0)
3481 break;
3482 prev = e;
3483 }
3484
3485 }
3486 /* else
3487 this is the first timeout on the list */
3488
3489 Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3490 return CURLM_OK;
3491}
3492
3493/*
3494 * Curl_expire()
3495 *
3496 * given a number of milliseconds from now to use to set the 'act before
3497 * this'-time for the transfer, to be extracted by curl_multi_timeout()
3498 *
3499 * The timeout will be added to a queue of timeouts if it defines a moment in
3500 * time that is later than the current head of queue.
3501 *
3502 * Expire replaces a former timeout using the same id if already set.
3503 */
3504void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3505{
3506 struct Curl_multi *multi = data->multi;
3507 struct curltime *nowp = &data->state.expiretime;
3508 struct curltime set;
3509
3510 /* this is only interesting while there is still an associated multi struct
3511 remaining! */
3512 if(!multi)
3513 return;
3514
3515 DEBUGASSERT(id < EXPIRE_LAST);
3516
3517 set = Curl_now();
3518 set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3519 set.tv_usec += (unsigned int)(milli%1000)*1000;
3520
3521 if(set.tv_usec >= 1000000) {
3522 set.tv_sec++;
3523 set.tv_usec -= 1000000;
3524 }
3525
3526 /* Remove any timer with the same id just in case. */
3527 multi_deltimeout(data, id);
3528
3529 /* Add it to the timer list. It must stay in the list until it has expired
3530 in case we need to recompute the minimum timer later. */
3531 multi_addtimeout(data, &set, id);
3532
3533 if(nowp->tv_sec || nowp->tv_usec) {
3534 /* This means that the struct is added as a node in the splay tree.
3535 Compare if the new time is earlier, and only remove-old/add-new if it
3536 is. */
3537 timediff_t diff = Curl_timediff(set, *nowp);
3538 int rc;
3539
3540 if(diff > 0) {
3541 /* The current splay tree entry is sooner than this new expiry time.
3542 We don't need to update our splay tree entry. */
3543 return;
3544 }
3545
3546 /* Since this is an updated time, we must remove the previous entry from
3547 the splay tree first and then re-add the new value */
3548 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3549 &multi->timetree);
3550 if(rc)
3551 infof(data, "Internal error removing splay node = %d", rc);
3552 }
3553
3554 /* Indicate that we are in the splay tree and insert the new timer expiry
3555 value since it is our local minimum. */
3556 *nowp = set;
3557 data->state.timenode.payload = data;
3558 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3559 &data->state.timenode);
3560}
3561
3562/*
3563 * Curl_expire_done()
3564 *
3565 * Removes the expire timer. Marks it as done.
3566 *
3567 */
3568void Curl_expire_done(struct Curl_easy *data, expire_id id)
3569{
3570 /* remove the timer, if there */
3571 multi_deltimeout(data, id);
3572}
3573
3574/*
3575 * Curl_expire_clear()
3576 *
3577 * Clear ALL timeout values for this handle.
3578 */
3579void Curl_expire_clear(struct Curl_easy *data)
3580{
3581 struct Curl_multi *multi = data->multi;
3582 struct curltime *nowp = &data->state.expiretime;
3583
3584 /* this is only interesting while there is still an associated multi struct
3585 remaining! */
3586 if(!multi)
3587 return;
3588
3589 if(nowp->tv_sec || nowp->tv_usec) {
3590 /* Since this is an cleared time, we must remove the previous entry from
3591 the splay tree */
3592 struct Curl_llist *list = &data->state.timeoutlist;
3593 int rc;
3594
3595 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3596 &multi->timetree);
3597 if(rc)
3598 infof(data, "Internal error clearing splay node = %d", rc);
3599
3600 /* flush the timeout list too */
3601 while(list->size > 0) {
3602 Curl_llist_remove(list, list->tail, NULL);
3603 }
3604
3605#ifdef DEBUGBUILD
3606 infof(data, "Expire cleared (transfer %p)", data);
3607#endif
3608 nowp->tv_sec = 0;
3609 nowp->tv_usec = 0;
3610 }
3611}
3612
3613
3614
3615
3616CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3617 void *hashp)
3618{
3619 struct Curl_sh_entry *there = NULL;
3620
3621 there = sh_getentry(&multi->sockhash, s);
3622
3623 if(!there)
3624 return CURLM_BAD_SOCKET;
3625
3626 there->socketp = hashp;
3627
3628 return CURLM_OK;
3629}
3630
3631size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3632{
3633 return multi ? multi->max_host_connections : 0;
3634}
3635
3636size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3637{
3638 return multi ? multi->max_total_connections : 0;
3639}
3640
3641/*
3642 * When information about a connection has appeared, call this!
3643 */
3644
3645void Curl_multiuse_state(struct Curl_easy *data,
3646 int bundlestate) /* use BUNDLE_* defines */
3647{
3648 struct connectdata *conn;
3649 DEBUGASSERT(data);
3650 DEBUGASSERT(data->multi);
3651 conn = data->conn;
3652 DEBUGASSERT(conn);
3653 DEBUGASSERT(conn->bundle);
3654
3655 conn->bundle->multiuse = bundlestate;
3656 process_pending_handles(data->multi);
3657}
3658
3659static void process_pending_handles(struct Curl_multi *multi)
3660{
3661 struct Curl_llist_element *e = multi->pending.head;
3662 if(e) {
3663 struct Curl_easy *data = e->ptr;
3664
3665 DEBUGASSERT(data->mstate == MSTATE_PENDING);
3666
3667 multistate(data, MSTATE_CONNECT);
3668
3669 /* Remove this node from the list */
3670 Curl_llist_remove(&multi->pending, e, NULL);
3671
3672 /* Make sure that the handle will be processed soonish. */
3673 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3674
3675 /* mark this as having been in the pending queue */
3676 data->state.previouslypending = TRUE;
3677 }
3678}
3679
3680void Curl_set_in_callback(struct Curl_easy *data, bool value)
3681{
3682 /* might get called when there is no data pointer! */
3683 if(data) {
3684 if(data->multi_easy)
3685 data->multi_easy->in_callback = value;
3686 else if(data->multi)
3687 data->multi->in_callback = value;
3688 }
3689}
3690
3691bool Curl_is_in_callback(struct Curl_easy *easy)
3692{
3693 return ((easy->multi && easy->multi->in_callback) ||
3694 (easy->multi_easy && easy->multi_easy->in_callback));
3695}
3696
3697#ifdef DEBUGBUILD
3698void Curl_multi_dump(struct Curl_multi *multi)
3699{
3700 struct Curl_easy *data;
3701 int i;
3702 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
3703 multi->num_easy, multi->num_alive);
3704 for(data = multi->easyp; data; data = data->next) {
3705 if(data->mstate < MSTATE_COMPLETED) {
3706 /* only display handles that are not completed */
3707 fprintf(stderr, "handle %p, state %s, %d sockets\n",
3708 (void *)data,
3709 statename[data->mstate], data->numsocks);
3710 for(i = 0; i < data->numsocks; i++) {
3711 curl_socket_t s = data->sockets[i];
3712 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3713
3714 fprintf(stderr, "%d ", (int)s);
3715 if(!entry) {
3716 fprintf(stderr, "INTERNAL CONFUSION\n");
3717 continue;
3718 }
3719 fprintf(stderr, "[%s %s] ",
3720 (entry->action&CURL_POLL_IN)?"RECVING":"",
3721 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3722 }
3723 if(data->numsocks)
3724 fprintf(stderr, "\n");
3725 }
3726 }
3727}
3728#endif
3729
3730unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3731{
3732 DEBUGASSERT(multi);
3733 return multi->max_concurrent_streams;
3734}
3735