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