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