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