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