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