1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, 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.haxx.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 ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #include <curl/curl.h>
26
27 #include "urldata.h"
28 #include "transfer.h"
29 #include "url.h"
30 #include "connect.h"
31 #include "progress.h"
32 #include "easyif.h"
33 #include "share.h"
34 #include "psl.h"
35 #include "multiif.h"
36 #include "sendf.h"
37 #include "timeval.h"
38 #include "http.h"
39 #include "select.h"
40 #include "warnless.h"
41 #include "speedcheck.h"
42 #include "conncache.h"
43 #include "multihandle.h"
44 #include "sigpipe.h"
45 #include "vtls/vtls.h"
46 #include "connect.h"
47 #include "http_proxy.h"
48 #include "http2.h"
49 /* The last 3 #include files should be in this order */
50 #include "curl_printf.h"
51 #include "curl_memory.h"
52 #include "memdebug.h"
53
54 /*
55 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
56 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
57 CURL handle takes 45-50 K memory, therefore this 3K are not significant.
58 */
59 #ifndef CURL_SOCKET_HASH_TABLE_SIZE
60 #define CURL_SOCKET_HASH_TABLE_SIZE 911
61 #endif
62
63 #ifndef CURL_CONNECTION_HASH_SIZE
64 #define CURL_CONNECTION_HASH_SIZE 97
65 #endif
66
67 #define CURL_MULTI_HANDLE 0x000bab1e
68
69 #define GOOD_MULTI_HANDLE(x) \
70 ((x) && (x)->type == CURL_MULTI_HANDLE)
71
72 static CURLMcode singlesocket(struct Curl_multi *multi,
73 struct Curl_easy *data);
74 static CURLMcode add_next_timeout(struct curltime now,
75 struct Curl_multi *multi,
76 struct Curl_easy *d);
77 static CURLMcode multi_timeout(struct Curl_multi *multi,
78 long *timeout_ms);
79 static void process_pending_handles(struct Curl_multi *multi);
80 static void detach_connnection(struct Curl_easy *data);
81
82 #ifdef DEBUGBUILD
83 static const char * const statename[]={
84 "INIT",
85 "CONNECT_PEND",
86 "CONNECT",
87 "WAITRESOLVE",
88 "WAITCONNECT",
89 "WAITPROXYCONNECT",
90 "SENDPROTOCONNECT",
91 "PROTOCONNECT",
92 "DO",
93 "DOING",
94 "DO_MORE",
95 "DO_DONE",
96 "PERFORM",
97 "TOOFAST",
98 "DONE",
99 "COMPLETED",
100 "MSGSENT",
101 };
102 #endif
103
104 /* function pointer called once when switching TO a state */
105 typedef void (*init_multistate_func)(struct Curl_easy *data);
106
Curl_init_completed(struct Curl_easy * data)107 static void Curl_init_completed(struct Curl_easy *data)
108 {
109 /* this is a completed transfer */
110
111 /* Important: reset the conn pointer so that we don't point to memory
112 that could be freed anytime */
113 detach_connnection(data);
114 Curl_expire_clear(data); /* stop all timers */
115 }
116
117 /* always use this function to change state, to make debugging easier */
mstate(struct Curl_easy * data,CURLMstate state,int lineno)118 static void mstate(struct Curl_easy *data, CURLMstate state
119 #ifdef DEBUGBUILD
120 , int lineno
121 #endif
122 )
123 {
124 CURLMstate oldstate = data->mstate;
125 static const init_multistate_func finit[CURLM_STATE_LAST] = {
126 NULL, /* INIT */
127 NULL, /* CONNECT_PEND */
128 Curl_init_CONNECT, /* CONNECT */
129 NULL, /* WAITRESOLVE */
130 NULL, /* WAITCONNECT */
131 NULL, /* WAITPROXYCONNECT */
132 NULL, /* SENDPROTOCONNECT */
133 NULL, /* PROTOCONNECT */
134 Curl_connect_free, /* DO */
135 NULL, /* DOING */
136 NULL, /* DO_MORE */
137 NULL, /* DO_DONE */
138 NULL, /* PERFORM */
139 NULL, /* TOOFAST */
140 NULL, /* DONE */
141 Curl_init_completed, /* COMPLETED */
142 NULL /* MSGSENT */
143 };
144
145 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
146 (void) lineno;
147 #endif
148
149 if(oldstate == state)
150 /* don't bother when the new state is the same as the old state */
151 return;
152
153 data->mstate = state;
154
155 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
156 if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
157 data->mstate < CURLM_STATE_COMPLETED) {
158 long connection_id = -5000;
159
160 if(data->conn)
161 connection_id = data->conn->connection_id;
162
163 infof(data,
164 "STATE: %s => %s handle %p; line %d (connection #%ld)\n",
165 statename[oldstate], statename[data->mstate],
166 (void *)data, lineno, connection_id);
167 }
168 #endif
169
170 if(state == CURLM_STATE_COMPLETED)
171 /* changing to COMPLETED means there's one less easy handle 'alive' */
172 data->multi->num_alive--;
173
174 /* if this state has an init-function, run it */
175 if(finit[state])
176 finit[state](data);
177 }
178
179 #ifndef DEBUGBUILD
180 #define multistate(x,y) mstate(x,y)
181 #else
182 #define multistate(x,y) mstate(x,y, __LINE__)
183 #endif
184
185 /*
186 * We add one of these structs to the sockhash for each socket
187 */
188
189 struct Curl_sh_entry {
190 struct curl_hash transfers; /* hash of transfers using this socket */
191 unsigned int action; /* what combined action READ/WRITE this socket waits
192 for */
193 void *socketp; /* settable by users with curl_multi_assign() */
194 unsigned int users; /* number of transfers using this */
195 unsigned int readers; /* this many transfers want to read */
196 unsigned int writers; /* this many transfers want to write */
197 };
198 /* bits for 'action' having no bits means this socket is not expecting any
199 action */
200 #define SH_READ 1
201 #define SH_WRITE 2
202
203 /* look up a given socket in the socket hash, skip invalid sockets */
sh_getentry(struct curl_hash * sh,curl_socket_t s)204 static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
205 curl_socket_t s)
206 {
207 if(s != CURL_SOCKET_BAD) {
208 /* only look for proper sockets */
209 return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
210 }
211 return NULL;
212 }
213
214 #define TRHASH_SIZE 13
trhash(void * key,size_t key_length,size_t slots_num)215 static size_t trhash(void *key, size_t key_length, size_t slots_num)
216 {
217 size_t keyval = (size_t)*(struct Curl_easy **)key;
218 (void) key_length;
219
220 return (keyval % slots_num);
221 }
222
trhash_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)223 static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
224 {
225 (void)k1_len;
226 (void)k2_len;
227
228 return *(struct Curl_easy **)k1 == *(struct Curl_easy **)k2;
229 }
230
trhash_dtor(void * nada)231 static void trhash_dtor(void *nada)
232 {
233 (void)nada;
234 }
235
236
237 /* make sure this socket is present in the hash for this handle */
sh_addentry(struct curl_hash * sh,curl_socket_t s)238 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
239 curl_socket_t s)
240 {
241 struct Curl_sh_entry *there = sh_getentry(sh, s);
242 struct Curl_sh_entry *check;
243
244 if(there) {
245 /* it is present, return fine */
246 return there;
247 }
248
249 /* not present, add it */
250 check = calloc(1, sizeof(struct Curl_sh_entry));
251 if(!check)
252 return NULL; /* major failure */
253
254 if(Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash,
255 trhash_compare, trhash_dtor)) {
256 free(check);
257 return NULL;
258 }
259
260 /* make/add new hash entry */
261 if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
262 free(check);
263 return NULL; /* major failure */
264 }
265
266 return check; /* things are good in sockhash land */
267 }
268
269
270 /* delete the given socket + handle from the hash */
sh_delentry(struct Curl_sh_entry * entry,struct curl_hash * sh,curl_socket_t s)271 static void sh_delentry(struct Curl_sh_entry *entry,
272 struct curl_hash *sh, curl_socket_t s)
273 {
274 Curl_hash_destroy(&entry->transfers);
275
276 /* We remove the hash entry. This will end up in a call to
277 sh_freeentry(). */
278 Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
279 }
280
281 /*
282 * free a sockhash entry
283 */
sh_freeentry(void * freethis)284 static void sh_freeentry(void *freethis)
285 {
286 struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
287
288 free(p);
289 }
290
fd_key_compare(void * k1,size_t k1_len,void * k2,size_t k2_len)291 static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
292 {
293 (void) k1_len; (void) k2_len;
294
295 return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
296 }
297
hash_fd(void * key,size_t key_length,size_t slots_num)298 static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
299 {
300 curl_socket_t fd = *((curl_socket_t *) key);
301 (void) key_length;
302
303 return (fd % slots_num);
304 }
305
306 /*
307 * sh_init() creates a new socket hash and returns the handle for it.
308 *
309 * Quote from README.multi_socket:
310 *
311 * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
312 * is somewhat of a bottle neck. Its current implementation may be a bit too
313 * limiting. It simply has a fixed-size array, and on each entry in the array
314 * it has a linked list with entries. So the hash only checks which list to
315 * scan through. The code I had used so for used a list with merely 7 slots
316 * (as that is what the DNS hash uses) but with 7000 connections that would
317 * make an average of 1000 nodes in each list to run through. I upped that to
318 * 97 slots (I believe a prime is suitable) and noticed a significant speed
319 * increase. I need to reconsider the hash implementation or use a rather
320 * large default value like this. At 9000 connections I was still below 10us
321 * per call."
322 *
323 */
sh_init(struct curl_hash * hash,int hashsize)324 static int sh_init(struct curl_hash *hash, int hashsize)
325 {
326 return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
327 sh_freeentry);
328 }
329
330 /*
331 * multi_addmsg()
332 *
333 * Called when a transfer is completed. Adds the given msg pointer to
334 * the list kept in the multi handle.
335 */
multi_addmsg(struct Curl_multi * multi,struct Curl_message * msg)336 static CURLMcode multi_addmsg(struct Curl_multi *multi,
337 struct Curl_message *msg)
338 {
339 Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
340 &msg->list);
341 return CURLM_OK;
342 }
343
Curl_multi_handle(int hashsize,int chashsize)344 struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
345 int chashsize) /* connection hash */
346 {
347 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
348
349 if(!multi)
350 return NULL;
351
352 multi->type = CURL_MULTI_HANDLE;
353
354 if(Curl_mk_dnscache(&multi->hostcache))
355 goto error;
356
357 if(sh_init(&multi->sockhash, hashsize))
358 goto error;
359
360 if(Curl_conncache_init(&multi->conn_cache, chashsize))
361 goto error;
362
363 Curl_llist_init(&multi->msglist, NULL);
364 Curl_llist_init(&multi->pending, NULL);
365
366 multi->multiplexing = TRUE;
367
368 /* -1 means it not set by user, use the default value */
369 multi->maxconnects = -1;
370 return multi;
371
372 error:
373
374 Curl_hash_destroy(&multi->sockhash);
375 Curl_hash_destroy(&multi->hostcache);
376 Curl_conncache_destroy(&multi->conn_cache);
377 Curl_llist_destroy(&multi->msglist, NULL);
378 Curl_llist_destroy(&multi->pending, NULL);
379
380 free(multi);
381 return NULL;
382 }
383
curl_multi_init(void)384 struct Curl_multi *curl_multi_init(void)
385 {
386 return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
387 CURL_CONNECTION_HASH_SIZE);
388 }
389
curl_multi_add_handle(struct Curl_multi * multi,struct Curl_easy * data)390 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
391 struct Curl_easy *data)
392 {
393 /* First, make some basic checks that the CURLM handle is a good handle */
394 if(!GOOD_MULTI_HANDLE(multi))
395 return CURLM_BAD_HANDLE;
396
397 /* Verify that we got a somewhat good easy handle too */
398 if(!GOOD_EASY_HANDLE(data))
399 return CURLM_BAD_EASY_HANDLE;
400
401 /* Prevent users from adding same easy handle more than once and prevent
402 adding to more than one multi stack */
403 if(data->multi)
404 return CURLM_ADDED_ALREADY;
405
406 if(multi->in_callback)
407 return CURLM_RECURSIVE_API_CALL;
408
409 /* Initialize timeout list for this handle */
410 Curl_llist_init(&data->state.timeoutlist, NULL);
411
412 /*
413 * No failure allowed in this function beyond this point. And no
414 * modification of easy nor multi handle allowed before this except for
415 * potential multi's connection cache growing which won't be undone in this
416 * function no matter what.
417 */
418 if(data->set.errorbuffer)
419 data->set.errorbuffer[0] = 0;
420
421 /* set the easy handle */
422 multistate(data, CURLM_STATE_INIT);
423
424 /* for multi interface connections, we share DNS cache automatically if the
425 easy handle's one is currently not set. */
426 if(!data->dns.hostcache ||
427 (data->dns.hostcachetype == HCACHE_NONE)) {
428 data->dns.hostcache = &multi->hostcache;
429 data->dns.hostcachetype = HCACHE_MULTI;
430 }
431
432 /* Point to the shared or multi handle connection cache */
433 if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
434 data->state.conn_cache = &data->share->conn_cache;
435 else
436 data->state.conn_cache = &multi->conn_cache;
437
438 #ifdef USE_LIBPSL
439 /* Do the same for PSL. */
440 if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
441 data->psl = &data->share->psl;
442 else
443 data->psl = &multi->psl;
444 #endif
445
446 /* We add the new entry last in the list. */
447 data->next = NULL; /* end of the line */
448 if(multi->easyp) {
449 struct Curl_easy *last = multi->easylp;
450 last->next = data;
451 data->prev = last;
452 multi->easylp = data; /* the new last node */
453 }
454 else {
455 /* first node, make prev NULL! */
456 data->prev = NULL;
457 multi->easylp = multi->easyp = data; /* both first and last */
458 }
459
460 /* make the Curl_easy refer back to this multi handle */
461 data->multi = multi;
462
463 /* Set the timeout for this handle to expire really soon so that it will
464 be taken care of even when this handle is added in the midst of operation
465 when only the curl_multi_socket() API is used. During that flow, only
466 sockets that time-out or have actions will be dealt with. Since this
467 handle has no action yet, we make sure it times out to get things to
468 happen. */
469 Curl_expire(data, 0, EXPIRE_RUN_NOW);
470
471 /* increase the node-counter */
472 multi->num_easy++;
473
474 /* increase the alive-counter */
475 multi->num_alive++;
476
477 /* A somewhat crude work-around for a little glitch in Curl_update_timer()
478 that happens if the lastcall time is set to the same time when the handle
479 is removed as when the next handle is added, as then the check in
480 Curl_update_timer() that prevents calling the application multiple times
481 with the same timer info will not trigger and then the new handle's
482 timeout will not be notified to the app.
483
484 The work-around is thus simply to clear the 'lastcall' variable to force
485 Curl_update_timer() to always trigger a callback to the app when a new
486 easy handle is added */
487 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
488
489 /* The closure handle only ever has default timeouts set. To improve the
490 state somewhat we clone the timeouts from each added handle so that the
491 closure handle always has the same timeouts as the most recently added
492 easy handle. */
493 data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
494 data->state.conn_cache->closure_handle->set.server_response_timeout =
495 data->set.server_response_timeout;
496 data->state.conn_cache->closure_handle->set.no_signal =
497 data->set.no_signal;
498
499 Curl_update_timer(multi);
500 return CURLM_OK;
501 }
502
503 #if 0
504 /* Debug-function, used like this:
505 *
506 * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
507 *
508 * Enable the hash print function first by editing hash.c
509 */
510 static void debug_print_sock_hash(void *p)
511 {
512 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
513
514 fprintf(stderr, " [easy %p/magic %x/socket %d]",
515 (void *)sh->data, sh->data->magic, (int)sh->socket);
516 }
517 #endif
518
multi_done(struct Curl_easy * data,CURLcode status,bool premature)519 static CURLcode multi_done(struct Curl_easy *data,
520 CURLcode status, /* an error if this is called
521 after an error was detected */
522 bool premature)
523 {
524 CURLcode result;
525 struct connectdata *conn = data->conn;
526 unsigned int i;
527
528 DEBUGF(infof(data, "multi_done\n"));
529
530 if(data->state.done)
531 /* Stop if multi_done() has already been called */
532 return CURLE_OK;
533
534 /* Stop the resolver and free its own resources (but not dns_entry yet). */
535 Curl_resolver_kill(conn);
536
537 /* Cleanup possible redirect junk */
538 Curl_safefree(data->req.newurl);
539 Curl_safefree(data->req.location);
540
541 switch(status) {
542 case CURLE_ABORTED_BY_CALLBACK:
543 case CURLE_READ_ERROR:
544 case CURLE_WRITE_ERROR:
545 /* When we're aborted due to a callback return code it basically have to
546 be counted as premature as there is trouble ahead if we don't. We have
547 many callbacks and protocols work differently, we could potentially do
548 this more fine-grained in the future. */
549 premature = TRUE;
550 default:
551 break;
552 }
553
554 /* this calls the protocol-specific function pointer previously set */
555 if(conn->handler->done)
556 result = conn->handler->done(conn, status, premature);
557 else
558 result = status;
559
560 if(CURLE_ABORTED_BY_CALLBACK != result) {
561 /* avoid this if we already aborted by callback to avoid this calling
562 another callback */
563 CURLcode rc = Curl_pgrsDone(conn);
564 if(!result && rc)
565 result = CURLE_ABORTED_BY_CALLBACK;
566 }
567
568 process_pending_handles(data->multi); /* connection / multiplex */
569
570 detach_connnection(data);
571 if(CONN_INUSE(conn)) {
572 /* Stop if still used. */
573 DEBUGF(infof(data, "Connection still in use %zu, "
574 "no more multi_done now!\n",
575 conn->easyq.size));
576 return CURLE_OK;
577 }
578
579 data->state.done = TRUE; /* called just now! */
580
581 if(conn->dns_entry) {
582 Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
583 conn->dns_entry = NULL;
584 }
585 Curl_hostcache_prune(data);
586 Curl_safefree(data->state.ulbuf);
587
588 /* if the transfer was completed in a paused state there can be buffered
589 data left to free */
590 for(i = 0; i < data->state.tempcount; i++) {
591 free(data->state.tempwrite[i].buf);
592 }
593 data->state.tempcount = 0;
594
595 /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
596 forced us to close this connection. This is ignored for requests taking
597 place in a NTLM/NEGOTIATE authentication handshake
598
599 if conn->bits.close is TRUE, it means that the connection should be
600 closed in spite of all our efforts to be nice, due to protocol
601 restrictions in our or the server's end
602
603 if premature is TRUE, it means this connection was said to be DONE before
604 the entire request operation is complete and thus we can't know in what
605 state it is for re-using, so we're forced to close it. In a perfect world
606 we can add code that keep track of if we really must close it here or not,
607 but currently we have no such detail knowledge.
608 */
609
610 if((data->set.reuse_forbid
611 #if defined(USE_NTLM)
612 && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
613 conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
614 #endif
615 #if defined(USE_SPNEGO)
616 && !(conn->http_negotiate_state == GSS_AUTHRECV ||
617 conn->proxy_negotiate_state == GSS_AUTHRECV)
618 #endif
619 ) || conn->bits.close
620 || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
621 CURLcode res2 = Curl_disconnect(data, conn, premature);
622
623 /* If we had an error already, make sure we return that one. But
624 if we got a new error, return that. */
625 if(!result && res2)
626 result = res2;
627 }
628 else {
629 char buffer[256];
630 /* create string before returning the connection */
631 msnprintf(buffer, sizeof(buffer),
632 "Connection #%ld to host %s left intact",
633 conn->connection_id,
634 conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
635 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
636 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
637 conn->host.dispname);
638
639 /* the connection is no longer in use by this transfer */
640 if(Curl_conncache_return_conn(conn)) {
641 /* remember the most recently used connection */
642 data->state.lastconnect = conn;
643 infof(data, "%s\n", buffer);
644 }
645 else
646 data->state.lastconnect = NULL;
647 }
648
649 Curl_free_request_state(data);
650 return result;
651 }
652
curl_multi_remove_handle(struct Curl_multi * multi,struct Curl_easy * data)653 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
654 struct Curl_easy *data)
655 {
656 struct Curl_easy *easy = data;
657 bool premature;
658 bool easy_owns_conn;
659 struct curl_llist_element *e;
660
661 /* First, make some basic checks that the CURLM handle is a good handle */
662 if(!GOOD_MULTI_HANDLE(multi))
663 return CURLM_BAD_HANDLE;
664
665 /* Verify that we got a somewhat good easy handle too */
666 if(!GOOD_EASY_HANDLE(data))
667 return CURLM_BAD_EASY_HANDLE;
668
669 /* Prevent users from trying to remove same easy handle more than once */
670 if(!data->multi)
671 return CURLM_OK; /* it is already removed so let's say it is fine! */
672
673 if(multi->in_callback)
674 return CURLM_RECURSIVE_API_CALL;
675
676 premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
677 easy_owns_conn = (data->conn && (data->conn->data == easy)) ?
678 TRUE : FALSE;
679
680 /* If the 'state' is not INIT or COMPLETED, we might need to do something
681 nice to put the easy_handle in a good known state when this returns. */
682 if(premature) {
683 /* this handle is "alive" so we need to count down the total number of
684 alive connections when this is removed */
685 multi->num_alive--;
686 }
687
688 if(data->conn &&
689 data->mstate > CURLM_STATE_DO &&
690 data->mstate < CURLM_STATE_COMPLETED) {
691 /* Set connection owner so that the DONE function closes it. We can
692 safely do this here since connection is killed. */
693 data->conn->data = easy;
694 streamclose(data->conn, "Removed with partial response");
695 easy_owns_conn = TRUE;
696 }
697
698 /* The timer must be shut down before data->multi is set to NULL,
699 else the timenode will remain in the splay tree after
700 curl_easy_cleanup is called. */
701 Curl_expire_clear(data);
702
703 if(data->conn) {
704
705 /* we must call multi_done() here (if we still own the connection) so that
706 we don't leave a half-baked one around */
707 if(easy_owns_conn) {
708
709 /* multi_done() clears the conn->data field to lose the association
710 between the easy handle and the connection
711
712 Note that this ignores the return code simply because there's
713 nothing really useful to do with it anyway! */
714 (void)multi_done(data, data->result, premature);
715 }
716 }
717
718 if(data->connect_queue.ptr)
719 /* the handle was in the pending list waiting for an available connection,
720 so go ahead and remove it */
721 Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
722
723 if(data->dns.hostcachetype == HCACHE_MULTI) {
724 /* stop using the multi handle's DNS cache, *after* the possible
725 multi_done() call above */
726 data->dns.hostcache = NULL;
727 data->dns.hostcachetype = HCACHE_NONE;
728 }
729
730 Curl_wildcard_dtor(&data->wildcard);
731
732 /* destroy the timeout list that is held in the easy handle, do this *after*
733 multi_done() as that may actually call Curl_expire that uses this */
734 Curl_llist_destroy(&data->state.timeoutlist, NULL);
735
736 /* as this was using a shared connection cache we clear the pointer to that
737 since we're not part of that multi handle anymore */
738 data->state.conn_cache = NULL;
739
740 /* change state without using multistate(), only to make singlesocket() do
741 what we want */
742 data->mstate = CURLM_STATE_COMPLETED;
743 singlesocket(multi, easy); /* to let the application know what sockets that
744 vanish with this handle */
745
746 /* Remove the association between the connection and the handle */
747 if(data->conn) {
748 data->conn->data = NULL;
749 detach_connnection(data);
750 }
751
752 #ifdef USE_LIBPSL
753 /* Remove the PSL association. */
754 if(data->psl == &multi->psl)
755 data->psl = NULL;
756 #endif
757
758 data->multi = NULL; /* clear the association to this multi handle */
759
760 /* make sure there's no pending message in the queue sent from this easy
761 handle */
762
763 for(e = multi->msglist.head; e; e = e->next) {
764 struct Curl_message *msg = e->ptr;
765
766 if(msg->extmsg.easy_handle == easy) {
767 Curl_llist_remove(&multi->msglist, e, NULL);
768 /* there can only be one from this specific handle */
769 break;
770 }
771 }
772
773 /* make the previous node point to our next */
774 if(data->prev)
775 data->prev->next = data->next;
776 else
777 multi->easyp = data->next; /* point to first node */
778
779 /* make our next point to our previous node */
780 if(data->next)
781 data->next->prev = data->prev;
782 else
783 multi->easylp = data->prev; /* point to last node */
784
785 /* NOTE NOTE NOTE
786 We do not touch the easy handle here! */
787 multi->num_easy--; /* one less to care about now */
788
789 Curl_update_timer(multi);
790 return CURLM_OK;
791 }
792
793 /* Return TRUE if the application asked for multiplexing */
Curl_multiplex_wanted(const struct Curl_multi * multi)794 bool Curl_multiplex_wanted(const struct Curl_multi *multi)
795 {
796 return (multi && (multi->multiplexing));
797 }
798
799 /* This is the only function that should clear data->conn. This will
800 occasionally be called with the pointer already cleared. */
detach_connnection(struct Curl_easy * data)801 static void detach_connnection(struct Curl_easy *data)
802 {
803 struct connectdata *conn = data->conn;
804 if(conn)
805 Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
806 data->conn = NULL;
807 }
808
809 /* This is the only function that should assign data->conn */
Curl_attach_connnection(struct Curl_easy * data,struct connectdata * conn)810 void Curl_attach_connnection(struct Curl_easy *data,
811 struct connectdata *conn)
812 {
813 DEBUGASSERT(!data->conn);
814 DEBUGASSERT(conn);
815 data->conn = conn;
816 Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
817 &data->conn_queue);
818 }
819
waitconnect_getsock(struct connectdata * conn,curl_socket_t * sock)820 static int waitconnect_getsock(struct connectdata *conn,
821 curl_socket_t *sock)
822 {
823 int i;
824 int s = 0;
825 int rc = 0;
826
827 #ifdef USE_SSL
828 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
829 return Curl_ssl_getsock(conn, sock);
830 #endif
831
832 for(i = 0; i<2; i++) {
833 if(conn->tempsock[i] != CURL_SOCKET_BAD) {
834 sock[s] = conn->tempsock[i];
835 rc |= GETSOCK_WRITESOCK(s);
836 #ifdef ENABLE_QUIC
837 if(conn->transport == TRNSPRT_QUIC)
838 /* when connecting QUIC, we want to read the socket too */
839 rc |= GETSOCK_READSOCK(s);
840 #endif
841 s++;
842 }
843 }
844
845 return rc;
846 }
847
waitproxyconnect_getsock(struct connectdata * conn,curl_socket_t * sock)848 static int waitproxyconnect_getsock(struct connectdata *conn,
849 curl_socket_t *sock)
850 {
851 sock[0] = conn->sock[FIRSTSOCKET];
852
853 /* when we've sent a CONNECT to a proxy, we should rather wait for the
854 socket to become readable to be able to get the response headers */
855 if(conn->connect_state)
856 return GETSOCK_READSOCK(0);
857
858 return GETSOCK_WRITESOCK(0);
859 }
860
domore_getsock(struct connectdata * conn,curl_socket_t * socks)861 static int domore_getsock(struct connectdata *conn,
862 curl_socket_t *socks)
863 {
864 if(conn && conn->handler->domore_getsock)
865 return conn->handler->domore_getsock(conn, socks);
866 return GETSOCK_BLANK;
867 }
868
doing_getsock(struct connectdata * conn,curl_socket_t * socks)869 static int doing_getsock(struct connectdata *conn,
870 curl_socket_t *socks)
871 {
872 if(conn && conn->handler->doing_getsock)
873 return conn->handler->doing_getsock(conn, socks);
874 return GETSOCK_BLANK;
875 }
876
protocol_getsock(struct connectdata * conn,curl_socket_t * socks)877 static int protocol_getsock(struct connectdata *conn,
878 curl_socket_t *socks)
879 {
880 if(conn->handler->proto_getsock)
881 return conn->handler->proto_getsock(conn, socks);
882 /* Backup getsock logic. Since there is a live socket in use, we must wait
883 for it or it will be removed from watching when the multi_socket API is
884 used. */
885 socks[0] = conn->sock[FIRSTSOCKET];
886 return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
887 }
888
889 /* returns bitmapped flags for this handle and its sockets. The 'socks[]'
890 array contains MAX_SOCKSPEREASYHANDLE entries. */
multi_getsock(struct Curl_easy * data,curl_socket_t * socks)891 static int multi_getsock(struct Curl_easy *data,
892 curl_socket_t *socks)
893 {
894 /* The no connection case can happen when this is called from
895 curl_multi_remove_handle() => singlesocket() => multi_getsock().
896 */
897 if(!data->conn)
898 return 0;
899
900 if(data->mstate > CURLM_STATE_CONNECT &&
901 data->mstate < CURLM_STATE_COMPLETED) {
902 /* Set up ownership correctly */
903 data->conn->data = data;
904 }
905
906 switch(data->mstate) {
907 default:
908 #if 0 /* switch back on these cases to get the compiler to check for all enums
909 to be present */
910 case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
911 case CURLM_STATE_COMPLETED:
912 case CURLM_STATE_MSGSENT:
913 case CURLM_STATE_INIT:
914 case CURLM_STATE_CONNECT:
915 case CURLM_STATE_WAITDO:
916 case CURLM_STATE_DONE:
917 case CURLM_STATE_LAST:
918 /* this will get called with CURLM_STATE_COMPLETED when a handle is
919 removed */
920 #endif
921 return 0;
922
923 case CURLM_STATE_WAITRESOLVE:
924 return Curl_resolv_getsock(data->conn, socks);
925
926 case CURLM_STATE_PROTOCONNECT:
927 case CURLM_STATE_SENDPROTOCONNECT:
928 return protocol_getsock(data->conn, socks);
929
930 case CURLM_STATE_DO:
931 case CURLM_STATE_DOING:
932 return doing_getsock(data->conn, socks);
933
934 case CURLM_STATE_WAITPROXYCONNECT:
935 return waitproxyconnect_getsock(data->conn, socks);
936
937 case CURLM_STATE_WAITCONNECT:
938 return waitconnect_getsock(data->conn, socks);
939
940 case CURLM_STATE_DO_MORE:
941 return domore_getsock(data->conn, socks);
942
943 case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
944 to waiting for the same as the *PERFORM
945 states */
946 case CURLM_STATE_PERFORM:
947 return Curl_single_getsock(data->conn, socks);
948 }
949
950 }
951
curl_multi_fdset(struct Curl_multi * multi,fd_set * read_fd_set,fd_set * write_fd_set,fd_set * exc_fd_set,int * max_fd)952 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
953 fd_set *read_fd_set, fd_set *write_fd_set,
954 fd_set *exc_fd_set, int *max_fd)
955 {
956 /* Scan through all the easy handles to get the file descriptors set.
957 Some easy handles may not have connected to the remote host yet,
958 and then we must make sure that is done. */
959 struct Curl_easy *data;
960 int this_max_fd = -1;
961 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
962 int i;
963 (void)exc_fd_set; /* not used */
964
965 if(!GOOD_MULTI_HANDLE(multi))
966 return CURLM_BAD_HANDLE;
967
968 if(multi->in_callback)
969 return CURLM_RECURSIVE_API_CALL;
970
971 data = multi->easyp;
972 while(data) {
973 int bitmap = multi_getsock(data, sockbunch);
974
975 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
976 curl_socket_t s = CURL_SOCKET_BAD;
977
978 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
979 FD_SET(sockbunch[i], read_fd_set);
980 s = sockbunch[i];
981 }
982 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
983 FD_SET(sockbunch[i], write_fd_set);
984 s = sockbunch[i];
985 }
986 if(s == CURL_SOCKET_BAD)
987 /* this socket is unused, break out of loop */
988 break;
989 if((int)s > this_max_fd)
990 this_max_fd = (int)s;
991 }
992
993 data = data->next; /* check next handle */
994 }
995
996 *max_fd = this_max_fd;
997
998 return CURLM_OK;
999 }
1000
1001 #define NUM_POLLS_ON_STACK 10
1002
Curl_multi_wait(struct Curl_multi * multi,struct curl_waitfd extra_fds[],unsigned int extra_nfds,int timeout_ms,int * ret,bool extrawait)1003 static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
1004 struct curl_waitfd extra_fds[],
1005 unsigned int extra_nfds,
1006 int timeout_ms,
1007 int *ret,
1008 bool extrawait) /* when no socket, wait */
1009 {
1010 struct Curl_easy *data;
1011 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1012 int bitmap;
1013 unsigned int i;
1014 unsigned int nfds = 0;
1015 unsigned int curlfds;
1016 bool ufds_malloc = FALSE;
1017 long timeout_internal;
1018 int retcode = 0;
1019 struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1020 struct pollfd *ufds = &a_few_on_stack[0];
1021
1022 if(!GOOD_MULTI_HANDLE(multi))
1023 return CURLM_BAD_HANDLE;
1024
1025 if(multi->in_callback)
1026 return CURLM_RECURSIVE_API_CALL;
1027
1028 /* Count up how many fds we have from the multi handle */
1029 data = multi->easyp;
1030 while(data) {
1031 bitmap = multi_getsock(data, sockbunch);
1032
1033 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1034 curl_socket_t s = CURL_SOCKET_BAD;
1035
1036 if(bitmap & GETSOCK_READSOCK(i)) {
1037 ++nfds;
1038 s = sockbunch[i];
1039 }
1040 if(bitmap & GETSOCK_WRITESOCK(i)) {
1041 ++nfds;
1042 s = sockbunch[i];
1043 }
1044 if(s == CURL_SOCKET_BAD) {
1045 break;
1046 }
1047 }
1048
1049 data = data->next; /* check next handle */
1050 }
1051
1052 /* If the internally desired timeout is actually shorter than requested from
1053 the outside, then use the shorter time! But only if the internal timer
1054 is actually larger than -1! */
1055 (void)multi_timeout(multi, &timeout_internal);
1056 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1057 timeout_ms = (int)timeout_internal;
1058
1059 curlfds = nfds; /* number of internal file descriptors */
1060 nfds += extra_nfds; /* add the externally provided ones */
1061
1062 if(nfds > NUM_POLLS_ON_STACK) {
1063 /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1064 big, so at 2^29 sockets this value might wrap. When a process gets
1065 the capability to actually handle over 500 million sockets this
1066 calculation needs a integer overflow check. */
1067 ufds = malloc(nfds * sizeof(struct pollfd));
1068 if(!ufds)
1069 return CURLM_OUT_OF_MEMORY;
1070 ufds_malloc = TRUE;
1071 }
1072 nfds = 0;
1073
1074 /* only do the second loop if we found descriptors in the first stage run
1075 above */
1076
1077 if(curlfds) {
1078 /* Add the curl handles to our pollfds first */
1079 data = multi->easyp;
1080 while(data) {
1081 bitmap = multi_getsock(data, sockbunch);
1082
1083 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1084 curl_socket_t s = CURL_SOCKET_BAD;
1085
1086 if(bitmap & GETSOCK_READSOCK(i)) {
1087 ufds[nfds].fd = sockbunch[i];
1088 ufds[nfds].events = POLLIN;
1089 ++nfds;
1090 s = sockbunch[i];
1091 }
1092 if(bitmap & GETSOCK_WRITESOCK(i)) {
1093 ufds[nfds].fd = sockbunch[i];
1094 ufds[nfds].events = POLLOUT;
1095 ++nfds;
1096 s = sockbunch[i];
1097 }
1098 if(s == CURL_SOCKET_BAD) {
1099 break;
1100 }
1101 }
1102
1103 data = data->next; /* check next handle */
1104 }
1105 }
1106
1107 /* Add external file descriptions from poll-like struct curl_waitfd */
1108 for(i = 0; i < extra_nfds; i++) {
1109 ufds[nfds].fd = extra_fds[i].fd;
1110 ufds[nfds].events = 0;
1111 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1112 ufds[nfds].events |= POLLIN;
1113 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1114 ufds[nfds].events |= POLLPRI;
1115 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1116 ufds[nfds].events |= POLLOUT;
1117 ++nfds;
1118 }
1119
1120 if(nfds) {
1121 int pollrc;
1122 /* wait... */
1123 pollrc = Curl_poll(ufds, nfds, timeout_ms);
1124
1125 if(pollrc > 0) {
1126 retcode = pollrc;
1127 /* copy revents results from the poll to the curl_multi_wait poll
1128 struct, the bit values of the actual underlying poll() implementation
1129 may not be the same as the ones in the public libcurl API! */
1130 for(i = 0; i < extra_nfds; i++) {
1131 unsigned short mask = 0;
1132 unsigned r = ufds[curlfds + i].revents;
1133
1134 if(r & POLLIN)
1135 mask |= CURL_WAIT_POLLIN;
1136 if(r & POLLOUT)
1137 mask |= CURL_WAIT_POLLOUT;
1138 if(r & POLLPRI)
1139 mask |= CURL_WAIT_POLLPRI;
1140
1141 extra_fds[i].revents = mask;
1142 }
1143 }
1144 }
1145
1146 if(ufds_malloc)
1147 free(ufds);
1148 if(ret)
1149 *ret = retcode;
1150 if(!extrawait || extra_fds || curlfds)
1151 /* if any socket was checked */
1152 ;
1153 else {
1154 long sleep_ms = 0;
1155
1156 /* Avoid busy-looping when there's nothing particular to wait for */
1157 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1158 if(sleep_ms > timeout_ms)
1159 sleep_ms = timeout_ms;
1160 Curl_wait_ms((int)sleep_ms);
1161 }
1162 }
1163
1164 return CURLM_OK;
1165 }
1166
curl_multi_wait(struct Curl_multi * multi,struct curl_waitfd extra_fds[],unsigned int extra_nfds,int timeout_ms,int * ret)1167 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1168 struct curl_waitfd extra_fds[],
1169 unsigned int extra_nfds,
1170 int timeout_ms,
1171 int *ret)
1172 {
1173 return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE);
1174 }
1175
curl_multi_poll(struct Curl_multi * multi,struct curl_waitfd extra_fds[],unsigned int extra_nfds,int timeout_ms,int * ret)1176 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1177 struct curl_waitfd extra_fds[],
1178 unsigned int extra_nfds,
1179 int timeout_ms,
1180 int *ret)
1181 {
1182 return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE);
1183 }
1184
1185 /*
1186 * multi_ischanged() is called
1187 *
1188 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1189 * => CONNECT action.
1190 *
1191 * Set 'clear' to TRUE to have it also clear the state variable.
1192 */
multi_ischanged(struct Curl_multi * multi,bool clear)1193 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1194 {
1195 bool retval = multi->recheckstate;
1196 if(clear)
1197 multi->recheckstate = FALSE;
1198 return retval;
1199 }
1200
Curl_multi_add_perform(struct Curl_multi * multi,struct Curl_easy * data,struct connectdata * conn)1201 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1202 struct Curl_easy *data,
1203 struct connectdata *conn)
1204 {
1205 CURLMcode rc;
1206
1207 if(multi->in_callback)
1208 return CURLM_RECURSIVE_API_CALL;
1209
1210 rc = curl_multi_add_handle(multi, data);
1211 if(!rc) {
1212 struct SingleRequest *k = &data->req;
1213
1214 /* pass in NULL for 'conn' here since we don't want to init the
1215 connection, only this transfer */
1216 Curl_init_do(data, NULL);
1217
1218 /* take this handle to the perform state right away */
1219 multistate(data, CURLM_STATE_PERFORM);
1220 Curl_attach_connnection(data, conn);
1221 k->keepon |= KEEP_RECV; /* setup to receive! */
1222 }
1223 return rc;
1224 }
1225
1226 /*
1227 * do_complete is called when the DO actions are complete.
1228 *
1229 * We init chunking and trailer bits to their default values here immediately
1230 * before receiving any header data for the current request.
1231 */
do_complete(struct connectdata * conn)1232 static void do_complete(struct connectdata *conn)
1233 {
1234 conn->data->req.chunk = FALSE;
1235 Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
1236 }
1237
multi_do(struct Curl_easy * data,bool * done)1238 static CURLcode multi_do(struct Curl_easy *data, bool *done)
1239 {
1240 CURLcode result = CURLE_OK;
1241 struct connectdata *conn = data->conn;
1242
1243 DEBUGASSERT(conn);
1244 DEBUGASSERT(conn->handler);
1245
1246 if(conn->handler->do_it) {
1247 /* generic protocol-specific function pointer set in curl_connect() */
1248 result = conn->handler->do_it(conn, done);
1249
1250 if(!result && *done)
1251 /* do_complete must be called after the protocol-specific DO function */
1252 do_complete(conn);
1253 }
1254 return result;
1255 }
1256
1257 /*
1258 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1259 * second stage DO state which (wrongly) was introduced to support FTP's
1260 * second connection.
1261 *
1262 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1263 * DOING state there's more work to do!
1264 */
1265
multi_do_more(struct connectdata * conn,int * complete)1266 static CURLcode multi_do_more(struct connectdata *conn, int *complete)
1267 {
1268 CURLcode result = CURLE_OK;
1269
1270 *complete = 0;
1271
1272 if(conn->handler->do_more)
1273 result = conn->handler->do_more(conn, complete);
1274
1275 if(!result && (*complete == 1))
1276 /* do_complete must be called after the protocol-specific DO function */
1277 do_complete(conn);
1278
1279 return result;
1280 }
1281
1282 /*
1283 * We are doing protocol-specific connecting and this is being called over and
1284 * over from the multi interface until the connection phase is done on
1285 * protocol layer.
1286 */
1287
protocol_connecting(struct connectdata * conn,bool * done)1288 static CURLcode protocol_connecting(struct connectdata *conn,
1289 bool *done)
1290 {
1291 CURLcode result = CURLE_OK;
1292
1293 if(conn && conn->handler->connecting) {
1294 *done = FALSE;
1295 result = conn->handler->connecting(conn, done);
1296 }
1297 else
1298 *done = TRUE;
1299
1300 return result;
1301 }
1302
1303 /*
1304 * We are DOING this is being called over and over from the multi interface
1305 * until the DOING phase is done on protocol layer.
1306 */
1307
protocol_doing(struct connectdata * conn,bool * done)1308 static CURLcode protocol_doing(struct connectdata *conn, bool *done)
1309 {
1310 CURLcode result = CURLE_OK;
1311
1312 if(conn && conn->handler->doing) {
1313 *done = FALSE;
1314 result = conn->handler->doing(conn, done);
1315 }
1316 else
1317 *done = TRUE;
1318
1319 return result;
1320 }
1321
1322 /*
1323 * We have discovered that the TCP connection has been successful, we can now
1324 * proceed with some action.
1325 *
1326 */
protocol_connect(struct connectdata * conn,bool * protocol_done)1327 static CURLcode protocol_connect(struct connectdata *conn,
1328 bool *protocol_done)
1329 {
1330 CURLcode result = CURLE_OK;
1331
1332 DEBUGASSERT(conn);
1333 DEBUGASSERT(protocol_done);
1334
1335 *protocol_done = FALSE;
1336
1337 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1338 /* We already are connected, get back. This may happen when the connect
1339 worked fine in the first call, like when we connect to a local server
1340 or proxy. Note that we don't know if the protocol is actually done.
1341
1342 Unless this protocol doesn't have any protocol-connect callback, as
1343 then we know we're done. */
1344 if(!conn->handler->connecting)
1345 *protocol_done = TRUE;
1346
1347 return CURLE_OK;
1348 }
1349
1350 if(!conn->bits.protoconnstart) {
1351
1352 result = Curl_proxy_connect(conn, FIRSTSOCKET);
1353 if(result)
1354 return result;
1355
1356 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1357 /* wait for HTTPS proxy SSL initialization to complete */
1358 return CURLE_OK;
1359
1360 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1361 Curl_connect_ongoing(conn))
1362 /* when using an HTTP tunnel proxy, await complete tunnel establishment
1363 before proceeding further. Return CURLE_OK so we'll be called again */
1364 return CURLE_OK;
1365
1366 if(conn->handler->connect_it) {
1367 /* is there a protocol-specific connect() procedure? */
1368
1369 /* Call the protocol-specific connect function */
1370 result = conn->handler->connect_it(conn, protocol_done);
1371 }
1372 else
1373 *protocol_done = TRUE;
1374
1375 /* it has started, possibly even completed but that knowledge isn't stored
1376 in this bit! */
1377 if(!result)
1378 conn->bits.protoconnstart = TRUE;
1379 }
1380
1381 return result; /* pass back status */
1382 }
1383
1384
multi_runsingle(struct Curl_multi * multi,struct curltime now,struct Curl_easy * data)1385 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1386 struct curltime now,
1387 struct Curl_easy *data)
1388 {
1389 struct Curl_message *msg = NULL;
1390 bool connected;
1391 bool async;
1392 bool protocol_connected = FALSE;
1393 bool dophase_done = FALSE;
1394 bool done = FALSE;
1395 CURLMcode rc;
1396 CURLcode result = CURLE_OK;
1397 timediff_t timeout_ms;
1398 timediff_t recv_timeout_ms;
1399 timediff_t send_timeout_ms;
1400 int control;
1401
1402 if(!GOOD_EASY_HANDLE(data))
1403 return CURLM_BAD_EASY_HANDLE;
1404
1405 do {
1406 /* A "stream" here is a logical stream if the protocol can handle that
1407 (HTTP/2), or the full connection for older protocols */
1408 bool stream_error = FALSE;
1409 rc = CURLM_OK;
1410
1411 DEBUGASSERT((data->mstate <= CURLM_STATE_CONNECT) ||
1412 (data->mstate >= CURLM_STATE_DONE) ||
1413 data->conn);
1414 if(!data->conn &&
1415 data->mstate > CURLM_STATE_CONNECT &&
1416 data->mstate < CURLM_STATE_DONE) {
1417 /* In all these states, the code will blindly access 'data->conn'
1418 so this is precaution that it isn't NULL. And it silences static
1419 analyzers. */
1420 failf(data, "In state %d with no conn, bail out!\n", data->mstate);
1421 return CURLM_INTERNAL_ERROR;
1422 }
1423
1424 if(multi_ischanged(multi, TRUE)) {
1425 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
1426 process_pending_handles(multi); /* multiplexed */
1427 }
1428
1429 if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
1430 data->mstate < CURLM_STATE_COMPLETED) {
1431 /* Make sure we set the connection's current owner */
1432 data->conn->data = data;
1433 }
1434
1435 if(data->conn &&
1436 (data->mstate >= CURLM_STATE_CONNECT) &&
1437 (data->mstate < CURLM_STATE_COMPLETED)) {
1438 /* we need to wait for the connect state as only then is the start time
1439 stored, but we must not check already completed handles */
1440 timeout_ms = Curl_timeleft(data, &now,
1441 (data->mstate <= CURLM_STATE_DO)?
1442 TRUE:FALSE);
1443
1444 if(timeout_ms < 0) {
1445 /* Handle timed out */
1446 if(data->mstate == CURLM_STATE_WAITRESOLVE)
1447 failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1448 " milliseconds",
1449 Curl_timediff(now, data->progress.t_startsingle));
1450 else if(data->mstate == CURLM_STATE_WAITCONNECT)
1451 failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1452 " milliseconds",
1453 Curl_timediff(now, data->progress.t_startsingle));
1454 else {
1455 struct SingleRequest *k = &data->req;
1456 if(k->size != -1) {
1457 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1458 " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1459 CURL_FORMAT_CURL_OFF_T " bytes received",
1460 Curl_timediff(now, data->progress.t_startsingle),
1461 k->bytecount, k->size);
1462 }
1463 else {
1464 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1465 " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1466 " bytes received",
1467 Curl_timediff(now, data->progress.t_startsingle),
1468 k->bytecount);
1469 }
1470 }
1471
1472 /* Force connection closed if the connection has indeed been used */
1473 if(data->mstate > CURLM_STATE_DO) {
1474 streamclose(data->conn, "Disconnected with pending data");
1475 stream_error = TRUE;
1476 }
1477 result = CURLE_OPERATION_TIMEDOUT;
1478 (void)multi_done(data, result, TRUE);
1479 /* Skip the statemachine and go directly to error handling section. */
1480 goto statemachine_end;
1481 }
1482 }
1483
1484 switch(data->mstate) {
1485 case CURLM_STATE_INIT:
1486 /* init this transfer. */
1487 result = Curl_pretransfer(data);
1488
1489 if(!result) {
1490 /* after init, go CONNECT */
1491 multistate(data, CURLM_STATE_CONNECT);
1492 Curl_pgrsTime(data, TIMER_STARTOP);
1493 rc = CURLM_CALL_MULTI_PERFORM;
1494 }
1495 break;
1496
1497 case CURLM_STATE_CONNECT_PEND:
1498 /* We will stay here until there is a connection available. Then
1499 we try again in the CURLM_STATE_CONNECT state. */
1500 break;
1501
1502 case CURLM_STATE_CONNECT:
1503 /* Connect. We want to get a connection identifier filled in. */
1504 Curl_pgrsTime(data, TIMER_STARTSINGLE);
1505 if(data->set.timeout)
1506 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1507
1508 if(data->set.connecttimeout)
1509 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1510
1511 result = Curl_connect(data, &async, &protocol_connected);
1512 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1513 /* There was no connection available. We will go to the pending
1514 state and wait for an available connection. */
1515 multistate(data, CURLM_STATE_CONNECT_PEND);
1516
1517 /* add this handle to the list of connect-pending handles */
1518 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1519 &data->connect_queue);
1520 result = CURLE_OK;
1521 break;
1522 }
1523 else if(data->state.previouslypending) {
1524 /* this transfer comes from the pending queue so try move another */
1525 infof(data, "Transfer was pending, now try another\n");
1526 process_pending_handles(data->multi);
1527 }
1528
1529 if(!result) {
1530 if(async)
1531 /* We're now waiting for an asynchronous name lookup */
1532 multistate(data, CURLM_STATE_WAITRESOLVE);
1533 else {
1534 /* after the connect has been sent off, go WAITCONNECT unless the
1535 protocol connect is already done and we can go directly to
1536 WAITDO or DO! */
1537 rc = CURLM_CALL_MULTI_PERFORM;
1538
1539 if(protocol_connected)
1540 multistate(data, CURLM_STATE_DO);
1541 else {
1542 #ifndef CURL_DISABLE_HTTP
1543 if(Curl_connect_ongoing(data->conn))
1544 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1545 else
1546 #endif
1547 multistate(data, CURLM_STATE_WAITCONNECT);
1548 }
1549 }
1550 }
1551 break;
1552
1553 case CURLM_STATE_WAITRESOLVE:
1554 /* awaiting an asynch name resolve to complete */
1555 {
1556 struct Curl_dns_entry *dns = NULL;
1557 struct connectdata *conn = data->conn;
1558 const char *hostname;
1559
1560 DEBUGASSERT(conn);
1561 if(conn->bits.httpproxy)
1562 hostname = conn->http_proxy.host.name;
1563 else if(conn->bits.conn_to_host)
1564 hostname = conn->conn_to_host.name;
1565 else
1566 hostname = conn->host.name;
1567
1568 /* check if we have the name resolved by now */
1569 dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
1570
1571 if(dns) {
1572 #ifdef CURLRES_ASYNCH
1573 conn->async.dns = dns;
1574 conn->async.done = TRUE;
1575 #endif
1576 result = CURLE_OK;
1577 infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
1578 }
1579
1580 if(!dns)
1581 result = Curl_resolv_check(data->conn, &dns);
1582
1583 /* Update sockets here, because the socket(s) may have been
1584 closed and the application thus needs to be told, even if it
1585 is likely that the same socket(s) will again be used further
1586 down. If the name has not yet been resolved, it is likely
1587 that new sockets have been opened in an attempt to contact
1588 another resolver. */
1589 singlesocket(multi, data);
1590
1591 if(dns) {
1592 /* Perform the next step in the connection phase, and then move on
1593 to the WAITCONNECT state */
1594 result = Curl_once_resolved(data->conn, &protocol_connected);
1595
1596 if(result)
1597 /* if Curl_once_resolved() returns failure, the connection struct
1598 is already freed and gone */
1599 data->conn = NULL; /* no more connection */
1600 else {
1601 /* call again please so that we get the next socket setup */
1602 rc = CURLM_CALL_MULTI_PERFORM;
1603 if(protocol_connected)
1604 multistate(data, CURLM_STATE_DO);
1605 else {
1606 #ifndef CURL_DISABLE_HTTP
1607 if(Curl_connect_ongoing(data->conn))
1608 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1609 else
1610 #endif
1611 multistate(data, CURLM_STATE_WAITCONNECT);
1612 }
1613 }
1614 }
1615
1616 if(result) {
1617 /* failure detected */
1618 stream_error = TRUE;
1619 break;
1620 }
1621 }
1622 break;
1623
1624 #ifndef CURL_DISABLE_HTTP
1625 case CURLM_STATE_WAITPROXYCONNECT:
1626 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1627 DEBUGASSERT(data->conn);
1628 result = Curl_http_connect(data->conn, &protocol_connected);
1629
1630 if(data->conn->bits.proxy_connect_closed) {
1631 rc = CURLM_CALL_MULTI_PERFORM;
1632 /* connect back to proxy again */
1633 result = CURLE_OK;
1634 multi_done(data, CURLE_OK, FALSE);
1635 multistate(data, CURLM_STATE_CONNECT);
1636 }
1637 else if(!result) {
1638 if((data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
1639 data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
1640 Curl_connect_complete(data->conn)) {
1641 rc = CURLM_CALL_MULTI_PERFORM;
1642 /* initiate protocol connect phase */
1643 multistate(data, CURLM_STATE_SENDPROTOCONNECT);
1644 }
1645 }
1646 else if(result)
1647 stream_error = TRUE;
1648 break;
1649 #endif
1650
1651 case CURLM_STATE_WAITCONNECT:
1652 /* awaiting a completion of an asynch TCP connect */
1653 DEBUGASSERT(data->conn);
1654 result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
1655 if(connected && !result) {
1656 #ifndef CURL_DISABLE_HTTP
1657 if((data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
1658 !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
1659 Curl_connect_ongoing(data->conn)) {
1660 multistate(data, CURLM_STATE_WAITPROXYCONNECT);
1661 break;
1662 }
1663 #endif
1664 rc = CURLM_CALL_MULTI_PERFORM;
1665 multistate(data, data->conn->bits.tunnel_proxy?
1666 CURLM_STATE_WAITPROXYCONNECT:
1667 CURLM_STATE_SENDPROTOCONNECT);
1668 }
1669 else if(result) {
1670 /* failure detected */
1671 Curl_posttransfer(data);
1672 multi_done(data, result, TRUE);
1673 stream_error = TRUE;
1674 break;
1675 }
1676 break;
1677
1678 case CURLM_STATE_SENDPROTOCONNECT:
1679 result = protocol_connect(data->conn, &protocol_connected);
1680 if(!result && !protocol_connected)
1681 /* switch to waiting state */
1682 multistate(data, CURLM_STATE_PROTOCONNECT);
1683 else if(!result) {
1684 /* protocol connect has completed, go WAITDO or DO */
1685 multistate(data, CURLM_STATE_DO);
1686 rc = CURLM_CALL_MULTI_PERFORM;
1687 }
1688 else if(result) {
1689 /* failure detected */
1690 Curl_posttransfer(data);
1691 multi_done(data, result, TRUE);
1692 stream_error = TRUE;
1693 }
1694 break;
1695
1696 case CURLM_STATE_PROTOCONNECT:
1697 /* protocol-specific connect phase */
1698 result = protocol_connecting(data->conn, &protocol_connected);
1699 if(!result && protocol_connected) {
1700 /* after the connect has completed, go WAITDO or DO */
1701 multistate(data, CURLM_STATE_DO);
1702 rc = CURLM_CALL_MULTI_PERFORM;
1703 }
1704 else if(result) {
1705 /* failure detected */
1706 Curl_posttransfer(data);
1707 multi_done(data, result, TRUE);
1708 stream_error = TRUE;
1709 }
1710 break;
1711
1712 case CURLM_STATE_DO:
1713 if(data->set.connect_only) {
1714 /* keep connection open for application to use the socket */
1715 connkeep(data->conn, "CONNECT_ONLY");
1716 multistate(data, CURLM_STATE_DONE);
1717 result = CURLE_OK;
1718 rc = CURLM_CALL_MULTI_PERFORM;
1719 }
1720 else {
1721 /* Perform the protocol's DO action */
1722 result = multi_do(data, &dophase_done);
1723
1724 /* When multi_do() returns failure, data->conn might be NULL! */
1725
1726 if(!result) {
1727 if(!dophase_done) {
1728 #ifndef CURL_DISABLE_FTP
1729 /* some steps needed for wildcard matching */
1730 if(data->state.wildcardmatch) {
1731 struct WildcardData *wc = &data->wildcard;
1732 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
1733 /* skip some states if it is important */
1734 multi_done(data, CURLE_OK, FALSE);
1735 multistate(data, CURLM_STATE_DONE);
1736 rc = CURLM_CALL_MULTI_PERFORM;
1737 break;
1738 }
1739 }
1740 #endif
1741 /* DO was not completed in one function call, we must continue
1742 DOING... */
1743 multistate(data, CURLM_STATE_DOING);
1744 rc = CURLM_OK;
1745 }
1746
1747 /* after DO, go DO_DONE... or DO_MORE */
1748 else if(data->conn->bits.do_more) {
1749 /* we're supposed to do more, but we need to sit down, relax
1750 and wait a little while first */
1751 multistate(data, CURLM_STATE_DO_MORE);
1752 rc = CURLM_OK;
1753 }
1754 else {
1755 /* we're done with the DO, now DO_DONE */
1756 multistate(data, CURLM_STATE_DO_DONE);
1757 rc = CURLM_CALL_MULTI_PERFORM;
1758 }
1759 }
1760 else if((CURLE_SEND_ERROR == result) &&
1761 data->conn->bits.reuse) {
1762 /*
1763 * In this situation, a connection that we were trying to use
1764 * may have unexpectedly died. If possible, send the connection
1765 * back to the CONNECT phase so we can try again.
1766 */
1767 char *newurl = NULL;
1768 followtype follow = FOLLOW_NONE;
1769 CURLcode drc;
1770
1771 drc = Curl_retry_request(data->conn, &newurl);
1772 if(drc) {
1773 /* a failure here pretty much implies an out of memory */
1774 result = drc;
1775 stream_error = TRUE;
1776 }
1777
1778 Curl_posttransfer(data);
1779 drc = multi_done(data, result, FALSE);
1780
1781 /* When set to retry the connection, we must to go back to
1782 * the CONNECT state */
1783 if(newurl) {
1784 if(!drc || (drc == CURLE_SEND_ERROR)) {
1785 follow = FOLLOW_RETRY;
1786 drc = Curl_follow(data, newurl, follow);
1787 if(!drc) {
1788 multistate(data, CURLM_STATE_CONNECT);
1789 rc = CURLM_CALL_MULTI_PERFORM;
1790 result = CURLE_OK;
1791 }
1792 else {
1793 /* Follow failed */
1794 result = drc;
1795 }
1796 }
1797 else {
1798 /* done didn't return OK or SEND_ERROR */
1799 result = drc;
1800 }
1801 }
1802 else {
1803 /* Have error handler disconnect conn if we can't retry */
1804 stream_error = TRUE;
1805 }
1806 free(newurl);
1807 }
1808 else {
1809 /* failure detected */
1810 Curl_posttransfer(data);
1811 if(data->conn)
1812 multi_done(data, result, FALSE);
1813 stream_error = TRUE;
1814 }
1815 }
1816 break;
1817
1818 case CURLM_STATE_DOING:
1819 /* we continue DOING until the DO phase is complete */
1820 DEBUGASSERT(data->conn);
1821 result = protocol_doing(data->conn, &dophase_done);
1822 if(!result) {
1823 if(dophase_done) {
1824 /* after DO, go DO_DONE or DO_MORE */
1825 multistate(data, data->conn->bits.do_more?
1826 CURLM_STATE_DO_MORE:
1827 CURLM_STATE_DO_DONE);
1828 rc = CURLM_CALL_MULTI_PERFORM;
1829 } /* dophase_done */
1830 }
1831 else {
1832 /* failure detected */
1833 Curl_posttransfer(data);
1834 multi_done(data, result, FALSE);
1835 stream_error = TRUE;
1836 }
1837 break;
1838
1839 case CURLM_STATE_DO_MORE:
1840 /*
1841 * When we are connected, DO MORE and then go DO_DONE
1842 */
1843 DEBUGASSERT(data->conn);
1844 result = multi_do_more(data->conn, &control);
1845
1846 if(!result) {
1847 if(control) {
1848 /* if positive, advance to DO_DONE
1849 if negative, go back to DOING */
1850 multistate(data, control == 1?
1851 CURLM_STATE_DO_DONE:
1852 CURLM_STATE_DOING);
1853 rc = CURLM_CALL_MULTI_PERFORM;
1854 }
1855 else
1856 /* stay in DO_MORE */
1857 rc = CURLM_OK;
1858 }
1859 else {
1860 /* failure detected */
1861 Curl_posttransfer(data);
1862 multi_done(data, result, FALSE);
1863 stream_error = TRUE;
1864 }
1865 break;
1866
1867 case CURLM_STATE_DO_DONE:
1868 DEBUGASSERT(data->conn);
1869 if(data->conn->bits.multiplex)
1870 /* Check if we can move pending requests to send pipe */
1871 process_pending_handles(multi); /* multiplexed */
1872
1873 /* Only perform the transfer if there's a good socket to work with.
1874 Having both BAD is a signal to skip immediately to DONE */
1875 if((data->conn->sockfd != CURL_SOCKET_BAD) ||
1876 (data->conn->writesockfd != CURL_SOCKET_BAD))
1877 multistate(data, CURLM_STATE_PERFORM);
1878 else {
1879 #ifndef CURL_DISABLE_FTP
1880 if(data->state.wildcardmatch &&
1881 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
1882 data->wildcard.state = CURLWC_DONE;
1883 }
1884 #endif
1885 multistate(data, CURLM_STATE_DONE);
1886 }
1887 rc = CURLM_CALL_MULTI_PERFORM;
1888 break;
1889
1890 case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
1891 DEBUGASSERT(data->conn);
1892 /* if both rates are within spec, resume transfer */
1893 if(Curl_pgrsUpdate(data->conn))
1894 result = CURLE_ABORTED_BY_CALLBACK;
1895 else
1896 result = Curl_speedcheck(data, now);
1897
1898 if(!result) {
1899 send_timeout_ms = 0;
1900 if(data->set.max_send_speed > 0)
1901 send_timeout_ms =
1902 Curl_pgrsLimitWaitTime(data->progress.uploaded,
1903 data->progress.ul_limit_size,
1904 data->set.max_send_speed,
1905 data->progress.ul_limit_start,
1906 now);
1907
1908 recv_timeout_ms = 0;
1909 if(data->set.max_recv_speed > 0)
1910 recv_timeout_ms =
1911 Curl_pgrsLimitWaitTime(data->progress.downloaded,
1912 data->progress.dl_limit_size,
1913 data->set.max_recv_speed,
1914 data->progress.dl_limit_start,
1915 now);
1916
1917 if(!send_timeout_ms && !recv_timeout_ms) {
1918 multistate(data, CURLM_STATE_PERFORM);
1919 Curl_ratelimit(data, now);
1920 }
1921 else if(send_timeout_ms >= recv_timeout_ms)
1922 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
1923 else
1924 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
1925 }
1926 break;
1927
1928 case CURLM_STATE_PERFORM:
1929 {
1930 char *newurl = NULL;
1931 bool retry = FALSE;
1932 bool comeback = FALSE;
1933
1934 /* check if over send speed */
1935 send_timeout_ms = 0;
1936 if(data->set.max_send_speed > 0)
1937 send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
1938 data->progress.ul_limit_size,
1939 data->set.max_send_speed,
1940 data->progress.ul_limit_start,
1941 now);
1942
1943 /* check if over recv speed */
1944 recv_timeout_ms = 0;
1945 if(data->set.max_recv_speed > 0)
1946 recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
1947 data->progress.dl_limit_size,
1948 data->set.max_recv_speed,
1949 data->progress.dl_limit_start,
1950 now);
1951
1952 if(send_timeout_ms || recv_timeout_ms) {
1953 Curl_ratelimit(data, now);
1954 multistate(data, CURLM_STATE_TOOFAST);
1955 if(send_timeout_ms >= recv_timeout_ms)
1956 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
1957 else
1958 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
1959 break;
1960 }
1961
1962 /* read/write data if it is ready to do so */
1963 result = Curl_readwrite(data->conn, data, &done, &comeback);
1964
1965 if(done || (result == CURLE_RECV_ERROR)) {
1966 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
1967 * condition and the server closed the re-used connection exactly when
1968 * we wanted to use it, so figure out if that is indeed the case.
1969 */
1970 CURLcode ret = Curl_retry_request(data->conn, &newurl);
1971 if(!ret)
1972 retry = (newurl)?TRUE:FALSE;
1973 else if(!result)
1974 result = ret;
1975
1976 if(retry) {
1977 /* if we are to retry, set the result to OK and consider the
1978 request as done */
1979 result = CURLE_OK;
1980 done = TRUE;
1981 }
1982 }
1983 else if((CURLE_HTTP2_STREAM == result) &&
1984 Curl_h2_http_1_1_error(data->conn)) {
1985 CURLcode ret = Curl_retry_request(data->conn, &newurl);
1986
1987 if(!ret) {
1988 infof(data, "Downgrades to HTTP/1.1!\n");
1989 data->set.httpversion = CURL_HTTP_VERSION_1_1;
1990 /* clear the error message bit too as we ignore the one we got */
1991 data->state.errorbuf = FALSE;
1992 if(!newurl)
1993 /* typically for HTTP_1_1_REQUIRED error on first flight */
1994 newurl = strdup(data->change.url);
1995 /* if we are to retry, set the result to OK and consider the request
1996 as done */
1997 retry = TRUE;
1998 result = CURLE_OK;
1999 done = TRUE;
2000 }
2001 else
2002 result = ret;
2003 }
2004
2005 if(result) {
2006 /*
2007 * The transfer phase returned error, we mark the connection to get
2008 * closed to prevent being re-used. This is because we can't possibly
2009 * know if the connection is in a good shape or not now. Unless it is
2010 * a protocol which uses two "channels" like FTP, as then the error
2011 * happened in the data connection.
2012 */
2013
2014 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2015 result != CURLE_HTTP2_STREAM)
2016 streamclose(data->conn, "Transfer returned error");
2017
2018 Curl_posttransfer(data);
2019 multi_done(data, result, TRUE);
2020 }
2021 else if(done) {
2022 followtype follow = FOLLOW_NONE;
2023
2024 /* call this even if the readwrite function returned error */
2025 Curl_posttransfer(data);
2026
2027 /* When we follow redirects or is set to retry the connection, we must
2028 to go back to the CONNECT state */
2029 if(data->req.newurl || retry) {
2030 if(!retry) {
2031 /* if the URL is a follow-location and not just a retried request
2032 then figure out the URL here */
2033 free(newurl);
2034 newurl = data->req.newurl;
2035 data->req.newurl = NULL;
2036 follow = FOLLOW_REDIR;
2037 }
2038 else
2039 follow = FOLLOW_RETRY;
2040 (void)multi_done(data, CURLE_OK, FALSE);
2041 /* multi_done() might return CURLE_GOT_NOTHING */
2042 result = Curl_follow(data, newurl, follow);
2043 if(!result) {
2044 multistate(data, CURLM_STATE_CONNECT);
2045 rc = CURLM_CALL_MULTI_PERFORM;
2046 }
2047 free(newurl);
2048 }
2049 else {
2050 /* after the transfer is done, go DONE */
2051
2052 /* but first check to see if we got a location info even though we're
2053 not following redirects */
2054 if(data->req.location) {
2055 free(newurl);
2056 newurl = data->req.location;
2057 data->req.location = NULL;
2058 result = Curl_follow(data, newurl, FOLLOW_FAKE);
2059 free(newurl);
2060 if(result) {
2061 stream_error = TRUE;
2062 result = multi_done(data, result, TRUE);
2063 }
2064 }
2065
2066 if(!result) {
2067 multistate(data, CURLM_STATE_DONE);
2068 rc = CURLM_CALL_MULTI_PERFORM;
2069 }
2070 }
2071 }
2072 else if(comeback)
2073 rc = CURLM_CALL_MULTI_PERFORM;
2074 break;
2075 }
2076
2077 case CURLM_STATE_DONE:
2078 /* this state is highly transient, so run another loop after this */
2079 rc = CURLM_CALL_MULTI_PERFORM;
2080
2081 if(data->conn) {
2082 CURLcode res;
2083
2084 if(data->conn->bits.multiplex)
2085 /* Check if we can move pending requests to connection */
2086 process_pending_handles(multi); /* multiplexing */
2087
2088 /* post-transfer command */
2089 res = multi_done(data, result, FALSE);
2090
2091 /* allow a previously set error code take precedence */
2092 if(!result)
2093 result = res;
2094
2095 /*
2096 * If there are other handles on the connection, multi_done won't set
2097 * conn to NULL. In such a case, curl_multi_remove_handle() can
2098 * access free'd data, if the connection is free'd and the handle
2099 * removed before we perform the processing in CURLM_STATE_COMPLETED
2100 */
2101 if(data->conn)
2102 detach_connnection(data);
2103 }
2104
2105 #ifndef CURL_DISABLE_FTP
2106 if(data->state.wildcardmatch) {
2107 if(data->wildcard.state != CURLWC_DONE) {
2108 /* if a wildcard is set and we are not ending -> lets start again
2109 with CURLM_STATE_INIT */
2110 multistate(data, CURLM_STATE_INIT);
2111 break;
2112 }
2113 }
2114 #endif
2115 /* after we have DONE what we're supposed to do, go COMPLETED, and
2116 it doesn't matter what the multi_done() returned! */
2117 multistate(data, CURLM_STATE_COMPLETED);
2118 break;
2119
2120 case CURLM_STATE_COMPLETED:
2121 break;
2122
2123 case CURLM_STATE_MSGSENT:
2124 data->result = result;
2125 return CURLM_OK; /* do nothing */
2126
2127 default:
2128 return CURLM_INTERNAL_ERROR;
2129 }
2130 statemachine_end:
2131
2132 if(data->mstate < CURLM_STATE_COMPLETED) {
2133 if(result) {
2134 /*
2135 * If an error was returned, and we aren't in completed state now,
2136 * then we go to completed and consider this transfer aborted.
2137 */
2138
2139 /* NOTE: no attempt to disconnect connections must be made
2140 in the case blocks above - cleanup happens only here */
2141
2142 /* Check if we can move pending requests to send pipe */
2143 process_pending_handles(multi); /* connection */
2144
2145 if(data->conn) {
2146 if(stream_error) {
2147 /* Don't attempt to send data over a connection that timed out */
2148 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2149 struct connectdata *conn = data->conn;
2150
2151 /* This is where we make sure that the conn pointer is reset.
2152 We don't have to do this in every case block above where a
2153 failure is detected */
2154 detach_connnection(data);
2155
2156 /* disconnect properly */
2157 Curl_disconnect(data, conn, dead_connection);
2158 }
2159 }
2160 else if(data->mstate == CURLM_STATE_CONNECT) {
2161 /* Curl_connect() failed */
2162 (void)Curl_posttransfer(data);
2163 }
2164
2165 multistate(data, CURLM_STATE_COMPLETED);
2166 rc = CURLM_CALL_MULTI_PERFORM;
2167 }
2168 /* if there's still a connection to use, call the progress function */
2169 else if(data->conn && Curl_pgrsUpdate(data->conn)) {
2170 /* aborted due to progress callback return code must close the
2171 connection */
2172 result = CURLE_ABORTED_BY_CALLBACK;
2173 streamclose(data->conn, "Aborted by callback");
2174
2175 /* if not yet in DONE state, go there, otherwise COMPLETED */
2176 multistate(data, (data->mstate < CURLM_STATE_DONE)?
2177 CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
2178 rc = CURLM_CALL_MULTI_PERFORM;
2179 }
2180 }
2181
2182 if(CURLM_STATE_COMPLETED == data->mstate) {
2183 if(data->set.fmultidone) {
2184 /* signal via callback instead */
2185 data->set.fmultidone(data, result);
2186 }
2187 else {
2188 /* now fill in the Curl_message with this info */
2189 msg = &data->msg;
2190
2191 msg->extmsg.msg = CURLMSG_DONE;
2192 msg->extmsg.easy_handle = data;
2193 msg->extmsg.data.result = result;
2194
2195 rc = multi_addmsg(multi, msg);
2196 DEBUGASSERT(!data->conn);
2197 }
2198 multistate(data, CURLM_STATE_MSGSENT);
2199 }
2200 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2201
2202 data->result = result;
2203 return rc;
2204 }
2205
2206
curl_multi_perform(struct Curl_multi * multi,int * running_handles)2207 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2208 {
2209 struct Curl_easy *data;
2210 CURLMcode returncode = CURLM_OK;
2211 struct Curl_tree *t;
2212 struct curltime now = Curl_now();
2213
2214 if(!GOOD_MULTI_HANDLE(multi))
2215 return CURLM_BAD_HANDLE;
2216
2217 if(multi->in_callback)
2218 return CURLM_RECURSIVE_API_CALL;
2219
2220 data = multi->easyp;
2221 while(data) {
2222 CURLMcode result;
2223 SIGPIPE_VARIABLE(pipe_st);
2224
2225 sigpipe_ignore(data, &pipe_st);
2226 result = multi_runsingle(multi, now, data);
2227 sigpipe_restore(&pipe_st);
2228
2229 if(result)
2230 returncode = result;
2231
2232 data = data->next; /* operate on next handle */
2233 }
2234
2235 /*
2236 * Simply remove all expired timers from the splay since handles are dealt
2237 * with unconditionally by this function and curl_multi_timeout() requires
2238 * that already passed/handled expire times are removed from the splay.
2239 *
2240 * It is important that the 'now' value is set at the entry of this function
2241 * and not for the current time as it may have ticked a little while since
2242 * then and then we risk this loop to remove timers that actually have not
2243 * been handled!
2244 */
2245 do {
2246 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2247 if(t)
2248 /* the removed may have another timeout in queue */
2249 (void)add_next_timeout(now, multi, t->payload);
2250
2251 } while(t);
2252
2253 *running_handles = multi->num_alive;
2254
2255 if(CURLM_OK >= returncode)
2256 Curl_update_timer(multi);
2257
2258 return returncode;
2259 }
2260
curl_multi_cleanup(struct Curl_multi * multi)2261 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2262 {
2263 struct Curl_easy *data;
2264 struct Curl_easy *nextdata;
2265
2266 if(GOOD_MULTI_HANDLE(multi)) {
2267 if(multi->in_callback)
2268 return CURLM_RECURSIVE_API_CALL;
2269
2270 multi->type = 0; /* not good anymore */
2271
2272 /* Firsrt remove all remaining easy handles */
2273 data = multi->easyp;
2274 while(data) {
2275 nextdata = data->next;
2276 if(!data->state.done && data->conn)
2277 /* if DONE was never called for this handle */
2278 (void)multi_done(data, CURLE_OK, TRUE);
2279 if(data->dns.hostcachetype == HCACHE_MULTI) {
2280 /* clear out the usage of the shared DNS cache */
2281 Curl_hostcache_clean(data, data->dns.hostcache);
2282 data->dns.hostcache = NULL;
2283 data->dns.hostcachetype = HCACHE_NONE;
2284 }
2285
2286 /* Clear the pointer to the connection cache */
2287 data->state.conn_cache = NULL;
2288 data->multi = NULL; /* clear the association */
2289
2290 #ifdef USE_LIBPSL
2291 if(data->psl == &multi->psl)
2292 data->psl = NULL;
2293 #endif
2294
2295 data = nextdata;
2296 }
2297
2298 /* Close all the connections in the connection cache */
2299 Curl_conncache_close_all_connections(&multi->conn_cache);
2300
2301 Curl_hash_destroy(&multi->sockhash);
2302 Curl_conncache_destroy(&multi->conn_cache);
2303 Curl_llist_destroy(&multi->msglist, NULL);
2304 Curl_llist_destroy(&multi->pending, NULL);
2305
2306 Curl_hash_destroy(&multi->hostcache);
2307 Curl_psl_destroy(&multi->psl);
2308 free(multi);
2309
2310 return CURLM_OK;
2311 }
2312 return CURLM_BAD_HANDLE;
2313 }
2314
2315 /*
2316 * curl_multi_info_read()
2317 *
2318 * This function is the primary way for a multi/multi_socket application to
2319 * figure out if a transfer has ended. We MUST make this function as fast as
2320 * possible as it will be polled frequently and we MUST NOT scan any lists in
2321 * here to figure out things. We must scale fine to thousands of handles and
2322 * beyond. The current design is fully O(1).
2323 */
2324
curl_multi_info_read(struct Curl_multi * multi,int * msgs_in_queue)2325 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2326 {
2327 struct Curl_message *msg;
2328
2329 *msgs_in_queue = 0; /* default to none */
2330
2331 if(GOOD_MULTI_HANDLE(multi) &&
2332 !multi->in_callback &&
2333 Curl_llist_count(&multi->msglist)) {
2334 /* there is one or more messages in the list */
2335 struct curl_llist_element *e;
2336
2337 /* extract the head of the list to return */
2338 e = multi->msglist.head;
2339
2340 msg = e->ptr;
2341
2342 /* remove the extracted entry */
2343 Curl_llist_remove(&multi->msglist, e, NULL);
2344
2345 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2346
2347 return &msg->extmsg;
2348 }
2349 return NULL;
2350 }
2351
2352 /*
2353 * singlesocket() checks what sockets we deal with and their "action state"
2354 * and if we have a different state in any of those sockets from last time we
2355 * call the callback accordingly.
2356 */
singlesocket(struct Curl_multi * multi,struct Curl_easy * data)2357 static CURLMcode singlesocket(struct Curl_multi *multi,
2358 struct Curl_easy *data)
2359 {
2360 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
2361 int i;
2362 struct Curl_sh_entry *entry;
2363 curl_socket_t s;
2364 int num;
2365 unsigned int curraction;
2366 int actions[MAX_SOCKSPEREASYHANDLE];
2367
2368 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
2369 socks[i] = CURL_SOCKET_BAD;
2370
2371 /* Fill in the 'current' struct with the state as it is now: what sockets to
2372 supervise and for what actions */
2373 curraction = multi_getsock(data, socks);
2374
2375 /* We have 0 .. N sockets already and we get to know about the 0 .. M
2376 sockets we should have from now on. Detect the differences, remove no
2377 longer supervised ones and add new ones */
2378
2379 /* walk over the sockets we got right now */
2380 for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
2381 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2382 i++) {
2383 unsigned int action = CURL_POLL_NONE;
2384 unsigned int prevaction = 0;
2385 unsigned int comboaction;
2386 bool sincebefore = FALSE;
2387
2388 s = socks[i];
2389
2390 /* get it from the hash */
2391 entry = sh_getentry(&multi->sockhash, s);
2392
2393 if(curraction & GETSOCK_READSOCK(i))
2394 action |= CURL_POLL_IN;
2395 if(curraction & GETSOCK_WRITESOCK(i))
2396 action |= CURL_POLL_OUT;
2397
2398 actions[i] = action;
2399 if(entry) {
2400 /* check if new for this transfer */
2401 int j;
2402 for(j = 0; j< data->numsocks; j++) {
2403 if(s == data->sockets[j]) {
2404 prevaction = data->actions[j];
2405 sincebefore = TRUE;
2406 break;
2407 }
2408 }
2409 }
2410 else {
2411 /* this is a socket we didn't have before, add it to the hash! */
2412 entry = sh_addentry(&multi->sockhash, s);
2413 if(!entry)
2414 /* fatal */
2415 return CURLM_OUT_OF_MEMORY;
2416 }
2417 if(sincebefore && (prevaction != action)) {
2418 /* Socket was used already, but different action now */
2419 if(prevaction & CURL_POLL_IN)
2420 entry->readers--;
2421 if(prevaction & CURL_POLL_OUT)
2422 entry->writers--;
2423 if(action & CURL_POLL_IN)
2424 entry->readers++;
2425 if(action & CURL_POLL_OUT)
2426 entry->writers++;
2427 }
2428 else if(!sincebefore) {
2429 /* a new user */
2430 entry->users++;
2431 if(action & CURL_POLL_IN)
2432 entry->readers++;
2433 if(action & CURL_POLL_OUT)
2434 entry->writers++;
2435
2436 /* add 'data' to the transfer hash on this socket! */
2437 if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2438 sizeof(struct Curl_easy *), data))
2439 return CURLM_OUT_OF_MEMORY;
2440 }
2441
2442 comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2443 (entry->readers ? CURL_POLL_IN : 0);
2444
2445 /* socket existed before and has the same action set as before */
2446 if(sincebefore && (entry->action == comboaction))
2447 /* same, continue */
2448 continue;
2449
2450 if(multi->socket_cb)
2451 multi->socket_cb(data, s, comboaction, multi->socket_userp,
2452 entry->socketp);
2453
2454 entry->action = comboaction; /* store the current action state */
2455 }
2456
2457 num = i; /* number of sockets */
2458
2459 /* when we've walked over all the sockets we should have right now, we must
2460 make sure to detect sockets that are removed */
2461 for(i = 0; i< data->numsocks; i++) {
2462 int j;
2463 bool stillused = FALSE;
2464 s = data->sockets[i];
2465 for(j = 0; j < num; j++) {
2466 if(s == socks[j]) {
2467 /* this is still supervised */
2468 stillused = TRUE;
2469 break;
2470 }
2471 }
2472 if(stillused)
2473 continue;
2474
2475 entry = sh_getentry(&multi->sockhash, s);
2476 /* if this is NULL here, the socket has been closed and notified so
2477 already by Curl_multi_closed() */
2478 if(entry) {
2479 int oldactions = data->actions[i];
2480 /* this socket has been removed. Decrease user count */
2481 entry->users--;
2482 if(oldactions & CURL_POLL_OUT)
2483 entry->writers--;
2484 if(oldactions & CURL_POLL_IN)
2485 entry->readers--;
2486 if(!entry->users) {
2487 if(multi->socket_cb)
2488 multi->socket_cb(data, s, CURL_POLL_REMOVE,
2489 multi->socket_userp,
2490 entry->socketp);
2491 sh_delentry(entry, &multi->sockhash, s);
2492 }
2493 else {
2494 /* still users, but remove this handle as a user of this socket */
2495 if(Curl_hash_delete(&entry->transfers, (char *)&data,
2496 sizeof(struct Curl_easy *))) {
2497 DEBUGASSERT(NULL);
2498 }
2499 }
2500 }
2501 } /* for loop over numsocks */
2502
2503 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2504 memcpy(data->actions, actions, num*sizeof(int));
2505 data->numsocks = num;
2506 return CURLM_OK;
2507 }
2508
Curl_updatesocket(struct Curl_easy * data)2509 void Curl_updatesocket(struct Curl_easy *data)
2510 {
2511 singlesocket(data->multi, data);
2512 }
2513
2514
2515 /*
2516 * Curl_multi_closed()
2517 *
2518 * Used by the connect code to tell the multi_socket code that one of the
2519 * sockets we were using is about to be closed. This function will then
2520 * remove it from the sockethash for this handle to make the multi_socket API
2521 * behave properly, especially for the case when libcurl will create another
2522 * socket again and it gets the same file descriptor number.
2523 */
2524
Curl_multi_closed(struct Curl_easy * data,curl_socket_t s)2525 void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
2526 {
2527 if(data) {
2528 /* if there's still an easy handle associated with this connection */
2529 struct Curl_multi *multi = data->multi;
2530 if(multi) {
2531 /* this is set if this connection is part of a handle that is added to
2532 a multi handle, and only then this is necessary */
2533 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2534
2535 if(entry) {
2536 if(multi->socket_cb)
2537 multi->socket_cb(data, s, CURL_POLL_REMOVE,
2538 multi->socket_userp,
2539 entry->socketp);
2540
2541 /* now remove it from the socket hash */
2542 sh_delentry(entry, &multi->sockhash, s);
2543 }
2544 }
2545 }
2546 }
2547
2548 /*
2549 * add_next_timeout()
2550 *
2551 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
2552 * when it has just been removed from the splay tree because the timeout has
2553 * expired. This function is then to advance in the list to pick the next
2554 * timeout to use (skip the already expired ones) and add this node back to
2555 * the splay tree again.
2556 *
2557 * The splay tree only has each sessionhandle as a single node and the nearest
2558 * timeout is used to sort it on.
2559 */
add_next_timeout(struct curltime now,struct Curl_multi * multi,struct Curl_easy * d)2560 static CURLMcode add_next_timeout(struct curltime now,
2561 struct Curl_multi *multi,
2562 struct Curl_easy *d)
2563 {
2564 struct curltime *tv = &d->state.expiretime;
2565 struct curl_llist *list = &d->state.timeoutlist;
2566 struct curl_llist_element *e;
2567 struct time_node *node = NULL;
2568
2569 /* move over the timeout list for this specific handle and remove all
2570 timeouts that are now passed tense and store the next pending
2571 timeout in *tv */
2572 for(e = list->head; e;) {
2573 struct curl_llist_element *n = e->next;
2574 timediff_t diff;
2575 node = (struct time_node *)e->ptr;
2576 diff = Curl_timediff(node->time, now);
2577 if(diff <= 0)
2578 /* remove outdated entry */
2579 Curl_llist_remove(list, e, NULL);
2580 else
2581 /* the list is sorted so get out on the first mismatch */
2582 break;
2583 e = n;
2584 }
2585 e = list->head;
2586 if(!e) {
2587 /* clear the expire times within the handles that we remove from the
2588 splay tree */
2589 tv->tv_sec = 0;
2590 tv->tv_usec = 0;
2591 }
2592 else {
2593 /* copy the first entry to 'tv' */
2594 memcpy(tv, &node->time, sizeof(*tv));
2595
2596 /* Insert this node again into the splay. Keep the timer in the list in
2597 case we need to recompute future timers. */
2598 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2599 &d->state.timenode);
2600 }
2601 return CURLM_OK;
2602 }
2603
multi_socket(struct Curl_multi * multi,bool checkall,curl_socket_t s,int ev_bitmask,int * running_handles)2604 static CURLMcode multi_socket(struct Curl_multi *multi,
2605 bool checkall,
2606 curl_socket_t s,
2607 int ev_bitmask,
2608 int *running_handles)
2609 {
2610 CURLMcode result = CURLM_OK;
2611 struct Curl_easy *data = NULL;
2612 struct Curl_tree *t;
2613 struct curltime now = Curl_now();
2614
2615 if(checkall) {
2616 /* *perform() deals with running_handles on its own */
2617 result = curl_multi_perform(multi, running_handles);
2618
2619 /* walk through each easy handle and do the socket state change magic
2620 and callbacks */
2621 if(result != CURLM_BAD_HANDLE) {
2622 data = multi->easyp;
2623 while(data && !result) {
2624 result = singlesocket(multi, data);
2625 data = data->next;
2626 }
2627 }
2628
2629 /* or should we fall-through and do the timer-based stuff? */
2630 return result;
2631 }
2632 if(s != CURL_SOCKET_TIMEOUT) {
2633 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2634
2635 if(!entry)
2636 /* Unmatched socket, we can't act on it but we ignore this fact. In
2637 real-world tests it has been proved that libevent can in fact give
2638 the application actions even though the socket was just previously
2639 asked to get removed, so thus we better survive stray socket actions
2640 and just move on. */
2641 ;
2642 else {
2643 struct curl_hash_iterator iter;
2644 struct curl_hash_element *he;
2645
2646 /* the socket can be shared by many transfers, iterate */
2647 Curl_hash_start_iterate(&entry->transfers, &iter);
2648 for(he = Curl_hash_next_element(&iter); he;
2649 he = Curl_hash_next_element(&iter)) {
2650 data = (struct Curl_easy *)he->ptr;
2651 DEBUGASSERT(data);
2652 DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
2653
2654 if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
2655 /* set socket event bitmask if they're not locked */
2656 data->conn->cselect_bits = ev_bitmask;
2657
2658 Curl_expire(data, 0, EXPIRE_RUN_NOW);
2659 }
2660
2661 /* Now we fall-through and do the timer-based stuff, since we don't want
2662 to force the user to have to deal with timeouts as long as at least
2663 one connection in fact has traffic. */
2664
2665 data = NULL; /* set data to NULL again to avoid calling
2666 multi_runsingle() in case there's no need to */
2667 now = Curl_now(); /* get a newer time since the multi_runsingle() loop
2668 may have taken some time */
2669 }
2670 }
2671 else {
2672 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
2673 Curl_update_timer() to trigger a callback to the app again even if the
2674 same timeout is still the one to run after this call. That handles the
2675 case when the application asks libcurl to run the timeout
2676 prematurely. */
2677 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
2678 }
2679
2680 /*
2681 * The loop following here will go on as long as there are expire-times left
2682 * to process in the splay and 'data' will be re-assigned for every expired
2683 * handle we deal with.
2684 */
2685 do {
2686 /* the first loop lap 'data' can be NULL */
2687 if(data) {
2688 SIGPIPE_VARIABLE(pipe_st);
2689
2690 sigpipe_ignore(data, &pipe_st);
2691 result = multi_runsingle(multi, now, data);
2692 sigpipe_restore(&pipe_st);
2693
2694 if(CURLM_OK >= result) {
2695 /* get the socket(s) and check if the state has been changed since
2696 last */
2697 result = singlesocket(multi, data);
2698 if(result)
2699 return result;
2700 }
2701 }
2702
2703 /* Check if there's one (more) expired timer to deal with! This function
2704 extracts a matching node if there is one */
2705
2706 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2707 if(t) {
2708 data = t->payload; /* assign this for next loop */
2709 (void)add_next_timeout(now, multi, t->payload);
2710 }
2711
2712 } while(t);
2713
2714 *running_handles = multi->num_alive;
2715 return result;
2716 }
2717
2718 #undef curl_multi_setopt
curl_multi_setopt(struct Curl_multi * multi,CURLMoption option,...)2719 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
2720 CURLMoption option, ...)
2721 {
2722 CURLMcode res = CURLM_OK;
2723 va_list param;
2724
2725 if(!GOOD_MULTI_HANDLE(multi))
2726 return CURLM_BAD_HANDLE;
2727
2728 if(multi->in_callback)
2729 return CURLM_RECURSIVE_API_CALL;
2730
2731 va_start(param, option);
2732
2733 switch(option) {
2734 case CURLMOPT_SOCKETFUNCTION:
2735 multi->socket_cb = va_arg(param, curl_socket_callback);
2736 break;
2737 case CURLMOPT_SOCKETDATA:
2738 multi->socket_userp = va_arg(param, void *);
2739 break;
2740 case CURLMOPT_PUSHFUNCTION:
2741 multi->push_cb = va_arg(param, curl_push_callback);
2742 break;
2743 case CURLMOPT_PUSHDATA:
2744 multi->push_userp = va_arg(param, void *);
2745 break;
2746 case CURLMOPT_PIPELINING:
2747 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
2748 break;
2749 case CURLMOPT_TIMERFUNCTION:
2750 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
2751 break;
2752 case CURLMOPT_TIMERDATA:
2753 multi->timer_userp = va_arg(param, void *);
2754 break;
2755 case CURLMOPT_MAXCONNECTS:
2756 multi->maxconnects = va_arg(param, long);
2757 break;
2758 case CURLMOPT_MAX_HOST_CONNECTIONS:
2759 multi->max_host_connections = va_arg(param, long);
2760 break;
2761 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
2762 multi->max_total_connections = va_arg(param, long);
2763 break;
2764 /* options formerly used for pipelining */
2765 case CURLMOPT_MAX_PIPELINE_LENGTH:
2766 break;
2767 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
2768 break;
2769 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
2770 break;
2771 case CURLMOPT_PIPELINING_SITE_BL:
2772 break;
2773 case CURLMOPT_PIPELINING_SERVER_BL:
2774 break;
2775 case CURLMOPT_MAX_CONCURRENT_STREAMS:
2776 {
2777 long streams = va_arg(param, long);
2778 if(streams < 1)
2779 streams = 100;
2780 multi->max_concurrent_streams =
2781 (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)?
2782 (long)INITIAL_MAX_CONCURRENT_STREAMS : streams;
2783 }
2784 break;
2785 default:
2786 res = CURLM_UNKNOWN_OPTION;
2787 break;
2788 }
2789 va_end(param);
2790 return res;
2791 }
2792
2793 /* we define curl_multi_socket() in the public multi.h header */
2794 #undef curl_multi_socket
2795
curl_multi_socket(struct Curl_multi * multi,curl_socket_t s,int * running_handles)2796 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
2797 int *running_handles)
2798 {
2799 CURLMcode result;
2800 if(multi->in_callback)
2801 return CURLM_RECURSIVE_API_CALL;
2802 result = multi_socket(multi, FALSE, s, 0, running_handles);
2803 if(CURLM_OK >= result)
2804 Curl_update_timer(multi);
2805 return result;
2806 }
2807
curl_multi_socket_action(struct Curl_multi * multi,curl_socket_t s,int ev_bitmask,int * running_handles)2808 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
2809 int ev_bitmask, int *running_handles)
2810 {
2811 CURLMcode result;
2812 if(multi->in_callback)
2813 return CURLM_RECURSIVE_API_CALL;
2814 result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
2815 if(CURLM_OK >= result)
2816 Curl_update_timer(multi);
2817 return result;
2818 }
2819
curl_multi_socket_all(struct Curl_multi * multi,int * running_handles)2820 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
2821
2822 {
2823 CURLMcode result;
2824 if(multi->in_callback)
2825 return CURLM_RECURSIVE_API_CALL;
2826 result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
2827 if(CURLM_OK >= result)
2828 Curl_update_timer(multi);
2829 return result;
2830 }
2831
multi_timeout(struct Curl_multi * multi,long * timeout_ms)2832 static CURLMcode multi_timeout(struct Curl_multi *multi,
2833 long *timeout_ms)
2834 {
2835 static struct curltime tv_zero = {0, 0};
2836
2837 if(multi->timetree) {
2838 /* we have a tree of expire times */
2839 struct curltime now = Curl_now();
2840
2841 /* splay the lowest to the bottom */
2842 multi->timetree = Curl_splay(tv_zero, multi->timetree);
2843
2844 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
2845 /* some time left before expiration */
2846 timediff_t diff = Curl_timediff(multi->timetree->key, now);
2847 if(diff <= 0)
2848 /*
2849 * Since we only provide millisecond resolution on the returned value
2850 * and the diff might be less than one millisecond here, we don't
2851 * return zero as that may cause short bursts of busyloops on fast
2852 * processors while the diff is still present but less than one
2853 * millisecond! instead we return 1 until the time is ripe.
2854 */
2855 *timeout_ms = 1;
2856 else
2857 /* this should be safe even on 64 bit archs, as we don't use that
2858 overly long timeouts */
2859 *timeout_ms = (long)diff;
2860 }
2861 else
2862 /* 0 means immediately */
2863 *timeout_ms = 0;
2864 }
2865 else
2866 *timeout_ms = -1;
2867
2868 return CURLM_OK;
2869 }
2870
curl_multi_timeout(struct Curl_multi * multi,long * timeout_ms)2871 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
2872 long *timeout_ms)
2873 {
2874 /* First, make some basic checks that the CURLM handle is a good handle */
2875 if(!GOOD_MULTI_HANDLE(multi))
2876 return CURLM_BAD_HANDLE;
2877
2878 if(multi->in_callback)
2879 return CURLM_RECURSIVE_API_CALL;
2880
2881 return multi_timeout(multi, timeout_ms);
2882 }
2883
2884 /*
2885 * Tell the application it should update its timers, if it subscribes to the
2886 * update timer callback.
2887 */
Curl_update_timer(struct Curl_multi * multi)2888 void Curl_update_timer(struct Curl_multi *multi)
2889 {
2890 long timeout_ms;
2891
2892 if(!multi->timer_cb)
2893 return;
2894 if(multi_timeout(multi, &timeout_ms)) {
2895 return;
2896 }
2897 if(timeout_ms < 0) {
2898 static const struct curltime none = {0, 0};
2899 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
2900 multi->timer_lastcall = none;
2901 /* there's no timeout now but there was one previously, tell the app to
2902 disable it */
2903 multi->timer_cb(multi, -1, multi->timer_userp);
2904 return;
2905 }
2906 return;
2907 }
2908
2909 /* When multi_timeout() is done, multi->timetree points to the node with the
2910 * timeout we got the (relative) time-out time for. We can thus easily check
2911 * if this is the same (fixed) time as we got in a previous call and then
2912 * avoid calling the callback again. */
2913 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
2914 return;
2915
2916 multi->timer_lastcall = multi->timetree->key;
2917
2918 multi->timer_cb(multi, timeout_ms, multi->timer_userp);
2919 }
2920
2921 /*
2922 * multi_deltimeout()
2923 *
2924 * Remove a given timestamp from the list of timeouts.
2925 */
2926 static void
multi_deltimeout(struct Curl_easy * data,expire_id eid)2927 multi_deltimeout(struct Curl_easy *data, expire_id eid)
2928 {
2929 struct curl_llist_element *e;
2930 struct curl_llist *timeoutlist = &data->state.timeoutlist;
2931 /* find and remove the specific node from the list */
2932 for(e = timeoutlist->head; e; e = e->next) {
2933 struct time_node *n = (struct time_node *)e->ptr;
2934 if(n->eid == eid) {
2935 Curl_llist_remove(timeoutlist, e, NULL);
2936 return;
2937 }
2938 }
2939 }
2940
2941 /*
2942 * multi_addtimeout()
2943 *
2944 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
2945 * of list is always the timeout nearest in time.
2946 *
2947 */
2948 static CURLMcode
multi_addtimeout(struct Curl_easy * data,struct curltime * stamp,expire_id eid)2949 multi_addtimeout(struct Curl_easy *data,
2950 struct curltime *stamp,
2951 expire_id eid)
2952 {
2953 struct curl_llist_element *e;
2954 struct time_node *node;
2955 struct curl_llist_element *prev = NULL;
2956 size_t n;
2957 struct curl_llist *timeoutlist = &data->state.timeoutlist;
2958
2959 node = &data->state.expires[eid];
2960
2961 /* copy the timestamp and id */
2962 memcpy(&node->time, stamp, sizeof(*stamp));
2963 node->eid = eid; /* also marks it as in use */
2964
2965 n = Curl_llist_count(timeoutlist);
2966 if(n) {
2967 /* find the correct spot in the list */
2968 for(e = timeoutlist->head; e; e = e->next) {
2969 struct time_node *check = (struct time_node *)e->ptr;
2970 timediff_t diff = Curl_timediff(check->time, node->time);
2971 if(diff > 0)
2972 break;
2973 prev = e;
2974 }
2975
2976 }
2977 /* else
2978 this is the first timeout on the list */
2979
2980 Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
2981 return CURLM_OK;
2982 }
2983
2984 /*
2985 * Curl_expire()
2986 *
2987 * given a number of milliseconds from now to use to set the 'act before
2988 * this'-time for the transfer, to be extracted by curl_multi_timeout()
2989 *
2990 * The timeout will be added to a queue of timeouts if it defines a moment in
2991 * time that is later than the current head of queue.
2992 *
2993 * Expire replaces a former timeout using the same id if already set.
2994 */
Curl_expire(struct Curl_easy * data,timediff_t milli,expire_id id)2995 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
2996 {
2997 struct Curl_multi *multi = data->multi;
2998 struct curltime *nowp = &data->state.expiretime;
2999 struct curltime set;
3000
3001 /* this is only interesting while there is still an associated multi struct
3002 remaining! */
3003 if(!multi)
3004 return;
3005
3006 DEBUGASSERT(id < EXPIRE_LAST);
3007
3008 set = Curl_now();
3009 set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3010 set.tv_usec += (unsigned int)(milli%1000)*1000;
3011
3012 if(set.tv_usec >= 1000000) {
3013 set.tv_sec++;
3014 set.tv_usec -= 1000000;
3015 }
3016
3017 /* Remove any timer with the same id just in case. */
3018 multi_deltimeout(data, id);
3019
3020 /* Add it to the timer list. It must stay in the list until it has expired
3021 in case we need to recompute the minimum timer later. */
3022 multi_addtimeout(data, &set, id);
3023
3024 if(nowp->tv_sec || nowp->tv_usec) {
3025 /* This means that the struct is added as a node in the splay tree.
3026 Compare if the new time is earlier, and only remove-old/add-new if it
3027 is. */
3028 timediff_t diff = Curl_timediff(set, *nowp);
3029 int rc;
3030
3031 if(diff > 0) {
3032 /* The current splay tree entry is sooner than this new expiry time.
3033 We don't need to update our splay tree entry. */
3034 return;
3035 }
3036
3037 /* Since this is an updated time, we must remove the previous entry from
3038 the splay tree first and then re-add the new value */
3039 rc = Curl_splayremovebyaddr(multi->timetree,
3040 &data->state.timenode,
3041 &multi->timetree);
3042 if(rc)
3043 infof(data, "Internal error removing splay node = %d\n", rc);
3044 }
3045
3046 /* Indicate that we are in the splay tree and insert the new timer expiry
3047 value since it is our local minimum. */
3048 *nowp = set;
3049 data->state.timenode.payload = data;
3050 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3051 &data->state.timenode);
3052 }
3053
3054 /*
3055 * Curl_expire_done()
3056 *
3057 * Removes the expire timer. Marks it as done.
3058 *
3059 */
Curl_expire_done(struct Curl_easy * data,expire_id id)3060 void Curl_expire_done(struct Curl_easy *data, expire_id id)
3061 {
3062 /* remove the timer, if there */
3063 multi_deltimeout(data, id);
3064 }
3065
3066 /*
3067 * Curl_expire_clear()
3068 *
3069 * Clear ALL timeout values for this handle.
3070 */
Curl_expire_clear(struct Curl_easy * data)3071 void Curl_expire_clear(struct Curl_easy *data)
3072 {
3073 struct Curl_multi *multi = data->multi;
3074 struct curltime *nowp = &data->state.expiretime;
3075
3076 /* this is only interesting while there is still an associated multi struct
3077 remaining! */
3078 if(!multi)
3079 return;
3080
3081 if(nowp->tv_sec || nowp->tv_usec) {
3082 /* Since this is an cleared time, we must remove the previous entry from
3083 the splay tree */
3084 struct curl_llist *list = &data->state.timeoutlist;
3085 int rc;
3086
3087 rc = Curl_splayremovebyaddr(multi->timetree,
3088 &data->state.timenode,
3089 &multi->timetree);
3090 if(rc)
3091 infof(data, "Internal error clearing splay node = %d\n", rc);
3092
3093 /* flush the timeout list too */
3094 while(list->size > 0) {
3095 Curl_llist_remove(list, list->tail, NULL);
3096 }
3097
3098 #ifdef DEBUGBUILD
3099 infof(data, "Expire cleared (transfer %p)\n", data);
3100 #endif
3101 nowp->tv_sec = 0;
3102 nowp->tv_usec = 0;
3103 }
3104 }
3105
3106
3107
3108
curl_multi_assign(struct Curl_multi * multi,curl_socket_t s,void * hashp)3109 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3110 void *hashp)
3111 {
3112 struct Curl_sh_entry *there = NULL;
3113
3114 if(multi->in_callback)
3115 return CURLM_RECURSIVE_API_CALL;
3116
3117 there = sh_getentry(&multi->sockhash, s);
3118
3119 if(!there)
3120 return CURLM_BAD_SOCKET;
3121
3122 there->socketp = hashp;
3123
3124 return CURLM_OK;
3125 }
3126
Curl_multi_max_host_connections(struct Curl_multi * multi)3127 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3128 {
3129 return multi ? multi->max_host_connections : 0;
3130 }
3131
Curl_multi_max_total_connections(struct Curl_multi * multi)3132 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3133 {
3134 return multi ? multi->max_total_connections : 0;
3135 }
3136
3137 /*
3138 * When information about a connection has appeared, call this!
3139 */
3140
Curl_multiuse_state(struct connectdata * conn,int bundlestate)3141 void Curl_multiuse_state(struct connectdata *conn,
3142 int bundlestate) /* use BUNDLE_* defines */
3143 {
3144 DEBUGASSERT(conn);
3145 DEBUGASSERT(conn->bundle);
3146 DEBUGASSERT(conn->data);
3147 DEBUGASSERT(conn->data->multi);
3148
3149 conn->bundle->multiuse = bundlestate;
3150 process_pending_handles(conn->data->multi);
3151 }
3152
process_pending_handles(struct Curl_multi * multi)3153 static void process_pending_handles(struct Curl_multi *multi)
3154 {
3155 struct curl_llist_element *e = multi->pending.head;
3156 if(e) {
3157 struct Curl_easy *data = e->ptr;
3158
3159 DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND);
3160
3161 multistate(data, CURLM_STATE_CONNECT);
3162
3163 /* Remove this node from the list */
3164 Curl_llist_remove(&multi->pending, e, NULL);
3165
3166 /* Make sure that the handle will be processed soonish. */
3167 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3168
3169 /* mark this as having been in the pending queue */
3170 data->state.previouslypending = TRUE;
3171 }
3172 }
3173
Curl_set_in_callback(struct Curl_easy * data,bool value)3174 void Curl_set_in_callback(struct Curl_easy *data, bool value)
3175 {
3176 /* might get called when there is no data pointer! */
3177 if(data) {
3178 if(data->multi_easy)
3179 data->multi_easy->in_callback = value;
3180 else if(data->multi)
3181 data->multi->in_callback = value;
3182 }
3183 }
3184
Curl_is_in_callback(struct Curl_easy * easy)3185 bool Curl_is_in_callback(struct Curl_easy *easy)
3186 {
3187 return ((easy->multi && easy->multi->in_callback) ||
3188 (easy->multi_easy && easy->multi_easy->in_callback));
3189 }
3190
3191 #ifdef DEBUGBUILD
Curl_multi_dump(struct Curl_multi * multi)3192 void Curl_multi_dump(struct Curl_multi *multi)
3193 {
3194 struct Curl_easy *data;
3195 int i;
3196 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
3197 multi->num_easy, multi->num_alive);
3198 for(data = multi->easyp; data; data = data->next) {
3199 if(data->mstate < CURLM_STATE_COMPLETED) {
3200 /* only display handles that are not completed */
3201 fprintf(stderr, "handle %p, state %s, %d sockets\n",
3202 (void *)data,
3203 statename[data->mstate], data->numsocks);
3204 for(i = 0; i < data->numsocks; i++) {
3205 curl_socket_t s = data->sockets[i];
3206 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3207
3208 fprintf(stderr, "%d ", (int)s);
3209 if(!entry) {
3210 fprintf(stderr, "INTERNAL CONFUSION\n");
3211 continue;
3212 }
3213 fprintf(stderr, "[%s %s] ",
3214 (entry->action&CURL_POLL_IN)?"RECVING":"",
3215 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3216 }
3217 if(data->numsocks)
3218 fprintf(stderr, "\n");
3219 }
3220 }
3221 }
3222 #endif
3223
Curl_multi_max_concurrent_streams(struct Curl_multi * multi)3224 size_t Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3225 {
3226 return multi ? ((size_t)multi->max_concurrent_streams ?
3227 (size_t)multi->max_concurrent_streams : 100) : 0;
3228 }
3229