VirtualBox

source: vbox/trunk/src/libs/curl-7.64.0/lib/multi.c@ 94601

Last change on this file since 94601 was 85671, checked in by vboxsync, 4 years ago

Export out internal curl copy to make it a lot simpler to build VBox (OSE) on Windows. bugref:9814

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette