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 FD_SET(sockbunch[i], read_fd_set);
1057 s = sockbunch[i];
1058 }
1059 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1060 FD_SET(sockbunch[i], write_fd_set);
1061 s = sockbunch[i];
1062 }
1063 if(s == CURL_SOCKET_BAD)
1064 /* this socket is unused, break out of loop */
1065 break;
1066 if((int)s > this_max_fd)
1067 this_max_fd = (int)s;
1068 }
1069
1070 data = data->next; /* check next handle */
1071 }
1072
1073 *max_fd = this_max_fd;
1074
1075 return CURLM_OK;
1076 }
1077
1078 #define NUM_POLLS_ON_STACK 10
1079
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)1080 static CURLMcode multi_wait(struct Curl_multi *multi,
1081 struct curl_waitfd extra_fds[],
1082 unsigned int extra_nfds,
1083 int timeout_ms,
1084 int *ret,
1085 bool extrawait, /* when no socket, wait */
1086 bool use_wakeup)
1087 {
1088 struct Curl_easy *data;
1089 curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
1090 int bitmap;
1091 unsigned int i;
1092 unsigned int nfds = 0;
1093 unsigned int curlfds;
1094 long timeout_internal;
1095 int retcode = 0;
1096 struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
1097 struct pollfd *ufds = &a_few_on_stack[0];
1098 bool ufds_malloc = FALSE;
1099 #ifdef USE_WINSOCK
1100 WSANETWORKEVENTS wsa_events;
1101 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1102 #endif
1103
1104 if(!GOOD_MULTI_HANDLE(multi))
1105 return CURLM_BAD_HANDLE;
1106
1107 if(multi->in_callback)
1108 return CURLM_RECURSIVE_API_CALL;
1109
1110 if(timeout_ms < 0)
1111 return CURLM_BAD_FUNCTION_ARGUMENT;
1112
1113 /* Count up how many fds we have from the multi handle */
1114 data = multi->easyp;
1115 while(data) {
1116 bitmap = multi_getsock(data, sockbunch);
1117
1118 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
1119 curl_socket_t s = CURL_SOCKET_BAD;
1120
1121 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1122 ++nfds;
1123 s = sockbunch[i];
1124 }
1125 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1126 ++nfds;
1127 s = sockbunch[i];
1128 }
1129 if(s == CURL_SOCKET_BAD) {
1130 break;
1131 }
1132 }
1133
1134 data = data->next; /* check next handle */
1135 }
1136
1137 /* If the internally desired timeout is actually shorter than requested from
1138 the outside, then use the shorter time! But only if the internal timer
1139 is actually larger than -1! */
1140 (void)multi_timeout(multi, &timeout_internal);
1141 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
1142 timeout_ms = (int)timeout_internal;
1143
1144 curlfds = nfds; /* number of internal file descriptors */
1145 nfds += extra_nfds; /* add the externally provided ones */
1146
1147 #ifdef ENABLE_WAKEUP
1148 #ifdef USE_WINSOCK
1149 if(use_wakeup) {
1150 #else
1151 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1152 #endif
1153 ++nfds;
1154 }
1155 #endif
1156
1157 if(nfds > NUM_POLLS_ON_STACK) {
1158 /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
1159 big, so at 2^29 sockets this value might wrap. When a process gets
1160 the capability to actually handle over 500 million sockets this
1161 calculation needs a integer overflow check. */
1162 ufds = malloc(nfds * sizeof(struct pollfd));
1163 if(!ufds)
1164 return CURLM_OUT_OF_MEMORY;
1165 ufds_malloc = TRUE;
1166 }
1167 nfds = 0;
1168
1169 /* only do the second loop if we found descriptors in the first stage run
1170 above */
1171
1172 if(curlfds) {
1173 /* Add the curl handles to our pollfds first */
1174 data = multi->easyp;
1175 while(data) {
1176 bitmap = multi_getsock(data, sockbunch);
1177
1178 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1179 curl_socket_t s = CURL_SOCKET_BAD;
1180 #ifdef USE_WINSOCK
1181 long mask = 0;
1182 #endif
1183 if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1184 s = sockbunch[i];
1185 #ifdef USE_WINSOCK
1186 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1187 #endif
1188 ufds[nfds].fd = s;
1189 ufds[nfds].events = POLLIN;
1190 ++nfds;
1191 }
1192 if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
1193 s = sockbunch[i];
1194 #ifdef USE_WINSOCK
1195 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1196 send(s, NULL, 0, 0); /* reset FD_WRITE */
1197 #endif
1198 ufds[nfds].fd = s;
1199 ufds[nfds].events = POLLOUT;
1200 ++nfds;
1201 }
1202 /* s is only set if either being readable or writable is checked */
1203 if(s == CURL_SOCKET_BAD) {
1204 /* break on entry not checked for being readable or writable */
1205 break;
1206 }
1207 #ifdef USE_WINSOCK
1208 if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
1209 if(ufds_malloc)
1210 free(ufds);
1211 return CURLM_INTERNAL_ERROR;
1212 }
1213 #endif
1214 }
1215
1216 data = data->next; /* check next handle */
1217 }
1218 }
1219
1220 /* Add external file descriptions from poll-like struct curl_waitfd */
1221 for(i = 0; i < extra_nfds; i++) {
1222 #ifdef USE_WINSOCK
1223 long mask = 0;
1224 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1225 mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1226 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1227 mask |= FD_OOB;
1228 if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1229 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1230 send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
1231 }
1232 if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1233 if(ufds_malloc)
1234 free(ufds);
1235 return CURLM_INTERNAL_ERROR;
1236 }
1237 #endif
1238 ufds[nfds].fd = extra_fds[i].fd;
1239 ufds[nfds].events = 0;
1240 if(extra_fds[i].events & CURL_WAIT_POLLIN)
1241 ufds[nfds].events |= POLLIN;
1242 if(extra_fds[i].events & CURL_WAIT_POLLPRI)
1243 ufds[nfds].events |= POLLPRI;
1244 if(extra_fds[i].events & CURL_WAIT_POLLOUT)
1245 ufds[nfds].events |= POLLOUT;
1246 ++nfds;
1247 }
1248
1249 #ifdef ENABLE_WAKEUP
1250 #ifndef USE_WINSOCK
1251 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1252 ufds[nfds].fd = multi->wakeup_pair[0];
1253 ufds[nfds].events = POLLIN;
1254 ++nfds;
1255 }
1256 #endif
1257 #endif
1258
1259 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1260 if(nfds || use_wakeup) {
1261 #else
1262 if(nfds) {
1263 #endif
1264 int pollrc;
1265 #ifdef USE_WINSOCK
1266 if(nfds)
1267 pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
1268 else
1269 pollrc = 0;
1270 if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
1271 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1272 #else
1273 pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
1274 #endif
1275
1276 if(pollrc > 0) {
1277 retcode = pollrc;
1278 #ifdef USE_WINSOCK
1279 }
1280 /* With WinSock, we have to run the following section unconditionally
1281 to call WSAEventSelect(fd, event, 0) on all the sockets */
1282 {
1283 #endif
1284 /* copy revents results from the poll to the curl_multi_wait poll
1285 struct, the bit values of the actual underlying poll() implementation
1286 may not be the same as the ones in the public libcurl API! */
1287 for(i = 0; i < extra_nfds; i++) {
1288 unsigned r = ufds[curlfds + i].revents;
1289 unsigned short mask = 0;
1290 #ifdef USE_WINSOCK
1291 wsa_events.lNetworkEvents = 0;
1292 if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
1293 if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1294 mask |= CURL_WAIT_POLLIN;
1295 if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1296 mask |= CURL_WAIT_POLLOUT;
1297 if(wsa_events.lNetworkEvents & FD_OOB)
1298 mask |= CURL_WAIT_POLLPRI;
1299 if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1300 retcode++;
1301 }
1302 WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
1303 if(pollrc <= 0)
1304 continue;
1305 #endif
1306 if(r & POLLIN)
1307 mask |= CURL_WAIT_POLLIN;
1308 if(r & POLLOUT)
1309 mask |= CURL_WAIT_POLLOUT;
1310 if(r & POLLPRI)
1311 mask |= CURL_WAIT_POLLPRI;
1312 extra_fds[i].revents = mask;
1313 }
1314
1315 #ifdef USE_WINSOCK
1316 /* Count up all our own sockets that had activity,
1317 and remove them from the event. */
1318 if(curlfds) {
1319 data = multi->easyp;
1320 while(data) {
1321 bitmap = multi_getsock(data, sockbunch);
1322
1323 for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1324 if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
1325 wsa_events.lNetworkEvents = 0;
1326 if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
1327 if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
1328 retcode++;
1329 }
1330 WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1331 }
1332 else {
1333 /* break on entry not checked for being readable or writable */
1334 break;
1335 }
1336 }
1337
1338 data = data->next;
1339 }
1340 }
1341
1342 WSAResetEvent(multi->wsa_event);
1343 #else
1344 #ifdef ENABLE_WAKEUP
1345 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1346 if(ufds[curlfds + extra_nfds].revents & POLLIN) {
1347 char buf[64];
1348 ssize_t nread;
1349 while(1) {
1350 /* the reading socket is non-blocking, try to read
1351 data from it until it receives an error (except EINTR).
1352 In normal cases it will get EAGAIN or EWOULDBLOCK
1353 when there is no more data, breaking the loop. */
1354 nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
1355 if(nread <= 0) {
1356 if(nread < 0 && EINTR == SOCKERRNO)
1357 continue;
1358 break;
1359 }
1360 }
1361 /* do not count the wakeup socket into the returned value */
1362 retcode--;
1363 }
1364 }
1365 #endif
1366 #endif
1367 }
1368 }
1369
1370 if(ufds_malloc)
1371 free(ufds);
1372 if(ret)
1373 *ret = retcode;
1374 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK)
1375 if(extrawait && !nfds && !use_wakeup) {
1376 #else
1377 if(extrawait && !nfds) {
1378 #endif
1379 long sleep_ms = 0;
1380
1381 /* Avoid busy-looping when there's nothing particular to wait for */
1382 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1383 if(sleep_ms > timeout_ms)
1384 sleep_ms = timeout_ms;
1385 /* when there are no easy handles in the multi, this holds a -1
1386 timeout */
1387 else if(sleep_ms < 0)
1388 sleep_ms = timeout_ms;
1389 Curl_wait_ms(sleep_ms);
1390 }
1391 }
1392
1393 return CURLM_OK;
1394 }
1395
1396 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1397 struct curl_waitfd extra_fds[],
1398 unsigned int extra_nfds,
1399 int timeout_ms,
1400 int *ret)
1401 {
1402 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1403 FALSE);
1404 }
1405
1406 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1407 struct curl_waitfd extra_fds[],
1408 unsigned int extra_nfds,
1409 int timeout_ms,
1410 int *ret)
1411 {
1412 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1413 TRUE);
1414 }
1415
1416 CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1417 {
1418 /* this function is usually called from another thread,
1419 it has to be careful only to access parts of the
1420 Curl_multi struct that are constant */
1421
1422 /* GOOD_MULTI_HANDLE can be safely called */
1423 if(!GOOD_MULTI_HANDLE(multi))
1424 return CURLM_BAD_HANDLE;
1425
1426 #ifdef ENABLE_WAKEUP
1427 #ifdef USE_WINSOCK
1428 if(WSASetEvent(multi->wsa_event))
1429 return CURLM_OK;
1430 #else
1431 /* the wakeup_pair variable is only written during init and cleanup,
1432 making it safe to access from another thread after the init part
1433 and before cleanup */
1434 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1435 char buf[1];
1436 buf[0] = 1;
1437 while(1) {
1438 /* swrite() is not thread-safe in general, because concurrent calls
1439 can have their messages interleaved, but in this case the content
1440 of the messages does not matter, which makes it ok to call.
1441
1442 The write socket is set to non-blocking, this way this function
1443 cannot block, making it safe to call even from the same thread
1444 that will call curl_multi_wait(). If swrite() returns that it
1445 would block, it's considered successful because it means that
1446 previous calls to this function will wake up the poll(). */
1447 if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1448 int err = SOCKERRNO;
1449 int return_success;
1450 #ifdef USE_WINSOCK
1451 return_success = WSAEWOULDBLOCK == err;
1452 #else
1453 if(EINTR == err)
1454 continue;
1455 return_success = EWOULDBLOCK == err || EAGAIN == err;
1456 #endif
1457 if(!return_success)
1458 return CURLM_WAKEUP_FAILURE;
1459 }
1460 return CURLM_OK;
1461 }
1462 }
1463 #endif
1464 #endif
1465 return CURLM_WAKEUP_FAILURE;
1466 }
1467
1468 /*
1469 * multi_ischanged() is called
1470 *
1471 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND
1472 * => CONNECT action.
1473 *
1474 * Set 'clear' to TRUE to have it also clear the state variable.
1475 */
1476 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1477 {
1478 bool retval = multi->recheckstate;
1479 if(clear)
1480 multi->recheckstate = FALSE;
1481 return retval;
1482 }
1483
1484 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1485 struct Curl_easy *data,
1486 struct connectdata *conn)
1487 {
1488 CURLMcode rc;
1489
1490 if(multi->in_callback)
1491 return CURLM_RECURSIVE_API_CALL;
1492
1493 rc = curl_multi_add_handle(multi, data);
1494 if(!rc) {
1495 struct SingleRequest *k = &data->req;
1496
1497 /* pass in NULL for 'conn' here since we don't want to init the
1498 connection, only this transfer */
1499 Curl_init_do(data, NULL);
1500
1501 /* take this handle to the perform state right away */
1502 multistate(data, MSTATE_PERFORMING);
1503 Curl_attach_connnection(data, conn);
1504 k->keepon |= KEEP_RECV; /* setup to receive! */
1505 }
1506 return rc;
1507 }
1508
1509 static CURLcode multi_do(struct Curl_easy *data, bool *done)
1510 {
1511 CURLcode result = CURLE_OK;
1512 struct connectdata *conn = data->conn;
1513
1514 DEBUGASSERT(conn);
1515 DEBUGASSERT(conn->handler);
1516
1517 if(conn->handler->do_it)
1518 /* generic protocol-specific function pointer set in curl_connect() */
1519 result = conn->handler->do_it(data, done);
1520
1521 return result;
1522 }
1523
1524 /*
1525 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1526 * second stage DO state which (wrongly) was introduced to support FTP's
1527 * second connection.
1528 *
1529 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
1530 * DOING state there's more work to do!
1531 */
1532
1533 static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
1534 {
1535 CURLcode result = CURLE_OK;
1536 struct connectdata *conn = data->conn;
1537
1538 *complete = 0;
1539
1540 if(conn->handler->do_more)
1541 result = conn->handler->do_more(data, complete);
1542
1543 return result;
1544 }
1545
1546 /*
1547 * Check whether a timeout occurred, and handle it if it did
1548 */
1549 static bool multi_handle_timeout(struct Curl_easy *data,
1550 struct curltime *now,
1551 bool *stream_error,
1552 CURLcode *result,
1553 bool connect_timeout)
1554 {
1555 timediff_t timeout_ms;
1556 timeout_ms = Curl_timeleft(data, now, connect_timeout);
1557
1558 if(timeout_ms < 0) {
1559 /* Handle timed out */
1560 if(data->mstate == MSTATE_RESOLVING)
1561 failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
1562 " milliseconds",
1563 Curl_timediff(*now, data->progress.t_startsingle));
1564 else if(data->mstate == MSTATE_CONNECTING)
1565 failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
1566 " milliseconds",
1567 Curl_timediff(*now, data->progress.t_startsingle));
1568 else {
1569 struct SingleRequest *k = &data->req;
1570 if(k->size != -1) {
1571 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1572 " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
1573 CURL_FORMAT_CURL_OFF_T " bytes received",
1574 Curl_timediff(*now, data->progress.t_startsingle),
1575 k->bytecount, k->size);
1576 }
1577 else {
1578 failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
1579 " milliseconds with %" CURL_FORMAT_CURL_OFF_T
1580 " bytes received",
1581 Curl_timediff(*now, data->progress.t_startsingle),
1582 k->bytecount);
1583 }
1584 }
1585
1586 /* Force connection closed if the connection has indeed been used */
1587 if(data->mstate > MSTATE_DO) {
1588 streamclose(data->conn, "Disconnected with pending data");
1589 *stream_error = TRUE;
1590 }
1591 *result = CURLE_OPERATION_TIMEDOUT;
1592 (void)multi_done(data, *result, TRUE);
1593 }
1594
1595 return (timeout_ms < 0);
1596 }
1597
1598 /*
1599 * We are doing protocol-specific connecting and this is being called over and
1600 * over from the multi interface until the connection phase is done on
1601 * protocol layer.
1602 */
1603
1604 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
1605 {
1606 CURLcode result = CURLE_OK;
1607 struct connectdata *conn = data->conn;
1608
1609 if(conn && conn->handler->connecting) {
1610 *done = FALSE;
1611 result = conn->handler->connecting(data, done);
1612 }
1613 else
1614 *done = TRUE;
1615
1616 return result;
1617 }
1618
1619 /*
1620 * We are DOING this is being called over and over from the multi interface
1621 * until the DOING phase is done on protocol layer.
1622 */
1623
1624 static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
1625 {
1626 CURLcode result = CURLE_OK;
1627 struct connectdata *conn = data->conn;
1628
1629 if(conn && conn->handler->doing) {
1630 *done = FALSE;
1631 result = conn->handler->doing(data, done);
1632 }
1633 else
1634 *done = TRUE;
1635
1636 return result;
1637 }
1638
1639 /*
1640 * We have discovered that the TCP connection has been successful, we can now
1641 * proceed with some action.
1642 *
1643 */
1644 static CURLcode protocol_connect(struct Curl_easy *data,
1645 bool *protocol_done)
1646 {
1647 CURLcode result = CURLE_OK;
1648 struct connectdata *conn = data->conn;
1649 DEBUGASSERT(conn);
1650 DEBUGASSERT(protocol_done);
1651
1652 *protocol_done = FALSE;
1653
1654 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1655 /* We already are connected, get back. This may happen when the connect
1656 worked fine in the first call, like when we connect to a local server
1657 or proxy. Note that we don't know if the protocol is actually done.
1658
1659 Unless this protocol doesn't have any protocol-connect callback, as
1660 then we know we're done. */
1661 if(!conn->handler->connecting)
1662 *protocol_done = TRUE;
1663
1664 return CURLE_OK;
1665 }
1666
1667 if(!conn->bits.protoconnstart) {
1668 #ifndef CURL_DISABLE_PROXY
1669 result = Curl_proxy_connect(data, FIRSTSOCKET);
1670 if(result)
1671 return result;
1672
1673 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1674 /* wait for HTTPS proxy SSL initialization to complete */
1675 return CURLE_OK;
1676
1677 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1678 Curl_connect_ongoing(conn))
1679 /* when using an HTTP tunnel proxy, await complete tunnel establishment
1680 before proceeding further. Return CURLE_OK so we'll be called again */
1681 return CURLE_OK;
1682 #endif
1683 if(conn->handler->connect_it) {
1684 /* is there a protocol-specific connect() procedure? */
1685
1686 /* Call the protocol-specific connect function */
1687 result = conn->handler->connect_it(data, protocol_done);
1688 }
1689 else
1690 *protocol_done = TRUE;
1691
1692 /* it has started, possibly even completed but that knowledge isn't stored
1693 in this bit! */
1694 if(!result)
1695 conn->bits.protoconnstart = TRUE;
1696 }
1697
1698 return result; /* pass back status */
1699 }
1700
1701 /*
1702 * Curl_preconnect() is called immediately before a connect starts. When a
1703 * redirect is followed, this is then called multiple times during a single
1704 * transfer.
1705 */
1706 CURLcode Curl_preconnect(struct Curl_easy *data)
1707 {
1708 if(!data->state.buffer) {
1709 data->state.buffer = malloc(data->set.buffer_size + 1);
1710 if(!data->state.buffer)
1711 return CURLE_OUT_OF_MEMORY;
1712 }
1713 return CURLE_OK;
1714 }
1715
1716
1717 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1718 struct curltime *nowp,
1719 struct Curl_easy *data)
1720 {
1721 struct Curl_message *msg = NULL;
1722 bool connected;
1723 bool async;
1724 bool protocol_connected = FALSE;
1725 bool dophase_done = FALSE;
1726 bool done = FALSE;
1727 CURLMcode rc;
1728 CURLcode result = CURLE_OK;
1729 timediff_t recv_timeout_ms;
1730 timediff_t send_timeout_ms;
1731 int control;
1732
1733 if(!GOOD_EASY_HANDLE(data))
1734 return CURLM_BAD_EASY_HANDLE;
1735
1736 do {
1737 /* A "stream" here is a logical stream if the protocol can handle that
1738 (HTTP/2), or the full connection for older protocols */
1739 bool stream_error = FALSE;
1740 rc = CURLM_OK;
1741
1742 if(multi_ischanged(multi, TRUE)) {
1743 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!"));
1744 process_pending_handles(multi); /* multiplexed */
1745 }
1746
1747 if(data->mstate > MSTATE_CONNECT &&
1748 data->mstate < MSTATE_COMPLETED) {
1749 /* Make sure we set the connection's current owner */
1750 DEBUGASSERT(data->conn);
1751 if(!data->conn)
1752 return CURLM_INTERNAL_ERROR;
1753 }
1754
1755 if(data->conn &&
1756 (data->mstate >= MSTATE_CONNECT) &&
1757 (data->mstate < MSTATE_COMPLETED)) {
1758 /* Check for overall operation timeout here but defer handling the
1759 * connection timeout to later, to allow for a connection to be set up
1760 * in the window since we last checked timeout. This prevents us
1761 * tearing down a completed connection in the case where we were slow
1762 * to check the timeout (e.g. process descheduled during this loop).
1763 * We set connect_timeout=FALSE to do this. */
1764
1765 /* we need to wait for the connect state as only then is the start time
1766 stored, but we must not check already completed handles */
1767 if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
1768 /* Skip the statemachine and go directly to error handling section. */
1769 goto statemachine_end;
1770 }
1771 }
1772
1773 switch(data->mstate) {
1774 case MSTATE_INIT:
1775 /* init this transfer. */
1776 result = Curl_pretransfer(data);
1777
1778 if(!result) {
1779 /* after init, go CONNECT */
1780 multistate(data, MSTATE_CONNECT);
1781 *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
1782 rc = CURLM_CALL_MULTI_PERFORM;
1783 }
1784 break;
1785
1786 case MSTATE_PENDING:
1787 /* We will stay here until there is a connection available. Then
1788 we try again in the MSTATE_CONNECT state. */
1789 break;
1790
1791 case MSTATE_CONNECT:
1792 /* Connect. We want to get a connection identifier filled in. */
1793 /* init this transfer. */
1794 result = Curl_preconnect(data);
1795 if(result)
1796 break;
1797
1798 *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
1799 if(data->set.timeout)
1800 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
1801
1802 if(data->set.connecttimeout)
1803 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
1804
1805 result = Curl_connect(data, &async, &protocol_connected);
1806 if(CURLE_NO_CONNECTION_AVAILABLE == result) {
1807 /* There was no connection available. We will go to the pending
1808 state and wait for an available connection. */
1809 multistate(data, MSTATE_PENDING);
1810
1811 /* add this handle to the list of connect-pending handles */
1812 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
1813 &data->connect_queue);
1814 result = CURLE_OK;
1815 break;
1816 }
1817 else if(data->state.previouslypending) {
1818 /* this transfer comes from the pending queue so try move another */
1819 infof(data, "Transfer was pending, now try another");
1820 process_pending_handles(data->multi);
1821 }
1822
1823 if(!result) {
1824 if(async)
1825 /* We're now waiting for an asynchronous name lookup */
1826 multistate(data, MSTATE_RESOLVING);
1827 else {
1828 /* after the connect has been sent off, go WAITCONNECT unless the
1829 protocol connect is already done and we can go directly to
1830 WAITDO or DO! */
1831 rc = CURLM_CALL_MULTI_PERFORM;
1832
1833 if(protocol_connected)
1834 multistate(data, MSTATE_DO);
1835 else {
1836 #ifndef CURL_DISABLE_HTTP
1837 if(Curl_connect_ongoing(data->conn))
1838 multistate(data, MSTATE_TUNNELING);
1839 else
1840 #endif
1841 multistate(data, MSTATE_CONNECTING);
1842 }
1843 }
1844 }
1845 break;
1846
1847 case MSTATE_RESOLVING:
1848 /* awaiting an asynch name resolve to complete */
1849 {
1850 struct Curl_dns_entry *dns = NULL;
1851 struct connectdata *conn = data->conn;
1852 const char *hostname;
1853
1854 DEBUGASSERT(conn);
1855 #ifndef CURL_DISABLE_PROXY
1856 if(conn->bits.httpproxy)
1857 hostname = conn->http_proxy.host.name;
1858 else
1859 #endif
1860 if(conn->bits.conn_to_host)
1861 hostname = conn->conn_to_host.name;
1862 else
1863 hostname = conn->host.name;
1864
1865 /* check if we have the name resolved by now */
1866 dns = Curl_fetch_addr(data, hostname, (int)conn->port);
1867
1868 if(dns) {
1869 #ifdef CURLRES_ASYNCH
1870 data->state.async.dns = dns;
1871 data->state.async.done = TRUE;
1872 #endif
1873 result = CURLE_OK;
1874 infof(data, "Hostname '%s' was found in DNS cache", hostname);
1875 }
1876
1877 if(!dns)
1878 result = Curl_resolv_check(data, &dns);
1879
1880 /* Update sockets here, because the socket(s) may have been
1881 closed and the application thus needs to be told, even if it
1882 is likely that the same socket(s) will again be used further
1883 down. If the name has not yet been resolved, it is likely
1884 that new sockets have been opened in an attempt to contact
1885 another resolver. */
1886 singlesocket(multi, data);
1887
1888 if(dns) {
1889 /* Perform the next step in the connection phase, and then move on
1890 to the WAITCONNECT state */
1891 result = Curl_once_resolved(data, &protocol_connected);
1892
1893 if(result)
1894 /* if Curl_once_resolved() returns failure, the connection struct
1895 is already freed and gone */
1896 data->conn = NULL; /* no more connection */
1897 else {
1898 /* call again please so that we get the next socket setup */
1899 rc = CURLM_CALL_MULTI_PERFORM;
1900 if(protocol_connected)
1901 multistate(data, MSTATE_DO);
1902 else {
1903 #ifndef CURL_DISABLE_HTTP
1904 if(Curl_connect_ongoing(data->conn))
1905 multistate(data, MSTATE_TUNNELING);
1906 else
1907 #endif
1908 multistate(data, MSTATE_CONNECTING);
1909 }
1910 }
1911 }
1912
1913 if(result) {
1914 /* failure detected */
1915 stream_error = TRUE;
1916 break;
1917 }
1918 }
1919 break;
1920
1921 #ifndef CURL_DISABLE_HTTP
1922 case MSTATE_TUNNELING:
1923 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
1924 DEBUGASSERT(data->conn);
1925 result = Curl_http_connect(data, &protocol_connected);
1926 #ifndef CURL_DISABLE_PROXY
1927 if(data->conn->bits.proxy_connect_closed) {
1928 rc = CURLM_CALL_MULTI_PERFORM;
1929 /* connect back to proxy again */
1930 result = CURLE_OK;
1931 multi_done(data, CURLE_OK, FALSE);
1932 multistate(data, MSTATE_CONNECT);
1933 }
1934 else
1935 #endif
1936 if(!result) {
1937 if(
1938 #ifndef CURL_DISABLE_PROXY
1939 (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
1940 data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
1941 #endif
1942 Curl_connect_complete(data->conn)) {
1943 rc = CURLM_CALL_MULTI_PERFORM;
1944 /* initiate protocol connect phase */
1945 multistate(data, MSTATE_PROTOCONNECT);
1946 }
1947 }
1948 else
1949 stream_error = TRUE;
1950 break;
1951 #endif
1952
1953 case MSTATE_CONNECTING:
1954 /* awaiting a completion of an asynch TCP connect */
1955 DEBUGASSERT(data->conn);
1956 result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
1957 if(connected && !result) {
1958 #ifndef CURL_DISABLE_HTTP
1959 if(
1960 #ifndef CURL_DISABLE_PROXY
1961 (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
1962 !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
1963 #endif
1964 Curl_connect_ongoing(data->conn)) {
1965 multistate(data, MSTATE_TUNNELING);
1966 break;
1967 }
1968 #endif
1969 rc = CURLM_CALL_MULTI_PERFORM;
1970 #ifndef CURL_DISABLE_PROXY
1971 multistate(data,
1972 data->conn->bits.tunnel_proxy?
1973 MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
1974 #else
1975 multistate(data, MSTATE_PROTOCONNECT);
1976 #endif
1977 }
1978 else if(result) {
1979 /* failure detected */
1980 Curl_posttransfer(data);
1981 multi_done(data, result, TRUE);
1982 stream_error = TRUE;
1983 break;
1984 }
1985 break;
1986
1987 case MSTATE_PROTOCONNECT:
1988 result = protocol_connect(data, &protocol_connected);
1989 if(!result && !protocol_connected)
1990 /* switch to waiting state */
1991 multistate(data, MSTATE_PROTOCONNECTING);
1992 else if(!result) {
1993 /* protocol connect has completed, go WAITDO or DO */
1994 multistate(data, MSTATE_DO);
1995 rc = CURLM_CALL_MULTI_PERFORM;
1996 }
1997 else {
1998 /* failure detected */
1999 Curl_posttransfer(data);
2000 multi_done(data, result, TRUE);
2001 stream_error = TRUE;
2002 }
2003 break;
2004
2005 case MSTATE_PROTOCONNECTING:
2006 /* protocol-specific connect phase */
2007 result = protocol_connecting(data, &protocol_connected);
2008 if(!result && protocol_connected) {
2009 /* after the connect has completed, go WAITDO or DO */
2010 multistate(data, MSTATE_DO);
2011 rc = CURLM_CALL_MULTI_PERFORM;
2012 }
2013 else if(result) {
2014 /* failure detected */
2015 Curl_posttransfer(data);
2016 multi_done(data, result, TRUE);
2017 stream_error = TRUE;
2018 }
2019 break;
2020
2021 case MSTATE_DO:
2022 if(data->set.connect_only) {
2023 /* keep connection open for application to use the socket */
2024 connkeep(data->conn, "CONNECT_ONLY");
2025 multistate(data, MSTATE_DONE);
2026 result = CURLE_OK;
2027 rc = CURLM_CALL_MULTI_PERFORM;
2028 }
2029 else {
2030 /* Perform the protocol's DO action */
2031 result = multi_do(data, &dophase_done);
2032
2033 /* When multi_do() returns failure, data->conn might be NULL! */
2034
2035 if(!result) {
2036 if(!dophase_done) {
2037 #ifndef CURL_DISABLE_FTP
2038 /* some steps needed for wildcard matching */
2039 if(data->state.wildcardmatch) {
2040 struct WildcardData *wc = &data->wildcard;
2041 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
2042 /* skip some states if it is important */
2043 multi_done(data, CURLE_OK, FALSE);
2044
2045 /* if there's no connection left, skip the DONE state */
2046 multistate(data, data->conn ?
2047 MSTATE_DONE : MSTATE_COMPLETED);
2048 rc = CURLM_CALL_MULTI_PERFORM;
2049 break;
2050 }
2051 }
2052 #endif
2053 /* DO was not completed in one function call, we must continue
2054 DOING... */
2055 multistate(data, MSTATE_DOING);
2056 rc = CURLM_OK;
2057 }
2058
2059 /* after DO, go DO_DONE... or DO_MORE */
2060 else if(data->conn->bits.do_more) {
2061 /* we're supposed to do more, but we need to sit down, relax
2062 and wait a little while first */
2063 multistate(data, MSTATE_DOING_MORE);
2064 rc = CURLM_OK;
2065 }
2066 else {
2067 /* we're done with the DO, now DID */
2068 multistate(data, MSTATE_DID);
2069 rc = CURLM_CALL_MULTI_PERFORM;
2070 }
2071 }
2072 else if((CURLE_SEND_ERROR == result) &&
2073 data->conn->bits.reuse) {
2074 /*
2075 * In this situation, a connection that we were trying to use
2076 * may have unexpectedly died. If possible, send the connection
2077 * back to the CONNECT phase so we can try again.
2078 */
2079 char *newurl = NULL;
2080 followtype follow = FOLLOW_NONE;
2081 CURLcode drc;
2082
2083 drc = Curl_retry_request(data, &newurl);
2084 if(drc) {
2085 /* a failure here pretty much implies an out of memory */
2086 result = drc;
2087 stream_error = TRUE;
2088 }
2089
2090 Curl_posttransfer(data);
2091 drc = multi_done(data, result, FALSE);
2092
2093 /* When set to retry the connection, we must to go back to
2094 * the CONNECT state */
2095 if(newurl) {
2096 if(!drc || (drc == CURLE_SEND_ERROR)) {
2097 follow = FOLLOW_RETRY;
2098 drc = Curl_follow(data, newurl, follow);
2099 if(!drc) {
2100 multistate(data, MSTATE_CONNECT);
2101 rc = CURLM_CALL_MULTI_PERFORM;
2102 result = CURLE_OK;
2103 }
2104 else {
2105 /* Follow failed */
2106 result = drc;
2107 }
2108 }
2109 else {
2110 /* done didn't return OK or SEND_ERROR */
2111 result = drc;
2112 }
2113 }
2114 else {
2115 /* Have error handler disconnect conn if we can't retry */
2116 stream_error = TRUE;
2117 }
2118 free(newurl);
2119 }
2120 else {
2121 /* failure detected */
2122 Curl_posttransfer(data);
2123 if(data->conn)
2124 multi_done(data, result, FALSE);
2125 stream_error = TRUE;
2126 }
2127 }
2128 break;
2129
2130 case MSTATE_DOING:
2131 /* we continue DOING until the DO phase is complete */
2132 DEBUGASSERT(data->conn);
2133 result = protocol_doing(data, &dophase_done);
2134 if(!result) {
2135 if(dophase_done) {
2136 /* after DO, go DO_DONE or DO_MORE */
2137 multistate(data, data->conn->bits.do_more?
2138 MSTATE_DOING_MORE : MSTATE_DID);
2139 rc = CURLM_CALL_MULTI_PERFORM;
2140 } /* dophase_done */
2141 }
2142 else {
2143 /* failure detected */
2144 Curl_posttransfer(data);
2145 multi_done(data, result, FALSE);
2146 stream_error = TRUE;
2147 }
2148 break;
2149
2150 case MSTATE_DOING_MORE:
2151 /*
2152 * When we are connected, DOING MORE and then go DID
2153 */
2154 DEBUGASSERT(data->conn);
2155 result = multi_do_more(data, &control);
2156
2157 if(!result) {
2158 if(control) {
2159 /* if positive, advance to DO_DONE
2160 if negative, go back to DOING */
2161 multistate(data, control == 1?
2162 MSTATE_DID : MSTATE_DOING);
2163 rc = CURLM_CALL_MULTI_PERFORM;
2164 }
2165 else
2166 /* stay in DO_MORE */
2167 rc = CURLM_OK;
2168 }
2169 else {
2170 /* failure detected */
2171 Curl_posttransfer(data);
2172 multi_done(data, result, FALSE);
2173 stream_error = TRUE;
2174 }
2175 break;
2176
2177 case MSTATE_DID:
2178 DEBUGASSERT(data->conn);
2179 if(data->conn->bits.multiplex)
2180 /* Check if we can move pending requests to send pipe */
2181 process_pending_handles(multi); /* multiplexed */
2182
2183 /* Only perform the transfer if there's a good socket to work with.
2184 Having both BAD is a signal to skip immediately to DONE */
2185 if((data->conn->sockfd != CURL_SOCKET_BAD) ||
2186 (data->conn->writesockfd != CURL_SOCKET_BAD))
2187 multistate(data, MSTATE_PERFORMING);
2188 else {
2189 #ifndef CURL_DISABLE_FTP
2190 if(data->state.wildcardmatch &&
2191 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
2192 data->wildcard.state = CURLWC_DONE;
2193 }
2194 #endif
2195 multistate(data, MSTATE_DONE);
2196 }
2197 rc = CURLM_CALL_MULTI_PERFORM;
2198 break;
2199
2200 case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */
2201 DEBUGASSERT(data->conn);
2202 /* if both rates are within spec, resume transfer */
2203 if(Curl_pgrsUpdate(data))
2204 result = CURLE_ABORTED_BY_CALLBACK;
2205 else
2206 result = Curl_speedcheck(data, *nowp);
2207
2208 if(result) {
2209 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2210 result != CURLE_HTTP2_STREAM)
2211 streamclose(data->conn, "Transfer returned error");
2212
2213 Curl_posttransfer(data);
2214 multi_done(data, result, TRUE);
2215 }
2216 else {
2217 send_timeout_ms = 0;
2218 if(data->set.max_send_speed)
2219 send_timeout_ms =
2220 Curl_pgrsLimitWaitTime(data->progress.uploaded,
2221 data->progress.ul_limit_size,
2222 data->set.max_send_speed,
2223 data->progress.ul_limit_start,
2224 *nowp);
2225
2226 recv_timeout_ms = 0;
2227 if(data->set.max_recv_speed)
2228 recv_timeout_ms =
2229 Curl_pgrsLimitWaitTime(data->progress.downloaded,
2230 data->progress.dl_limit_size,
2231 data->set.max_recv_speed,
2232 data->progress.dl_limit_start,
2233 *nowp);
2234
2235 if(!send_timeout_ms && !recv_timeout_ms) {
2236 multistate(data, MSTATE_PERFORMING);
2237 Curl_ratelimit(data, *nowp);
2238 }
2239 else if(send_timeout_ms >= recv_timeout_ms)
2240 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2241 else
2242 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2243 }
2244 break;
2245
2246 case MSTATE_PERFORMING:
2247 {
2248 char *newurl = NULL;
2249 bool retry = FALSE;
2250 bool comeback = FALSE;
2251 DEBUGASSERT(data->state.buffer);
2252 /* check if over send speed */
2253 send_timeout_ms = 0;
2254 if(data->set.max_send_speed)
2255 send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
2256 data->progress.ul_limit_size,
2257 data->set.max_send_speed,
2258 data->progress.ul_limit_start,
2259 *nowp);
2260
2261 /* check if over recv speed */
2262 recv_timeout_ms = 0;
2263 if(data->set.max_recv_speed)
2264 recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
2265 data->progress.dl_limit_size,
2266 data->set.max_recv_speed,
2267 data->progress.dl_limit_start,
2268 *nowp);
2269
2270 if(send_timeout_ms || recv_timeout_ms) {
2271 Curl_ratelimit(data, *nowp);
2272 multistate(data, MSTATE_RATELIMITING);
2273 if(send_timeout_ms >= recv_timeout_ms)
2274 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
2275 else
2276 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
2277 break;
2278 }
2279
2280 /* read/write data if it is ready to do so */
2281 result = Curl_readwrite(data->conn, data, &done, &comeback);
2282
2283 if(done || (result == CURLE_RECV_ERROR)) {
2284 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
2285 * condition and the server closed the re-used connection exactly when
2286 * we wanted to use it, so figure out if that is indeed the case.
2287 */
2288 CURLcode ret = Curl_retry_request(data, &newurl);
2289 if(!ret)
2290 retry = (newurl)?TRUE:FALSE;
2291 else if(!result)
2292 result = ret;
2293
2294 if(retry) {
2295 /* if we are to retry, set the result to OK and consider the
2296 request as done */
2297 result = CURLE_OK;
2298 done = TRUE;
2299 }
2300 }
2301 else if((CURLE_HTTP2_STREAM == result) &&
2302 Curl_h2_http_1_1_error(data)) {
2303 CURLcode ret = Curl_retry_request(data, &newurl);
2304
2305 if(!ret) {
2306 infof(data, "Downgrades to HTTP/1.1!");
2307 streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
2308 data->state.httpwant = CURL_HTTP_VERSION_1_1;
2309 /* clear the error message bit too as we ignore the one we got */
2310 data->state.errorbuf = FALSE;
2311 if(!newurl)
2312 /* typically for HTTP_1_1_REQUIRED error on first flight */
2313 newurl = strdup(data->state.url);
2314 /* if we are to retry, set the result to OK and consider the request
2315 as done */
2316 retry = TRUE;
2317 result = CURLE_OK;
2318 done = TRUE;
2319 }
2320 else
2321 result = ret;
2322 }
2323
2324 if(result) {
2325 /*
2326 * The transfer phase returned error, we mark the connection to get
2327 * closed to prevent being re-used. This is because we can't possibly
2328 * know if the connection is in a good shape or not now. Unless it is
2329 * a protocol which uses two "channels" like FTP, as then the error
2330 * happened in the data connection.
2331 */
2332
2333 if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
2334 result != CURLE_HTTP2_STREAM)
2335 streamclose(data->conn, "Transfer returned error");
2336
2337 Curl_posttransfer(data);
2338 multi_done(data, result, TRUE);
2339 }
2340 else if(done) {
2341
2342 /* call this even if the readwrite function returned error */
2343 Curl_posttransfer(data);
2344
2345 /* When we follow redirects or is set to retry the connection, we must
2346 to go back to the CONNECT state */
2347 if(data->req.newurl || retry) {
2348 followtype follow = FOLLOW_NONE;
2349 if(!retry) {
2350 /* if the URL is a follow-location and not just a retried request
2351 then figure out the URL here */
2352 free(newurl);
2353 newurl = data->req.newurl;
2354 data->req.newurl = NULL;
2355 follow = FOLLOW_REDIR;
2356 }
2357 else
2358 follow = FOLLOW_RETRY;
2359 (void)multi_done(data, CURLE_OK, FALSE);
2360 /* multi_done() might return CURLE_GOT_NOTHING */
2361 result = Curl_follow(data, newurl, follow);
2362 if(!result) {
2363 multistate(data, MSTATE_CONNECT);
2364 rc = CURLM_CALL_MULTI_PERFORM;
2365 }
2366 free(newurl);
2367 }
2368 else {
2369 /* after the transfer is done, go DONE */
2370
2371 /* but first check to see if we got a location info even though we're
2372 not following redirects */
2373 if(data->req.location) {
2374 free(newurl);
2375 newurl = data->req.location;
2376 data->req.location = NULL;
2377 result = Curl_follow(data, newurl, FOLLOW_FAKE);
2378 free(newurl);
2379 if(result) {
2380 stream_error = TRUE;
2381 result = multi_done(data, result, TRUE);
2382 }
2383 }
2384
2385 if(!result) {
2386 multistate(data, MSTATE_DONE);
2387 rc = CURLM_CALL_MULTI_PERFORM;
2388 }
2389 }
2390 }
2391 else if(comeback) {
2392 /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
2393 won't get stuck on this transfer at the expense of other concurrent
2394 transfers */
2395 Curl_expire(data, 0, EXPIRE_RUN_NOW);
2396 rc = CURLM_OK;
2397 }
2398 break;
2399 }
2400
2401 case MSTATE_DONE:
2402 /* this state is highly transient, so run another loop after this */
2403 rc = CURLM_CALL_MULTI_PERFORM;
2404
2405 if(data->conn) {
2406 CURLcode res;
2407
2408 if(data->conn->bits.multiplex)
2409 /* Check if we can move pending requests to connection */
2410 process_pending_handles(multi); /* multiplexing */
2411
2412 /* post-transfer command */
2413 res = multi_done(data, result, FALSE);
2414
2415 /* allow a previously set error code take precedence */
2416 if(!result)
2417 result = res;
2418 }
2419
2420 #ifndef CURL_DISABLE_FTP
2421 if(data->state.wildcardmatch) {
2422 if(data->wildcard.state != CURLWC_DONE) {
2423 /* if a wildcard is set and we are not ending -> lets start again
2424 with MSTATE_INIT */
2425 multistate(data, MSTATE_INIT);
2426 break;
2427 }
2428 }
2429 #endif
2430 /* after we have DONE what we're supposed to do, go COMPLETED, and
2431 it doesn't matter what the multi_done() returned! */
2432 multistate(data, MSTATE_COMPLETED);
2433 break;
2434
2435 case MSTATE_COMPLETED:
2436 break;
2437
2438 case MSTATE_MSGSENT:
2439 data->result = result;
2440 return CURLM_OK; /* do nothing */
2441
2442 default:
2443 return CURLM_INTERNAL_ERROR;
2444 }
2445
2446 if(data->conn &&
2447 data->mstate >= MSTATE_CONNECT &&
2448 data->mstate < MSTATE_DO &&
2449 rc != CURLM_CALL_MULTI_PERFORM &&
2450 !multi_ischanged(multi, false)) {
2451 /* We now handle stream timeouts if and only if this will be the last
2452 * loop iteration. We only check this on the last iteration to ensure
2453 * that if we know we have additional work to do immediately
2454 * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
2455 * declaring the connection timed out as we may almost have a completed
2456 * connection. */
2457 multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
2458 }
2459
2460 statemachine_end:
2461
2462 if(data->mstate < MSTATE_COMPLETED) {
2463 if(result) {
2464 /*
2465 * If an error was returned, and we aren't in completed state now,
2466 * then we go to completed and consider this transfer aborted.
2467 */
2468
2469 /* NOTE: no attempt to disconnect connections must be made
2470 in the case blocks above - cleanup happens only here */
2471
2472 /* Check if we can move pending requests to send pipe */
2473 process_pending_handles(multi); /* connection */
2474
2475 if(data->conn) {
2476 if(stream_error) {
2477 /* Don't attempt to send data over a connection that timed out */
2478 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
2479 struct connectdata *conn = data->conn;
2480
2481 /* This is where we make sure that the conn pointer is reset.
2482 We don't have to do this in every case block above where a
2483 failure is detected */
2484 Curl_detach_connnection(data);
2485
2486 /* remove connection from cache */
2487 Curl_conncache_remove_conn(data, conn, TRUE);
2488
2489 /* disconnect properly */
2490 Curl_disconnect(data, conn, dead_connection);
2491 }
2492 }
2493 else if(data->mstate == MSTATE_CONNECT) {
2494 /* Curl_connect() failed */
2495 (void)Curl_posttransfer(data);
2496 }
2497
2498 multistate(data, MSTATE_COMPLETED);
2499 rc = CURLM_CALL_MULTI_PERFORM;
2500 }
2501 /* if there's still a connection to use, call the progress function */
2502 else if(data->conn && Curl_pgrsUpdate(data)) {
2503 /* aborted due to progress callback return code must close the
2504 connection */
2505 result = CURLE_ABORTED_BY_CALLBACK;
2506 streamclose(data->conn, "Aborted by callback");
2507
2508 /* if not yet in DONE state, go there, otherwise COMPLETED */
2509 multistate(data, (data->mstate < MSTATE_DONE)?
2510 MSTATE_DONE: MSTATE_COMPLETED);
2511 rc = CURLM_CALL_MULTI_PERFORM;
2512 }
2513 }
2514
2515 if(MSTATE_COMPLETED == data->mstate) {
2516 if(data->set.fmultidone) {
2517 /* signal via callback instead */
2518 data->set.fmultidone(data, result);
2519 }
2520 else {
2521 /* now fill in the Curl_message with this info */
2522 msg = &data->msg;
2523
2524 msg->extmsg.msg = CURLMSG_DONE;
2525 msg->extmsg.easy_handle = data;
2526 msg->extmsg.data.result = result;
2527
2528 rc = multi_addmsg(multi, msg);
2529 DEBUGASSERT(!data->conn);
2530 }
2531 multistate(data, MSTATE_MSGSENT);
2532 }
2533 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2534
2535 data->result = result;
2536 return rc;
2537 }
2538
2539
2540 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2541 {
2542 struct Curl_easy *data;
2543 CURLMcode returncode = CURLM_OK;
2544 struct Curl_tree *t;
2545 struct curltime now = Curl_now();
2546
2547 if(!GOOD_MULTI_HANDLE(multi))
2548 return CURLM_BAD_HANDLE;
2549
2550 if(multi->in_callback)
2551 return CURLM_RECURSIVE_API_CALL;
2552
2553 data = multi->easyp;
2554 while(data) {
2555 CURLMcode result;
2556 SIGPIPE_VARIABLE(pipe_st);
2557
2558 sigpipe_ignore(data, &pipe_st);
2559 result = multi_runsingle(multi, &now, data);
2560 sigpipe_restore(&pipe_st);
2561
2562 if(result)
2563 returncode = result;
2564
2565 data = data->next; /* operate on next handle */
2566 }
2567
2568 /*
2569 * Simply remove all expired timers from the splay since handles are dealt
2570 * with unconditionally by this function and curl_multi_timeout() requires
2571 * that already passed/handled expire times are removed from the splay.
2572 *
2573 * It is important that the 'now' value is set at the entry of this function
2574 * and not for the current time as it may have ticked a little while since
2575 * then and then we risk this loop to remove timers that actually have not
2576 * been handled!
2577 */
2578 do {
2579 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2580 if(t)
2581 /* the removed may have another timeout in queue */
2582 (void)add_next_timeout(now, multi, t->payload);
2583
2584 } while(t);
2585
2586 *running_handles = multi->num_alive;
2587
2588 if(CURLM_OK >= returncode)
2589 Curl_update_timer(multi);
2590
2591 return returncode;
2592 }
2593
2594 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2595 {
2596 struct Curl_easy *data;
2597 struct Curl_easy *nextdata;
2598
2599 if(GOOD_MULTI_HANDLE(multi)) {
2600 if(multi->in_callback)
2601 return CURLM_RECURSIVE_API_CALL;
2602
2603 multi->magic = 0; /* not good anymore */
2604
2605 /* Firsrt remove all remaining easy handles */
2606 data = multi->easyp;
2607 while(data) {
2608 nextdata = data->next;
2609 if(!data->state.done && data->conn)
2610 /* if DONE was never called for this handle */
2611 (void)multi_done(data, CURLE_OK, TRUE);
2612 if(data->dns.hostcachetype == HCACHE_MULTI) {
2613 /* clear out the usage of the shared DNS cache */
2614 Curl_hostcache_clean(data, data->dns.hostcache);
2615 data->dns.hostcache = NULL;
2616 data->dns.hostcachetype = HCACHE_NONE;
2617 }
2618
2619 /* Clear the pointer to the connection cache */
2620 data->state.conn_cache = NULL;
2621 data->multi = NULL; /* clear the association */
2622
2623 #ifdef USE_LIBPSL
2624 if(data->psl == &multi->psl)
2625 data->psl = NULL;
2626 #endif
2627
2628 data = nextdata;
2629 }
2630
2631 /* Close all the connections in the connection cache */
2632 Curl_conncache_close_all_connections(&multi->conn_cache);
2633
2634 Curl_hash_destroy(&multi->sockhash);
2635 Curl_conncache_destroy(&multi->conn_cache);
2636 Curl_llist_destroy(&multi->msglist, NULL);
2637 Curl_llist_destroy(&multi->pending, NULL);
2638
2639 Curl_hash_destroy(&multi->hostcache);
2640 Curl_psl_destroy(&multi->psl);
2641
2642 #ifdef USE_WINSOCK
2643 WSACloseEvent(multi->wsa_event);
2644 #else
2645 #ifdef ENABLE_WAKEUP
2646 sclose(multi->wakeup_pair[0]);
2647 sclose(multi->wakeup_pair[1]);
2648 #endif
2649 #endif
2650 free(multi);
2651
2652 return CURLM_OK;
2653 }
2654 return CURLM_BAD_HANDLE;
2655 }
2656
2657 /*
2658 * curl_multi_info_read()
2659 *
2660 * This function is the primary way for a multi/multi_socket application to
2661 * figure out if a transfer has ended. We MUST make this function as fast as
2662 * possible as it will be polled frequently and we MUST NOT scan any lists in
2663 * here to figure out things. We must scale fine to thousands of handles and
2664 * beyond. The current design is fully O(1).
2665 */
2666
2667 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2668 {
2669 struct Curl_message *msg;
2670
2671 *msgs_in_queue = 0; /* default to none */
2672
2673 if(GOOD_MULTI_HANDLE(multi) &&
2674 !multi->in_callback &&
2675 Curl_llist_count(&multi->msglist)) {
2676 /* there is one or more messages in the list */
2677 struct Curl_llist_element *e;
2678
2679 /* extract the head of the list to return */
2680 e = multi->msglist.head;
2681
2682 msg = e->ptr;
2683
2684 /* remove the extracted entry */
2685 Curl_llist_remove(&multi->msglist, e, NULL);
2686
2687 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2688
2689 return &msg->extmsg;
2690 }
2691 return NULL;
2692 }
2693
2694 /*
2695 * singlesocket() checks what sockets we deal with and their "action state"
2696 * and if we have a different state in any of those sockets from last time we
2697 * call the callback accordingly.
2698 */
2699 static CURLMcode singlesocket(struct Curl_multi *multi,
2700 struct Curl_easy *data)
2701 {
2702 curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
2703 int i;
2704 struct Curl_sh_entry *entry;
2705 curl_socket_t s;
2706 int num;
2707 unsigned int curraction;
2708 unsigned char actions[MAX_SOCKSPEREASYHANDLE];
2709
2710 for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
2711 socks[i] = CURL_SOCKET_BAD;
2712
2713 /* Fill in the 'current' struct with the state as it is now: what sockets to
2714 supervise and for what actions */
2715 curraction = multi_getsock(data, socks);
2716
2717 /* We have 0 .. N sockets already and we get to know about the 0 .. M
2718 sockets we should have from now on. Detect the differences, remove no
2719 longer supervised ones and add new ones */
2720
2721 /* walk over the sockets we got right now */
2722 for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
2723 (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
2724 i++) {
2725 unsigned char action = CURL_POLL_NONE;
2726 unsigned char prevaction = 0;
2727 int comboaction;
2728 bool sincebefore = FALSE;
2729
2730 s = socks[i];
2731
2732 /* get it from the hash */
2733 entry = sh_getentry(&multi->sockhash, s);
2734
2735 if(curraction & GETSOCK_READSOCK(i))
2736 action |= CURL_POLL_IN;
2737 if(curraction & GETSOCK_WRITESOCK(i))
2738 action |= CURL_POLL_OUT;
2739
2740 actions[i] = action;
2741 if(entry) {
2742 /* check if new for this transfer */
2743 int j;
2744 for(j = 0; j< data->numsocks; j++) {
2745 if(s == data->sockets[j]) {
2746 prevaction = data->actions[j];
2747 sincebefore = TRUE;
2748 break;
2749 }
2750 }
2751 }
2752 else {
2753 /* this is a socket we didn't have before, add it to the hash! */
2754 entry = sh_addentry(&multi->sockhash, s);
2755 if(!entry)
2756 /* fatal */
2757 return CURLM_OUT_OF_MEMORY;
2758 }
2759 if(sincebefore && (prevaction != action)) {
2760 /* Socket was used already, but different action now */
2761 if(prevaction & CURL_POLL_IN)
2762 entry->readers--;
2763 if(prevaction & CURL_POLL_OUT)
2764 entry->writers--;
2765 if(action & CURL_POLL_IN)
2766 entry->readers++;
2767 if(action & CURL_POLL_OUT)
2768 entry->writers++;
2769 }
2770 else if(!sincebefore) {
2771 /* a new user */
2772 entry->users++;
2773 if(action & CURL_POLL_IN)
2774 entry->readers++;
2775 if(action & CURL_POLL_OUT)
2776 entry->writers++;
2777
2778 /* add 'data' to the transfer hash on this socket! */
2779 if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
2780 sizeof(struct Curl_easy *), data))
2781 return CURLM_OUT_OF_MEMORY;
2782 }
2783
2784 comboaction = (entry->writers? CURL_POLL_OUT : 0) |
2785 (entry->readers ? CURL_POLL_IN : 0);
2786
2787 /* socket existed before and has the same action set as before */
2788 if(sincebefore && ((int)entry->action == comboaction))
2789 /* same, continue */
2790 continue;
2791
2792 if(multi->socket_cb)
2793 multi->socket_cb(data, s, comboaction, multi->socket_userp,
2794 entry->socketp);
2795
2796 entry->action = comboaction; /* store the current action state */
2797 }
2798
2799 num = i; /* number of sockets */
2800
2801 /* when we've walked over all the sockets we should have right now, we must
2802 make sure to detect sockets that are removed */
2803 for(i = 0; i< data->numsocks; i++) {
2804 int j;
2805 bool stillused = FALSE;
2806 s = data->sockets[i];
2807 for(j = 0; j < num; j++) {
2808 if(s == socks[j]) {
2809 /* this is still supervised */
2810 stillused = TRUE;
2811 break;
2812 }
2813 }
2814 if(stillused)
2815 continue;
2816
2817 entry = sh_getentry(&multi->sockhash, s);
2818 /* if this is NULL here, the socket has been closed and notified so
2819 already by Curl_multi_closed() */
2820 if(entry) {
2821 unsigned char oldactions = data->actions[i];
2822 /* this socket has been removed. Decrease user count */
2823 entry->users--;
2824 if(oldactions & CURL_POLL_OUT)
2825 entry->writers--;
2826 if(oldactions & CURL_POLL_IN)
2827 entry->readers--;
2828 if(!entry->users) {
2829 if(multi->socket_cb)
2830 multi->socket_cb(data, s, CURL_POLL_REMOVE,
2831 multi->socket_userp,
2832 entry->socketp);
2833 sh_delentry(entry, &multi->sockhash, s);
2834 }
2835 else {
2836 /* still users, but remove this handle as a user of this socket */
2837 if(Curl_hash_delete(&entry->transfers, (char *)&data,
2838 sizeof(struct Curl_easy *))) {
2839 DEBUGASSERT(NULL);
2840 }
2841 }
2842 }
2843 } /* for loop over numsocks */
2844
2845 memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
2846 memcpy(data->actions, actions, num*sizeof(char));
2847 data->numsocks = num;
2848 return CURLM_OK;
2849 }
2850
2851 void Curl_updatesocket(struct Curl_easy *data)
2852 {
2853 singlesocket(data->multi, data);
2854 }
2855
2856
2857 /*
2858 * Curl_multi_closed()
2859 *
2860 * Used by the connect code to tell the multi_socket code that one of the
2861 * sockets we were using is about to be closed. This function will then
2862 * remove it from the sockethash for this handle to make the multi_socket API
2863 * behave properly, especially for the case when libcurl will create another
2864 * socket again and it gets the same file descriptor number.
2865 */
2866
2867 void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
2868 {
2869 if(data) {
2870 /* if there's still an easy handle associated with this connection */
2871 struct Curl_multi *multi = data->multi;
2872 if(multi) {
2873 /* this is set if this connection is part of a handle that is added to
2874 a multi handle, and only then this is necessary */
2875 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2876
2877 if(entry) {
2878 if(multi->socket_cb)
2879 multi->socket_cb(data, s, CURL_POLL_REMOVE,
2880 multi->socket_userp,
2881 entry->socketp);
2882
2883 /* now remove it from the socket hash */
2884 sh_delentry(entry, &multi->sockhash, s);
2885 }
2886 }
2887 }
2888 }
2889
2890 /*
2891 * add_next_timeout()
2892 *
2893 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called
2894 * when it has just been removed from the splay tree because the timeout has
2895 * expired. This function is then to advance in the list to pick the next
2896 * timeout to use (skip the already expired ones) and add this node back to
2897 * the splay tree again.
2898 *
2899 * The splay tree only has each sessionhandle as a single node and the nearest
2900 * timeout is used to sort it on.
2901 */
2902 static CURLMcode add_next_timeout(struct curltime now,
2903 struct Curl_multi *multi,
2904 struct Curl_easy *d)
2905 {
2906 struct curltime *tv = &d->state.expiretime;
2907 struct Curl_llist *list = &d->state.timeoutlist;
2908 struct Curl_llist_element *e;
2909 struct time_node *node = NULL;
2910
2911 /* move over the timeout list for this specific handle and remove all
2912 timeouts that are now passed tense and store the next pending
2913 timeout in *tv */
2914 for(e = list->head; e;) {
2915 struct Curl_llist_element *n = e->next;
2916 timediff_t diff;
2917 node = (struct time_node *)e->ptr;
2918 diff = Curl_timediff(node->time, now);
2919 if(diff <= 0)
2920 /* remove outdated entry */
2921 Curl_llist_remove(list, e, NULL);
2922 else
2923 /* the list is sorted so get out on the first mismatch */
2924 break;
2925 e = n;
2926 }
2927 e = list->head;
2928 if(!e) {
2929 /* clear the expire times within the handles that we remove from the
2930 splay tree */
2931 tv->tv_sec = 0;
2932 tv->tv_usec = 0;
2933 }
2934 else {
2935 /* copy the first entry to 'tv' */
2936 memcpy(tv, &node->time, sizeof(*tv));
2937
2938 /* Insert this node again into the splay. Keep the timer in the list in
2939 case we need to recompute future timers. */
2940 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
2941 &d->state.timenode);
2942 }
2943 return CURLM_OK;
2944 }
2945
2946 static CURLMcode multi_socket(struct Curl_multi *multi,
2947 bool checkall,
2948 curl_socket_t s,
2949 int ev_bitmask,
2950 int *running_handles)
2951 {
2952 CURLMcode result = CURLM_OK;
2953 struct Curl_easy *data = NULL;
2954 struct Curl_tree *t;
2955 struct curltime now = Curl_now();
2956
2957 if(checkall) {
2958 /* *perform() deals with running_handles on its own */
2959 result = curl_multi_perform(multi, running_handles);
2960
2961 /* walk through each easy handle and do the socket state change magic
2962 and callbacks */
2963 if(result != CURLM_BAD_HANDLE) {
2964 data = multi->easyp;
2965 while(data && !result) {
2966 result = singlesocket(multi, data);
2967 data = data->next;
2968 }
2969 }
2970
2971 /* or should we fall-through and do the timer-based stuff? */
2972 return result;
2973 }
2974 if(s != CURL_SOCKET_TIMEOUT) {
2975 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
2976
2977 if(!entry)
2978 /* Unmatched socket, we can't act on it but we ignore this fact. In
2979 real-world tests it has been proved that libevent can in fact give
2980 the application actions even though the socket was just previously
2981 asked to get removed, so thus we better survive stray socket actions
2982 and just move on. */
2983 ;
2984 else {
2985 struct Curl_hash_iterator iter;
2986 struct Curl_hash_element *he;
2987
2988 /* the socket can be shared by many transfers, iterate */
2989 Curl_hash_start_iterate(&entry->transfers, &iter);
2990 for(he = Curl_hash_next_element(&iter); he;
2991 he = Curl_hash_next_element(&iter)) {
2992 data = (struct Curl_easy *)he->ptr;
2993 DEBUGASSERT(data);
2994 DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
2995
2996 if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
2997 /* set socket event bitmask if they're not locked */
2998 data->conn->cselect_bits = ev_bitmask;
2999
3000 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3001 }
3002
3003 /* Now we fall-through and do the timer-based stuff, since we don't want
3004 to force the user to have to deal with timeouts as long as at least
3005 one connection in fact has traffic. */
3006
3007 data = NULL; /* set data to NULL again to avoid calling
3008 multi_runsingle() in case there's no need to */
3009 now = Curl_now(); /* get a newer time since the multi_runsingle() loop
3010 may have taken some time */
3011 }
3012 }
3013 else {
3014 /* Asked to run due to time-out. Clear the 'lastcall' variable to force
3015 Curl_update_timer() to trigger a callback to the app again even if the
3016 same timeout is still the one to run after this call. That handles the
3017 case when the application asks libcurl to run the timeout
3018 prematurely. */
3019 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3020 }
3021
3022 /*
3023 * The loop following here will go on as long as there are expire-times left
3024 * to process in the splay and 'data' will be re-assigned for every expired
3025 * handle we deal with.
3026 */
3027 do {
3028 /* the first loop lap 'data' can be NULL */
3029 if(data) {
3030 SIGPIPE_VARIABLE(pipe_st);
3031
3032 sigpipe_ignore(data, &pipe_st);
3033 result = multi_runsingle(multi, &now, data);
3034 sigpipe_restore(&pipe_st);
3035
3036 if(CURLM_OK >= result) {
3037 /* get the socket(s) and check if the state has been changed since
3038 last */
3039 result = singlesocket(multi, data);
3040 if(result)
3041 return result;
3042 }
3043 }
3044
3045 /* Check if there's one (more) expired timer to deal with! This function
3046 extracts a matching node if there is one */
3047
3048 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3049 if(t) {
3050 data = t->payload; /* assign this for next loop */
3051 (void)add_next_timeout(now, multi, t->payload);
3052 }
3053
3054 } while(t);
3055
3056 *running_handles = multi->num_alive;
3057 return result;
3058 }
3059
3060 #undef curl_multi_setopt
3061 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3062 CURLMoption option, ...)
3063 {
3064 CURLMcode res = CURLM_OK;
3065 va_list param;
3066
3067 if(!GOOD_MULTI_HANDLE(multi))
3068 return CURLM_BAD_HANDLE;
3069
3070 if(multi->in_callback)
3071 return CURLM_RECURSIVE_API_CALL;
3072
3073 va_start(param, option);
3074
3075 switch(option) {
3076 case CURLMOPT_SOCKETFUNCTION:
3077 multi->socket_cb = va_arg(param, curl_socket_callback);
3078 break;
3079 case CURLMOPT_SOCKETDATA:
3080 multi->socket_userp = va_arg(param, void *);
3081 break;
3082 case CURLMOPT_PUSHFUNCTION:
3083 multi->push_cb = va_arg(param, curl_push_callback);
3084 break;
3085 case CURLMOPT_PUSHDATA:
3086 multi->push_userp = va_arg(param, void *);
3087 break;
3088 case CURLMOPT_PIPELINING:
3089 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
3090 break;
3091 case CURLMOPT_TIMERFUNCTION:
3092 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3093 break;
3094 case CURLMOPT_TIMERDATA:
3095 multi->timer_userp = va_arg(param, void *);
3096 break;
3097 case CURLMOPT_MAXCONNECTS:
3098 multi->maxconnects = va_arg(param, long);
3099 break;
3100 case CURLMOPT_MAX_HOST_CONNECTIONS:
3101 multi->max_host_connections = va_arg(param, long);
3102 break;
3103 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
3104 multi->max_total_connections = va_arg(param, long);
3105 break;
3106 /* options formerly used for pipelining */
3107 case CURLMOPT_MAX_PIPELINE_LENGTH:
3108 break;
3109 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
3110 break;
3111 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
3112 break;
3113 case CURLMOPT_PIPELINING_SITE_BL:
3114 break;
3115 case CURLMOPT_PIPELINING_SERVER_BL:
3116 break;
3117 case CURLMOPT_MAX_CONCURRENT_STREAMS:
3118 {
3119 long streams = va_arg(param, long);
3120 if(streams < 1)
3121 streams = 100;
3122 multi->max_concurrent_streams = curlx_sltoui(streams);
3123 }
3124 break;
3125 default:
3126 res = CURLM_UNKNOWN_OPTION;
3127 break;
3128 }
3129 va_end(param);
3130 return res;
3131 }
3132
3133 /* we define curl_multi_socket() in the public multi.h header */
3134 #undef curl_multi_socket
3135
3136 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3137 int *running_handles)
3138 {
3139 CURLMcode result;
3140 if(multi->in_callback)
3141 return CURLM_RECURSIVE_API_CALL;
3142 result = multi_socket(multi, FALSE, s, 0, running_handles);
3143 if(CURLM_OK >= result)
3144 Curl_update_timer(multi);
3145 return result;
3146 }
3147
3148 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3149 int ev_bitmask, int *running_handles)
3150 {
3151 CURLMcode result;
3152 if(multi->in_callback)
3153 return CURLM_RECURSIVE_API_CALL;
3154 result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3155 if(CURLM_OK >= result)
3156 Curl_update_timer(multi);
3157 return result;
3158 }
3159
3160 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3161 {
3162 CURLMcode result;
3163 if(multi->in_callback)
3164 return CURLM_RECURSIVE_API_CALL;
3165 result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3166 if(CURLM_OK >= result)
3167 Curl_update_timer(multi);
3168 return result;
3169 }
3170
3171 static CURLMcode multi_timeout(struct Curl_multi *multi,
3172 long *timeout_ms)
3173 {
3174 static struct curltime tv_zero = {0, 0};
3175
3176 if(multi->timetree) {
3177 /* we have a tree of expire times */
3178 struct curltime now = Curl_now();
3179
3180 /* splay the lowest to the bottom */
3181 multi->timetree = Curl_splay(tv_zero, multi->timetree);
3182
3183 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3184 /* some time left before expiration */
3185 timediff_t diff = Curl_timediff(multi->timetree->key, now);
3186 if(diff <= 0)
3187 /*
3188 * Since we only provide millisecond resolution on the returned value
3189 * and the diff might be less than one millisecond here, we don't
3190 * return zero as that may cause short bursts of busyloops on fast
3191 * processors while the diff is still present but less than one
3192 * millisecond! instead we return 1 until the time is ripe.
3193 */
3194 *timeout_ms = 1;
3195 else
3196 /* this should be safe even on 64 bit archs, as we don't use that
3197 overly long timeouts */
3198 *timeout_ms = (long)diff;
3199 }
3200 else
3201 /* 0 means immediately */
3202 *timeout_ms = 0;
3203 }
3204 else
3205 *timeout_ms = -1;
3206
3207 return CURLM_OK;
3208 }
3209
3210 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3211 long *timeout_ms)
3212 {
3213 /* First, make some basic checks that the CURLM handle is a good handle */
3214 if(!GOOD_MULTI_HANDLE(multi))
3215 return CURLM_BAD_HANDLE;
3216
3217 if(multi->in_callback)
3218 return CURLM_RECURSIVE_API_CALL;
3219
3220 return multi_timeout(multi, timeout_ms);
3221 }
3222
3223 /*
3224 * Tell the application it should update its timers, if it subscribes to the
3225 * update timer callback.
3226 */
3227 void Curl_update_timer(struct Curl_multi *multi)
3228 {
3229 long timeout_ms;
3230
3231 if(!multi->timer_cb)
3232 return;
3233 if(multi_timeout(multi, &timeout_ms)) {
3234 return;
3235 }
3236 if(timeout_ms < 0) {
3237 static const struct curltime none = {0, 0};
3238 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3239 multi->timer_lastcall = none;
3240 /* there's no timeout now but there was one previously, tell the app to
3241 disable it */
3242 multi->timer_cb(multi, -1, multi->timer_userp);
3243 return;
3244 }
3245 return;
3246 }
3247
3248 /* When multi_timeout() is done, multi->timetree points to the node with the
3249 * timeout we got the (relative) time-out time for. We can thus easily check
3250 * if this is the same (fixed) time as we got in a previous call and then
3251 * avoid calling the callback again. */
3252 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3253 return;
3254
3255 multi->timer_lastcall = multi->timetree->key;
3256
3257 multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3258 }
3259
3260 /*
3261 * multi_deltimeout()
3262 *
3263 * Remove a given timestamp from the list of timeouts.
3264 */
3265 static void
3266 multi_deltimeout(struct Curl_easy *data, expire_id eid)
3267 {
3268 struct Curl_llist_element *e;
3269 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3270 /* find and remove the specific node from the list */
3271 for(e = timeoutlist->head; e; e = e->next) {
3272 struct time_node *n = (struct time_node *)e->ptr;
3273 if(n->eid == eid) {
3274 Curl_llist_remove(timeoutlist, e, NULL);
3275 return;
3276 }
3277 }
3278 }
3279
3280 /*
3281 * multi_addtimeout()
3282 *
3283 * Add a timestamp to the list of timeouts. Keep the list sorted so that head
3284 * of list is always the timeout nearest in time.
3285 *
3286 */
3287 static CURLMcode
3288 multi_addtimeout(struct Curl_easy *data,
3289 struct curltime *stamp,
3290 expire_id eid)
3291 {
3292 struct Curl_llist_element *e;
3293 struct time_node *node;
3294 struct Curl_llist_element *prev = NULL;
3295 size_t n;
3296 struct Curl_llist *timeoutlist = &data->state.timeoutlist;
3297
3298 node = &data->state.expires[eid];
3299
3300 /* copy the timestamp and id */
3301 memcpy(&node->time, stamp, sizeof(*stamp));
3302 node->eid = eid; /* also marks it as in use */
3303
3304 n = Curl_llist_count(timeoutlist);
3305 if(n) {
3306 /* find the correct spot in the list */
3307 for(e = timeoutlist->head; e; e = e->next) {
3308 struct time_node *check = (struct time_node *)e->ptr;
3309 timediff_t diff = Curl_timediff(check->time, node->time);
3310 if(diff > 0)
3311 break;
3312 prev = e;
3313 }
3314
3315 }
3316 /* else
3317 this is the first timeout on the list */
3318
3319 Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
3320 return CURLM_OK;
3321 }
3322
3323 /*
3324 * Curl_expire()
3325 *
3326 * given a number of milliseconds from now to use to set the 'act before
3327 * this'-time for the transfer, to be extracted by curl_multi_timeout()
3328 *
3329 * The timeout will be added to a queue of timeouts if it defines a moment in
3330 * time that is later than the current head of queue.
3331 *
3332 * Expire replaces a former timeout using the same id if already set.
3333 */
3334 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
3335 {
3336 struct Curl_multi *multi = data->multi;
3337 struct curltime *nowp = &data->state.expiretime;
3338 struct curltime set;
3339
3340 /* this is only interesting while there is still an associated multi struct
3341 remaining! */
3342 if(!multi)
3343 return;
3344
3345 DEBUGASSERT(id < EXPIRE_LAST);
3346
3347 set = Curl_now();
3348 set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bit conversion */
3349 set.tv_usec += (unsigned int)(milli%1000)*1000;
3350
3351 if(set.tv_usec >= 1000000) {
3352 set.tv_sec++;
3353 set.tv_usec -= 1000000;
3354 }
3355
3356 /* Remove any timer with the same id just in case. */
3357 multi_deltimeout(data, id);
3358
3359 /* Add it to the timer list. It must stay in the list until it has expired
3360 in case we need to recompute the minimum timer later. */
3361 multi_addtimeout(data, &set, id);
3362
3363 if(nowp->tv_sec || nowp->tv_usec) {
3364 /* This means that the struct is added as a node in the splay tree.
3365 Compare if the new time is earlier, and only remove-old/add-new if it
3366 is. */
3367 timediff_t diff = Curl_timediff(set, *nowp);
3368 int rc;
3369
3370 if(diff > 0) {
3371 /* The current splay tree entry is sooner than this new expiry time.
3372 We don't need to update our splay tree entry. */
3373 return;
3374 }
3375
3376 /* Since this is an updated time, we must remove the previous entry from
3377 the splay tree first and then re-add the new value */
3378 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3379 &multi->timetree);
3380 if(rc)
3381 infof(data, "Internal error removing splay node = %d", rc);
3382 }
3383
3384 /* Indicate that we are in the splay tree and insert the new timer expiry
3385 value since it is our local minimum. */
3386 *nowp = set;
3387 data->state.timenode.payload = data;
3388 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3389 &data->state.timenode);
3390 }
3391
3392 /*
3393 * Curl_expire_done()
3394 *
3395 * Removes the expire timer. Marks it as done.
3396 *
3397 */
3398 void Curl_expire_done(struct Curl_easy *data, expire_id id)
3399 {
3400 /* remove the timer, if there */
3401 multi_deltimeout(data, id);
3402 }
3403
3404 /*
3405 * Curl_expire_clear()
3406 *
3407 * Clear ALL timeout values for this handle.
3408 */
3409 void Curl_expire_clear(struct Curl_easy *data)
3410 {
3411 struct Curl_multi *multi = data->multi;
3412 struct curltime *nowp = &data->state.expiretime;
3413
3414 /* this is only interesting while there is still an associated multi struct
3415 remaining! */
3416 if(!multi)
3417 return;
3418
3419 if(nowp->tv_sec || nowp->tv_usec) {
3420 /* Since this is an cleared time, we must remove the previous entry from
3421 the splay tree */
3422 struct Curl_llist *list = &data->state.timeoutlist;
3423 int rc;
3424
3425 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3426 &multi->timetree);
3427 if(rc)
3428 infof(data, "Internal error clearing splay node = %d", rc);
3429
3430 /* flush the timeout list too */
3431 while(list->size > 0) {
3432 Curl_llist_remove(list, list->tail, NULL);
3433 }
3434
3435 #ifdef DEBUGBUILD
3436 infof(data, "Expire cleared (transfer %p)", data);
3437 #endif
3438 nowp->tv_sec = 0;
3439 nowp->tv_usec = 0;
3440 }
3441 }
3442
3443
3444
3445
3446 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3447 void *hashp)
3448 {
3449 struct Curl_sh_entry *there = NULL;
3450
3451 if(multi->in_callback)
3452 return CURLM_RECURSIVE_API_CALL;
3453
3454 there = sh_getentry(&multi->sockhash, s);
3455
3456 if(!there)
3457 return CURLM_BAD_SOCKET;
3458
3459 there->socketp = hashp;
3460
3461 return CURLM_OK;
3462 }
3463
3464 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3465 {
3466 return multi ? multi->max_host_connections : 0;
3467 }
3468
3469 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3470 {
3471 return multi ? multi->max_total_connections : 0;
3472 }
3473
3474 /*
3475 * When information about a connection has appeared, call this!
3476 */
3477
3478 void Curl_multiuse_state(struct Curl_easy *data,
3479 int bundlestate) /* use BUNDLE_* defines */
3480 {
3481 struct connectdata *conn;
3482 DEBUGASSERT(data);
3483 DEBUGASSERT(data->multi);
3484 conn = data->conn;
3485 DEBUGASSERT(conn);
3486 DEBUGASSERT(conn->bundle);
3487
3488 conn->bundle->multiuse = bundlestate;
3489 process_pending_handles(data->multi);
3490 }
3491
3492 static void process_pending_handles(struct Curl_multi *multi)
3493 {
3494 struct Curl_llist_element *e = multi->pending.head;
3495 if(e) {
3496 struct Curl_easy *data = e->ptr;
3497
3498 DEBUGASSERT(data->mstate == MSTATE_PENDING);
3499
3500 multistate(data, MSTATE_CONNECT);
3501
3502 /* Remove this node from the list */
3503 Curl_llist_remove(&multi->pending, e, NULL);
3504
3505 /* Make sure that the handle will be processed soonish. */
3506 Curl_expire(data, 0, EXPIRE_RUN_NOW);
3507
3508 /* mark this as having been in the pending queue */
3509 data->state.previouslypending = TRUE;
3510 }
3511 }
3512
3513 void Curl_set_in_callback(struct Curl_easy *data, bool value)
3514 {
3515 /* might get called when there is no data pointer! */
3516 if(data) {
3517 if(data->multi_easy)
3518 data->multi_easy->in_callback = value;
3519 else if(data->multi)
3520 data->multi->in_callback = value;
3521 }
3522 }
3523
3524 bool Curl_is_in_callback(struct Curl_easy *easy)
3525 {
3526 return ((easy->multi && easy->multi->in_callback) ||
3527 (easy->multi_easy && easy->multi_easy->in_callback));
3528 }
3529
3530 #ifdef DEBUGBUILD
3531 void Curl_multi_dump(struct Curl_multi *multi)
3532 {
3533 struct Curl_easy *data;
3534 int i;
3535 fprintf(stderr, "* Multi status: %d handles, %d alive\n",
3536 multi->num_easy, multi->num_alive);
3537 for(data = multi->easyp; data; data = data->next) {
3538 if(data->mstate < MSTATE_COMPLETED) {
3539 /* only display handles that are not completed */
3540 fprintf(stderr, "handle %p, state %s, %d sockets\n",
3541 (void *)data,
3542 statename[data->mstate], data->numsocks);
3543 for(i = 0; i < data->numsocks; i++) {
3544 curl_socket_t s = data->sockets[i];
3545 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3546
3547 fprintf(stderr, "%d ", (int)s);
3548 if(!entry) {
3549 fprintf(stderr, "INTERNAL CONFUSION\n");
3550 continue;
3551 }
3552 fprintf(stderr, "[%s %s] ",
3553 (entry->action&CURL_POLL_IN)?"RECVING":"",
3554 (entry->action&CURL_POLL_OUT)?"SENDING":"");
3555 }
3556 if(data->numsocks)
3557 fprintf(stderr, "\n");
3558 }
3559 }
3560 }
3561 #endif
3562
3563 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3564 {
3565 DEBUGASSERT(multi);
3566 return multi->max_concurrent_streams;
3567 }
3568