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