VirtualBox

source: vbox/trunk/src/libs/curl-8.3.0/lib/multi.c@ 101259

Last change on this file since 101259 was 101127, checked in by vboxsync, 19 months ago

curl-8.3.0: Applied and adjusted our curl changes to 8.0.1. bugref:10526

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette