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