VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/multi.c@ 106542

最後變更 在這個檔案從106542是 104083,由 vboxsync 提交於 11 月 前

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

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

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