source: EcnlProtoTool/trunk/curl-7.57.0/lib/multi.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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