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