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