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