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