VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/multi.c@ 98929

Last change on this file since 98929 was 98326, checked in by vboxsync, 2 years ago

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

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

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