multi.c (122154B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #include <curl/curl.h> 28 29 #include "urldata.h" 30 #include "transfer.h" 31 #include "url.h" 32 #include "cfilters.h" 33 #include "connect.h" 34 #include "progress.h" 35 #include "easyif.h" 36 #include "share.h" 37 #include "psl.h" 38 #include "multiif.h" 39 #include "multi_ev.h" 40 #include "sendf.h" 41 #include "curlx/timeval.h" 42 #include "http.h" 43 #include "select.h" 44 #include "curlx/warnless.h" 45 #include "curlx/wait.h" 46 #include "speedcheck.h" 47 #include "conncache.h" 48 #include "multihandle.h" 49 #include "sigpipe.h" 50 #include "vtls/vtls.h" 51 #include "vtls/vtls_scache.h" 52 #include "http_proxy.h" 53 #include "http2.h" 54 #include "socketpair.h" 55 #include "socks.h" 56 #include "urlapi-int.h" 57 /* The last 3 #include files should be in this order */ 58 #include "curl_printf.h" 59 #include "curl_memory.h" 60 #include "memdebug.h" 61 62 /* initial multi->xfers table size for a full multi */ 63 #define CURL_XFER_TABLE_SIZE 512 64 65 /* 66 CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 67 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every 68 curl handle takes 6K memory, therefore this 3K are not significant. 69 */ 70 #ifndef CURL_SOCKET_HASH_TABLE_SIZE 71 #define CURL_SOCKET_HASH_TABLE_SIZE 911 72 #endif 73 74 #ifndef CURL_CONNECTION_HASH_SIZE 75 #define CURL_CONNECTION_HASH_SIZE 97 76 #endif 77 78 #ifndef CURL_DNS_HASH_SIZE 79 #define CURL_DNS_HASH_SIZE 71 80 #endif 81 82 #ifndef CURL_TLS_SESSION_SIZE 83 #define CURL_TLS_SESSION_SIZE 25 84 #endif 85 86 #define CURL_MULTI_HANDLE 0x000bab1e 87 88 #ifdef DEBUGBUILD 89 /* On a debug build, we want to fail hard on multi handles that 90 * are not NULL, but no longer have the MAGIC touch. This gives 91 * us early warning on things only discovered by valgrind otherwise. */ 92 #define GOOD_MULTI_HANDLE(x) \ 93 (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE: \ 94 (DEBUGASSERT(!(x)), FALSE)) 95 #else 96 #define GOOD_MULTI_HANDLE(x) \ 97 ((x) && (x)->magic == CURL_MULTI_HANDLE) 98 #endif 99 100 static void move_pending_to_connect(struct Curl_multi *multi, 101 struct Curl_easy *data); 102 static CURLMcode add_next_timeout(struct curltime now, 103 struct Curl_multi *multi, 104 struct Curl_easy *d); 105 static CURLMcode multi_timeout(struct Curl_multi *multi, 106 struct curltime *expire_time, 107 long *timeout_ms); 108 static void process_pending_handles(struct Curl_multi *multi); 109 static void multi_xfer_bufs_free(struct Curl_multi *multi); 110 #ifdef DEBUGBUILD 111 static void multi_xfer_tbl_dump(struct Curl_multi *multi); 112 #endif 113 114 /* function pointer called once when switching TO a state */ 115 typedef void (*init_multistate_func)(struct Curl_easy *data); 116 117 /* called in DID state, before PERFORMING state */ 118 static void before_perform(struct Curl_easy *data) 119 { 120 data->req.chunk = FALSE; 121 Curl_pgrsTime(data, TIMER_PRETRANSFER); 122 } 123 124 static void init_completed(struct Curl_easy *data) 125 { 126 /* this is a completed transfer */ 127 128 /* Important: reset the conn pointer so that we do not point to memory 129 that could be freed anytime */ 130 Curl_detach_connection(data); 131 Curl_expire_clear(data); /* stop all timers */ 132 } 133 134 /* always use this function to change state, to make debugging easier */ 135 static void mstate(struct Curl_easy *data, CURLMstate state 136 #ifdef DEBUGBUILD 137 , int lineno 138 #endif 139 ) 140 { 141 CURLMstate oldstate = data->mstate; 142 static const init_multistate_func finit[MSTATE_LAST] = { 143 NULL, /* INIT */ 144 NULL, /* PENDING */ 145 NULL, /* SETUP */ 146 Curl_init_CONNECT, /* CONNECT */ 147 NULL, /* RESOLVING */ 148 NULL, /* CONNECTING */ 149 NULL, /* TUNNELING */ 150 NULL, /* PROTOCONNECT */ 151 NULL, /* PROTOCONNECTING */ 152 NULL, /* DO */ 153 NULL, /* DOING */ 154 NULL, /* DOING_MORE */ 155 before_perform, /* DID */ 156 NULL, /* PERFORMING */ 157 NULL, /* RATELIMITING */ 158 NULL, /* DONE */ 159 init_completed, /* COMPLETED */ 160 NULL /* MSGSENT */ 161 }; 162 163 if(oldstate == state) 164 /* do not bother when the new state is the same as the old state */ 165 return; 166 167 #ifdef DEBUGBUILD 168 CURL_TRC_M(data, "-> [%s] (line %d)", CURL_MSTATE_NAME(state), lineno); 169 #else 170 CURL_TRC_M(data, "-> [%s]", CURL_MSTATE_NAME(state)); 171 #endif 172 173 data->mstate = state; 174 175 if(state == MSTATE_COMPLETED) { 176 /* changing to COMPLETED means it is in process and needs to go */ 177 DEBUGASSERT(Curl_uint_bset_contains(&data->multi->process, data->mid)); 178 Curl_uint_bset_remove(&data->multi->process, data->mid); 179 Curl_uint_bset_remove(&data->multi->pending, data->mid); /* to be sure */ 180 181 if(Curl_uint_bset_empty(&data->multi->process)) { 182 /* free the transfer buffer when we have no more active transfers */ 183 multi_xfer_bufs_free(data->multi); 184 } 185 } 186 187 /* if this state has an init-function, run it */ 188 if(finit[state]) 189 finit[state](data); 190 } 191 192 #ifndef DEBUGBUILD 193 #define multistate(x,y) mstate(x,y) 194 #else 195 #define multistate(x,y) mstate(x,y, __LINE__) 196 #endif 197 198 199 /* multi->proto_hash destructor. Should never be called as elements 200 * MUST be added with their own destructor */ 201 static void ph_freeentry(void *p) 202 { 203 (void)p; 204 /* Will always be FALSE. Cannot use a 0 assert here since compilers 205 * are not in agreement if they then want a NORETURN attribute or 206 * not. *sigh* */ 207 DEBUGASSERT(p == NULL); 208 } 209 210 /* 211 * multi_addmsg() 212 * 213 * Called when a transfer is completed. Adds the given msg pointer to 214 * the list kept in the multi handle. 215 */ 216 static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg) 217 { 218 Curl_llist_append(&multi->msglist, msg, &msg->list); 219 } 220 221 struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, 222 size_t ev_hashsize, /* event hash */ 223 size_t chashsize, /* connection hash */ 224 size_t dnssize, /* dns hash */ 225 size_t sesssize) /* TLS session cache */ 226 { 227 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); 228 229 if(!multi) 230 return NULL; 231 232 multi->magic = CURL_MULTI_HANDLE; 233 234 Curl_dnscache_init(&multi->dnscache, dnssize); 235 Curl_multi_ev_init(multi, ev_hashsize); 236 Curl_uint_tbl_init(&multi->xfers, NULL); 237 Curl_uint_bset_init(&multi->process); 238 Curl_uint_bset_init(&multi->dirty); 239 Curl_uint_bset_init(&multi->pending); 240 Curl_uint_bset_init(&multi->msgsent); 241 Curl_hash_init(&multi->proto_hash, 23, 242 Curl_hash_str, curlx_str_key_compare, ph_freeentry); 243 Curl_llist_init(&multi->msglist, NULL); 244 245 multi->multiplexing = TRUE; 246 multi->max_concurrent_streams = 100; 247 multi->last_timeout_ms = -1; 248 249 if(Curl_uint_bset_resize(&multi->process, xfer_table_size) || 250 Curl_uint_bset_resize(&multi->pending, xfer_table_size) || 251 Curl_uint_bset_resize(&multi->dirty, xfer_table_size) || 252 Curl_uint_bset_resize(&multi->msgsent, xfer_table_size) || 253 Curl_uint_tbl_resize(&multi->xfers, xfer_table_size)) 254 goto error; 255 256 multi->admin = curl_easy_init(); 257 if(!multi->admin) 258 goto error; 259 /* Initialize admin handle to operate inside this multi */ 260 multi->admin->multi = multi; 261 multi->admin->state.internal = TRUE; 262 Curl_llist_init(&multi->admin->state.timeoutlist, NULL); 263 #ifdef DEBUGBUILD 264 if(getenv("CURL_DEBUG")) 265 multi->admin->set.verbose = TRUE; 266 #endif 267 Curl_uint_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid); 268 269 if(Curl_cshutdn_init(&multi->cshutdn, multi)) 270 goto error; 271 272 Curl_cpool_init(&multi->cpool, multi->admin, NULL, chashsize); 273 274 #ifdef USE_SSL 275 if(Curl_ssl_scache_create(sesssize, 2, &multi->ssl_scache)) 276 goto error; 277 #else 278 (void)sesssize; 279 #endif 280 281 #ifdef USE_WINSOCK 282 multi->wsa_event = WSACreateEvent(); 283 if(multi->wsa_event == WSA_INVALID_EVENT) 284 goto error; 285 #elif defined(ENABLE_WAKEUP) 286 if(wakeup_create(multi->wakeup_pair, TRUE) < 0) { 287 multi->wakeup_pair[0] = CURL_SOCKET_BAD; 288 multi->wakeup_pair[1] = CURL_SOCKET_BAD; 289 } 290 #endif 291 292 return multi; 293 294 error: 295 296 Curl_multi_ev_cleanup(multi); 297 Curl_hash_destroy(&multi->proto_hash); 298 Curl_dnscache_destroy(&multi->dnscache); 299 Curl_cpool_destroy(&multi->cpool); 300 Curl_cshutdn_destroy(&multi->cshutdn, multi->admin); 301 #ifdef USE_SSL 302 Curl_ssl_scache_destroy(multi->ssl_scache); 303 #endif 304 if(multi->admin) { 305 multi->admin->multi = NULL; 306 Curl_close(&multi->admin); 307 } 308 309 Curl_uint_bset_destroy(&multi->process); 310 Curl_uint_bset_destroy(&multi->dirty); 311 Curl_uint_bset_destroy(&multi->pending); 312 Curl_uint_bset_destroy(&multi->msgsent); 313 Curl_uint_tbl_destroy(&multi->xfers); 314 315 free(multi); 316 return NULL; 317 } 318 319 CURLM *curl_multi_init(void) 320 { 321 return Curl_multi_handle(CURL_XFER_TABLE_SIZE, 322 CURL_SOCKET_HASH_TABLE_SIZE, 323 CURL_CONNECTION_HASH_SIZE, 324 CURL_DNS_HASH_SIZE, 325 CURL_TLS_SESSION_SIZE); 326 } 327 328 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 329 static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data) 330 { 331 if(!multi->warned) { 332 infof(data, "!!! WARNING !!!"); 333 infof(data, "This is a debug build of libcurl, " 334 "do not use in production."); 335 multi->warned = TRUE; 336 } 337 } 338 #else 339 #define multi_warn_debug(x,y) Curl_nop_stmt 340 #endif 341 342 343 static CURLMcode multi_xfers_add(struct Curl_multi *multi, 344 struct Curl_easy *data) 345 { 346 unsigned int capacity = Curl_uint_tbl_capacity(&multi->xfers); 347 unsigned int new_size = 0; 348 /* Prepare to make this into a CURLMOPT_MAX_TRANSFERS, because some 349 * applications may want to prevent a run-away of their memory use. */ 350 /* UINT_MAX is our "invalid" id, do not let the table grow up to that. */ 351 const unsigned int max_capacity = UINT_MAX - 1; 352 353 if(capacity < max_capacity) { 354 /* We want `multi->xfers` to have "sufficient" free rows, so that we do 355 * have to reuse the `mid` from a just removed easy right away. 356 * Since uint_tbl and uint_bset are quite memory efficient, 357 * regard less than 25% free as insufficient. 358 * (for low capacities, e.g. multi_easy, 4 or less). */ 359 unsigned int used = Curl_uint_tbl_count(&multi->xfers); 360 unsigned int unused = capacity - used; 361 unsigned int min_unused = CURLMAX(capacity >> 2, 4); 362 if(unused <= min_unused) { 363 /* Make sure the uint arithmetic here works on the corner 364 * cases where we are close to max_capacity or UINT_MAX */ 365 if((min_unused >= max_capacity) || 366 ((max_capacity - min_unused) <= capacity) || 367 ((UINT_MAX - min_unused - 63) <= capacity)) { 368 new_size = max_capacity; /* can not be larger than this */ 369 } 370 else { 371 /* make it a 64 multiple, since our bitsets frow by that and 372 * small (easy_multi) grows to at least 64 on first resize. */ 373 new_size = (((used + min_unused) + 63) / 64) * 64; 374 } 375 } 376 } 377 378 if(new_size > capacity) { 379 /* Grow the bitsets first. Should one fail, we do not need 380 * to downsize the already resized ones. The sets continue 381 * to work properly when larger than the table, but not 382 * the other way around. */ 383 CURL_TRC_M(data, "increasing xfer table size to %u", new_size); 384 if(Curl_uint_bset_resize(&multi->process, new_size) || 385 Curl_uint_bset_resize(&multi->dirty, new_size) || 386 Curl_uint_bset_resize(&multi->pending, new_size) || 387 Curl_uint_bset_resize(&multi->msgsent, new_size) || 388 Curl_uint_tbl_resize(&multi->xfers, new_size)) 389 return CURLM_OUT_OF_MEMORY; 390 } 391 392 /* Insert the easy into the table now */ 393 if(!Curl_uint_tbl_add(&multi->xfers, data, &data->mid)) { 394 /* MUST only happen when table is full */ 395 DEBUGASSERT(Curl_uint_tbl_capacity(&multi->xfers) <= 396 Curl_uint_tbl_count(&multi->xfers)); 397 return CURLM_OUT_OF_MEMORY; 398 } 399 return CURLM_OK; 400 } 401 402 403 CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) 404 { 405 CURLMcode rc; 406 struct Curl_multi *multi = m; 407 struct Curl_easy *data = d; 408 /* First, make some basic checks that the CURLM handle is a good handle */ 409 if(!GOOD_MULTI_HANDLE(multi)) 410 return CURLM_BAD_HANDLE; 411 412 /* Verify that we got a somewhat good easy handle too */ 413 if(!GOOD_EASY_HANDLE(data)) 414 return CURLM_BAD_EASY_HANDLE; 415 416 /* Prevent users from adding same easy handle more than once and prevent 417 adding to more than one multi stack */ 418 if(data->multi) 419 return CURLM_ADDED_ALREADY; 420 421 if(multi->in_callback) 422 return CURLM_RECURSIVE_API_CALL; 423 424 if(multi->dead) { 425 /* a "dead" handle cannot get added transfers while any existing easy 426 handles are still alive - but if there are none alive anymore, it is 427 fine to start over and unmark the "deadness" of this handle. 428 This means only the admin handle MUST be present. */ 429 if((Curl_uint_tbl_count(&multi->xfers) != 1) || 430 !Curl_uint_tbl_contains(&multi->xfers, 0)) 431 return CURLM_ABORTED_BY_CALLBACK; 432 multi->dead = FALSE; 433 Curl_uint_bset_clear(&multi->process); 434 Curl_uint_bset_clear(&multi->dirty); 435 Curl_uint_bset_clear(&multi->pending); 436 Curl_uint_bset_clear(&multi->msgsent); 437 } 438 439 if(data->multi_easy) { 440 /* if this easy handle was previously used for curl_easy_perform(), there 441 is a private multi handle here that we can kill */ 442 curl_multi_cleanup(data->multi_easy); 443 data->multi_easy = NULL; 444 } 445 446 /* Insert the easy into the multi->xfers table, assigning it a `mid`. */ 447 if(multi_xfers_add(multi, data)) 448 return CURLM_OUT_OF_MEMORY; 449 450 /* Initialize timeout list for this handle */ 451 Curl_llist_init(&data->state.timeoutlist, NULL); 452 453 /* 454 * No failure allowed in this function beyond this point. No modification of 455 * easy nor multi handle allowed before this except for potential multi's 456 * connection pool growing which will not be undone in this function no 457 * matter what. 458 */ 459 if(data->set.errorbuffer) 460 data->set.errorbuffer[0] = 0; 461 462 data->state.os_errno = 0; 463 464 /* make the Curl_easy refer back to this multi handle - before Curl_expire() 465 is called. */ 466 data->multi = multi; 467 468 /* Set the timeout for this handle to expire really soon so that it will 469 be taken care of even when this handle is added in the midst of operation 470 when only the curl_multi_socket() API is used. During that flow, only 471 sockets that time-out or have actions will be dealt with. Since this 472 handle has no action yet, we make sure it times out to get things to 473 happen. */ 474 Curl_expire(data, 0, EXPIRE_RUN_NOW); 475 476 rc = Curl_update_timer(multi); 477 if(rc) { 478 data->multi = NULL; /* not anymore */ 479 Curl_uint_tbl_remove(&multi->xfers, data->mid); 480 data->mid = UINT_MAX; 481 return rc; 482 } 483 484 /* set the easy handle */ 485 multistate(data, MSTATE_INIT); 486 487 #ifdef USE_LIBPSL 488 /* Do the same for PSL. */ 489 if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL))) 490 data->psl = &data->share->psl; 491 else 492 data->psl = &multi->psl; 493 #endif 494 495 /* add the easy handle to the process set */ 496 Curl_uint_bset_add(&multi->process, data->mid); 497 ++multi->xfers_alive; 498 499 Curl_cpool_xfer_init(data); 500 multi_warn_debug(multi, data); 501 502 /* The admin handle only ever has default timeouts set. To improve the 503 state somewhat we clone the timeouts from each added handle so that the 504 admin handle always has the same timeouts as the most recently added 505 easy handle. */ 506 multi->admin->set.timeout = data->set.timeout; 507 multi->admin->set.server_response_timeout = 508 data->set.server_response_timeout; 509 multi->admin->set.no_signal = data->set.no_signal; 510 511 CURL_TRC_M(data, "added to multi, mid=%u, running=%u, total=%u", 512 data->mid, Curl_multi_xfers_running(multi), 513 Curl_uint_tbl_count(&multi->xfers)); 514 return CURLM_OK; 515 } 516 517 #if 0 518 /* Debug-function, used like this: 519 * 520 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash); 521 * 522 * Enable the hash print function first by editing hash.c 523 */ 524 static void debug_print_sock_hash(void *p) 525 { 526 struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p; 527 528 fprintf(stderr, " [readers %u][writers %u]", 529 sh->readers, sh->writers); 530 } 531 #endif 532 533 struct multi_done_ctx { 534 BIT(premature); 535 }; 536 537 static void multi_done_locked(struct connectdata *conn, 538 struct Curl_easy *data, 539 void *userdata) 540 { 541 struct multi_done_ctx *mdctx = userdata; 542 543 Curl_detach_connection(data); 544 545 CURL_TRC_M(data, "multi_done_locked, in use=%u", 546 Curl_uint_spbset_count(&conn->xfers_attached)); 547 if(CONN_INUSE(conn)) { 548 /* Stop if still used. */ 549 CURL_TRC_M(data, "Connection still in use %u, no more multi_done now!", 550 Curl_uint_spbset_count(&conn->xfers_attached)); 551 return; 552 } 553 554 data->state.done = TRUE; /* called just now! */ 555 data->state.recent_conn_id = conn->connection_id; 556 557 Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */ 558 Curl_resolv_unlink(data, &data->state.dns[1]); 559 Curl_dnscache_prune(data); 560 561 /* if data->set.reuse_forbid is TRUE, it means the libcurl client has 562 forced us to close this connection. This is ignored for requests taking 563 place in a NTLM/NEGOTIATE authentication handshake 564 565 if conn->bits.close is TRUE, it means that the connection should be 566 closed in spite of all our efforts to be nice, due to protocol 567 restrictions in our or the server's end 568 569 if premature is TRUE, it means this connection was said to be DONE before 570 the entire request operation is complete and thus we cannot know in what 571 state it is for reusing, so we are forced to close it. In a perfect world 572 we can add code that keep track of if we really must close it here or not, 573 but currently we have no such detail knowledge. 574 */ 575 576 if((data->set.reuse_forbid 577 #if defined(USE_NTLM) 578 && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || 579 conn->proxy_ntlm_state == NTLMSTATE_TYPE2) 580 #endif 581 #if defined(USE_SPNEGO) 582 && !(conn->http_negotiate_state == GSS_AUTHRECV || 583 conn->proxy_negotiate_state == GSS_AUTHRECV) 584 #endif 585 ) || conn->bits.close 586 || (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) { 587 CURL_TRC_M(data, "multi_done, not reusing connection=%" 588 FMT_OFF_T ", forbid=%d" 589 ", close=%d, premature=%d, conn_multiplex=%d", 590 conn->connection_id, data->set.reuse_forbid, 591 conn->bits.close, mdctx->premature, 592 Curl_conn_is_multiplex(conn, FIRSTSOCKET)); 593 connclose(conn, "disconnecting"); 594 Curl_conn_terminate(data, conn, mdctx->premature); 595 } 596 else { 597 /* the connection is no longer in use by any transfer */ 598 if(Curl_cpool_conn_now_idle(data, conn)) { 599 /* connection kept in the cpool */ 600 const char *host = 601 #ifndef CURL_DISABLE_PROXY 602 conn->bits.socksproxy ? 603 conn->socks_proxy.host.dispname : 604 conn->bits.httpproxy ? conn->http_proxy.host.dispname : 605 #endif 606 conn->bits.conn_to_host ? conn->conn_to_host.dispname : 607 conn->host.dispname; 608 data->state.lastconnect_id = conn->connection_id; 609 infof(data, "Connection #%" FMT_OFF_T " to host %s left intact", 610 conn->connection_id, host); 611 } 612 else { 613 /* connection was removed from the cpool and destroyed. */ 614 data->state.lastconnect_id = -1; 615 } 616 } 617 } 618 619 static CURLcode multi_done(struct Curl_easy *data, 620 CURLcode status, /* an error if this is called 621 after an error was detected */ 622 bool premature) 623 { 624 CURLcode result; 625 struct connectdata *conn = data->conn; 626 struct multi_done_ctx mdctx; 627 628 memset(&mdctx, 0, sizeof(mdctx)); 629 630 CURL_TRC_M(data, "multi_done: status: %d prem: %d done: %d", 631 (int)status, (int)premature, data->state.done); 632 633 if(data->state.done) 634 /* Stop if multi_done() has already been called */ 635 return CURLE_OK; 636 637 /* Shut down any ongoing async resolver operation. */ 638 Curl_async_shutdown(data); 639 640 /* Cleanup possible redirect junk */ 641 Curl_safefree(data->req.newurl); 642 Curl_safefree(data->req.location); 643 644 switch(status) { 645 case CURLE_ABORTED_BY_CALLBACK: 646 case CURLE_READ_ERROR: 647 case CURLE_WRITE_ERROR: 648 /* When we are aborted due to a callback return code it basically have to 649 be counted as premature as there is trouble ahead if we do not. We have 650 many callbacks and protocols work differently, we could potentially do 651 this more fine-grained in the future. */ 652 premature = TRUE; 653 FALLTHROUGH(); 654 default: 655 break; 656 } 657 658 /* this calls the protocol-specific function pointer previously set */ 659 if(conn->handler->done && (data->mstate >= MSTATE_PROTOCONNECT)) 660 result = conn->handler->done(data, status, premature); 661 else 662 result = status; 663 664 if(CURLE_ABORTED_BY_CALLBACK != result) { 665 /* avoid this if we already aborted by callback to avoid this calling 666 another callback */ 667 int rc = Curl_pgrsDone(data); 668 if(!result && rc) 669 result = CURLE_ABORTED_BY_CALLBACK; 670 } 671 672 /* Make sure that transfer client writes are really done now. */ 673 result = Curl_1st_err(result, Curl_xfer_write_done(data, premature)); 674 675 /* Inform connection filters that this transfer is done */ 676 Curl_conn_ev_data_done(data, premature); 677 678 process_pending_handles(data->multi); /* connection / multiplex */ 679 680 if(!result) 681 result = Curl_req_done(&data->req, data, premature); 682 683 /* Under the potential connection pool's share lock, decide what to 684 * do with the transfer's connection. */ 685 mdctx.premature = premature; 686 Curl_cpool_do_locked(data, data->conn, multi_done_locked, &mdctx); 687 688 /* flush the netrc cache */ 689 Curl_netrc_cleanup(&data->state.netrc); 690 return result; 691 } 692 693 static void close_connect_only(struct connectdata *conn, 694 struct Curl_easy *data, 695 void *userdata) 696 { 697 (void)userdata; 698 (void)data; 699 if(conn->connect_only) 700 connclose(conn, "Removing connect-only easy handle"); 701 } 702 703 CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) 704 { 705 struct Curl_multi *multi = m; 706 struct Curl_easy *data = d; 707 bool premature; 708 struct Curl_llist_node *e; 709 CURLMcode rc; 710 bool removed_timer = FALSE; 711 unsigned int mid; 712 713 /* First, make some basic checks that the CURLM handle is a good handle */ 714 if(!GOOD_MULTI_HANDLE(multi)) 715 return CURLM_BAD_HANDLE; 716 717 /* Verify that we got a somewhat good easy handle too */ 718 if(!GOOD_EASY_HANDLE(data)) 719 return CURLM_BAD_EASY_HANDLE; 720 721 /* Prevent users from trying to remove same easy handle more than once */ 722 if(!data->multi) 723 return CURLM_OK; /* it is already removed so let's say it is fine! */ 724 725 /* Prevent users from trying to remove an easy handle from the wrong multi */ 726 if(data->multi != multi) 727 return CURLM_BAD_EASY_HANDLE; 728 729 if(data->mid == UINT_MAX) { 730 DEBUGASSERT(0); 731 return CURLM_INTERNAL_ERROR; 732 } 733 if(Curl_uint_tbl_get(&multi->xfers, data->mid) != data) { 734 DEBUGASSERT(0); 735 return CURLM_INTERNAL_ERROR; 736 } 737 738 if(multi->in_callback) 739 return CURLM_RECURSIVE_API_CALL; 740 741 premature = (data->mstate < MSTATE_COMPLETED); 742 743 /* If the 'state' is not INIT or COMPLETED, we might need to do something 744 nice to put the easy_handle in a good known state when this returns. */ 745 if(data->conn && 746 data->mstate > MSTATE_DO && 747 data->mstate < MSTATE_COMPLETED) { 748 /* Set connection owner so that the DONE function closes it. We can 749 safely do this here since connection is killed. */ 750 streamclose(data->conn, "Removed with partial response"); 751 } 752 753 if(data->conn) { 754 /* multi_done() clears the association between the easy handle and the 755 connection. 756 757 Note that this ignores the return code simply because there is 758 nothing really useful to do with it anyway! */ 759 (void)multi_done(data, data->result, premature); 760 } 761 762 /* The timer must be shut down before data->multi is set to NULL, else the 763 timenode will remain in the splay tree after curl_easy_cleanup is 764 called. Do it after multi_done() in case that sets another time! */ 765 removed_timer = Curl_expire_clear(data); 766 767 /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */ 768 if(!Curl_uint_bset_contains(&multi->msgsent, data->mid)) 769 --multi->xfers_alive; 770 771 Curl_wildcard_dtor(&data->wildcard); 772 773 data->mstate = MSTATE_COMPLETED; 774 775 /* Remove the association between the connection and the handle */ 776 Curl_detach_connection(data); 777 778 /* Tell event handling that this transfer is definitely going away */ 779 Curl_multi_ev_xfer_done(multi, data); 780 781 if(data->set.connect_only && !data->multi_easy) { 782 /* This removes a handle that was part the multi interface that used 783 CONNECT_ONLY, that connection is now left alive but since this handle 784 has bits.close set nothing can use that transfer anymore and it is 785 forbidden from reuse. This easy handle cannot find the connection 786 anymore once removed from the multi handle 787 788 Better close the connection here, at once. 789 */ 790 struct connectdata *c; 791 curl_socket_t s; 792 s = Curl_getconnectinfo(data, &c); 793 if((s != CURL_SOCKET_BAD) && c) { 794 Curl_conn_terminate(data, c, TRUE); 795 } 796 } 797 798 if(data->state.lastconnect_id != -1) { 799 /* Mark any connect-only connection for closure */ 800 Curl_cpool_do_by_id(data, data->state.lastconnect_id, 801 close_connect_only, NULL); 802 } 803 804 #ifdef USE_LIBPSL 805 /* Remove the PSL association. */ 806 if(data->psl == &multi->psl) 807 data->psl = NULL; 808 #endif 809 810 /* make sure there is no pending message in the queue sent from this easy 811 handle */ 812 for(e = Curl_llist_head(&multi->msglist); e; e = Curl_node_next(e)) { 813 struct Curl_message *msg = Curl_node_elem(e); 814 815 if(msg->extmsg.easy_handle == data) { 816 Curl_node_remove(e); 817 /* there can only be one from this specific handle */ 818 break; 819 } 820 } 821 822 /* clear the association to this multi handle */ 823 mid = data->mid; 824 DEBUGASSERT(Curl_uint_tbl_contains(&multi->xfers, mid)); 825 Curl_uint_tbl_remove(&multi->xfers, mid); 826 Curl_uint_bset_remove(&multi->process, mid); 827 Curl_uint_bset_remove(&multi->dirty, mid); 828 Curl_uint_bset_remove(&multi->pending, mid); 829 Curl_uint_bset_remove(&multi->msgsent, mid); 830 data->multi = NULL; 831 data->mid = UINT_MAX; 832 data->master_mid = UINT_MAX; 833 834 /* NOTE NOTE NOTE 835 We do not touch the easy handle here! */ 836 process_pending_handles(multi); 837 838 if(removed_timer) { 839 rc = Curl_update_timer(multi); 840 if(rc) 841 return rc; 842 } 843 844 CURL_TRC_M(data, "removed from multi, mid=%u, running=%u, total=%u", 845 mid, Curl_multi_xfers_running(multi), 846 Curl_uint_tbl_count(&multi->xfers)); 847 return CURLM_OK; 848 } 849 850 /* Return TRUE if the application asked for multiplexing */ 851 bool Curl_multiplex_wanted(const struct Curl_multi *multi) 852 { 853 return multi && multi->multiplexing; 854 } 855 856 /* 857 * Curl_detach_connection() removes the given transfer from the connection. 858 * 859 * This is the only function that should clear data->conn. This will 860 * occasionally be called with the data->conn pointer already cleared. 861 */ 862 void Curl_detach_connection(struct Curl_easy *data) 863 { 864 struct connectdata *conn = data->conn; 865 if(conn) { 866 Curl_uint_spbset_remove(&conn->xfers_attached, data->mid); 867 if(Curl_uint_spbset_empty(&conn->xfers_attached)) 868 conn->attached_multi = NULL; 869 } 870 data->conn = NULL; 871 } 872 873 /* 874 * Curl_attach_connection() attaches this transfer to this connection. 875 * 876 * This is the only function that should assign data->conn 877 */ 878 void Curl_attach_connection(struct Curl_easy *data, 879 struct connectdata *conn) 880 { 881 DEBUGASSERT(data); 882 DEBUGASSERT(!data->conn); 883 DEBUGASSERT(conn); 884 data->conn = conn; 885 Curl_uint_spbset_add(&conn->xfers_attached, data->mid); 886 /* all attached transfers must be from the same multi */ 887 if(!conn->attached_multi) 888 conn->attached_multi = data->multi; 889 DEBUGASSERT(conn->attached_multi == data->multi); 890 891 if(conn->handler && conn->handler->attach) 892 conn->handler->attach(data, conn); 893 } 894 895 static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks) 896 { 897 struct connectdata *conn = data->conn; 898 curl_socket_t sockfd; 899 900 if(!conn) 901 return GETSOCK_BLANK; 902 sockfd = Curl_conn_get_socket(data, FIRSTSOCKET); 903 if(sockfd != CURL_SOCKET_BAD) { 904 /* Default is to wait to something from the server */ 905 socks[0] = sockfd; 906 return GETSOCK_READSOCK(0); 907 } 908 return GETSOCK_BLANK; 909 } 910 911 static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks) 912 { 913 struct connectdata *conn = data->conn; 914 curl_socket_t sockfd; 915 916 if(!conn) 917 return GETSOCK_BLANK; 918 if(conn->handler->proto_getsock) 919 return conn->handler->proto_getsock(data, conn, socks); 920 sockfd = Curl_conn_get_socket(data, FIRSTSOCKET); 921 if(sockfd != CURL_SOCKET_BAD) { 922 /* Default is to wait to something from the server */ 923 socks[0] = sockfd; 924 return GETSOCK_READSOCK(0); 925 } 926 return GETSOCK_BLANK; 927 } 928 929 static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks) 930 { 931 struct connectdata *conn = data->conn; 932 if(!conn) 933 return GETSOCK_BLANK; 934 if(conn->handler->domore_getsock) 935 return conn->handler->domore_getsock(data, conn, socks); 936 else if(conn->sockfd != CURL_SOCKET_BAD) { 937 /* Default is that we want to send something to the server */ 938 socks[0] = conn->sockfd; 939 return GETSOCK_WRITESOCK(0); 940 } 941 return GETSOCK_BLANK; 942 } 943 944 static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks) 945 { 946 struct connectdata *conn = data->conn; 947 if(!conn) 948 return GETSOCK_BLANK; 949 if(conn->handler->doing_getsock) 950 return conn->handler->doing_getsock(data, conn, socks); 951 else if(conn->sockfd != CURL_SOCKET_BAD) { 952 /* Default is that we want to send something to the server */ 953 socks[0] = conn->sockfd; 954 return GETSOCK_WRITESOCK(0); 955 } 956 return GETSOCK_BLANK; 957 } 958 959 static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock) 960 { 961 struct connectdata *conn = data->conn; 962 if(!conn) 963 return GETSOCK_BLANK; 964 else if(conn->handler->perform_getsock) 965 return conn->handler->perform_getsock(data, conn, sock); 966 else { 967 /* Default is to obey the data->req.keepon flags for send/recv */ 968 int bitmap = GETSOCK_BLANK; 969 unsigned sockindex = 0; 970 if(CURL_WANT_RECV(data)) { 971 DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD); 972 bitmap |= GETSOCK_READSOCK(sockindex); 973 sock[sockindex] = conn->sockfd; 974 } 975 976 if(Curl_req_want_send(data)) { 977 if((conn->sockfd != conn->writesockfd) || 978 bitmap == GETSOCK_BLANK) { 979 /* only if they are not the same socket and we have a readable 980 one, we increase index */ 981 if(bitmap != GETSOCK_BLANK) 982 sockindex++; /* increase index if we need two entries */ 983 984 DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD); 985 sock[sockindex] = conn->writesockfd; 986 } 987 bitmap |= GETSOCK_WRITESOCK(sockindex); 988 } 989 return bitmap; 990 } 991 } 992 993 /* Initializes `poll_set` with the current socket poll actions needed 994 * for transfer `data`. */ 995 void Curl_multi_getsock(struct Curl_easy *data, 996 struct easy_pollset *ps, 997 const char *caller) 998 { 999 bool expect_sockets = TRUE; 1000 1001 /* If the transfer has no connection, this is fine. Happens when 1002 called via curl_multi_remove_handle() => Curl_multi_ev_assess() => 1003 Curl_multi_getsock(). */ 1004 Curl_pollset_reset(data, ps); 1005 if(!data->conn) 1006 return; 1007 1008 switch(data->mstate) { 1009 case MSTATE_INIT: 1010 case MSTATE_PENDING: 1011 case MSTATE_SETUP: 1012 case MSTATE_CONNECT: 1013 /* nothing to poll for yet */ 1014 expect_sockets = FALSE; 1015 break; 1016 1017 case MSTATE_RESOLVING: 1018 Curl_pollset_add_socks(data, ps, Curl_resolv_getsock); 1019 /* connection filters are not involved in this phase. It's ok if we get no 1020 * sockets to wait for. Resolving can wake up from other sources. */ 1021 expect_sockets = FALSE; 1022 break; 1023 1024 case MSTATE_CONNECTING: 1025 case MSTATE_TUNNELING: 1026 Curl_pollset_add_socks(data, ps, connecting_getsock); 1027 Curl_conn_adjust_pollset(data, data->conn, ps); 1028 break; 1029 1030 case MSTATE_PROTOCONNECT: 1031 case MSTATE_PROTOCONNECTING: 1032 Curl_pollset_add_socks(data, ps, protocol_getsock); 1033 Curl_conn_adjust_pollset(data, data->conn, ps); 1034 break; 1035 1036 case MSTATE_DO: 1037 case MSTATE_DOING: 1038 Curl_pollset_add_socks(data, ps, doing_getsock); 1039 Curl_conn_adjust_pollset(data, data->conn, ps); 1040 break; 1041 1042 case MSTATE_DOING_MORE: 1043 Curl_pollset_add_socks(data, ps, domore_getsock); 1044 Curl_conn_adjust_pollset(data, data->conn, ps); 1045 break; 1046 1047 case MSTATE_DID: /* same as PERFORMING in regard to polling */ 1048 case MSTATE_PERFORMING: 1049 Curl_pollset_add_socks(data, ps, perform_getsock); 1050 Curl_conn_adjust_pollset(data, data->conn, ps); 1051 break; 1052 1053 case MSTATE_RATELIMITING: 1054 /* we need to let time pass, ignore socket(s) */ 1055 expect_sockets = FALSE; 1056 break; 1057 1058 case MSTATE_DONE: 1059 case MSTATE_COMPLETED: 1060 case MSTATE_MSGSENT: 1061 /* nothing more to poll for */ 1062 expect_sockets = FALSE; 1063 break; 1064 1065 default: 1066 failf(data, "multi_getsock: unexpected multi state %d", data->mstate); 1067 DEBUGASSERT(0); 1068 expect_sockets = FALSE; 1069 break; 1070 } 1071 1072 1073 /* Unblocked and waiting to receive with buffered input. 1074 * Make transfer run again at next opportunity. */ 1075 if(!Curl_xfer_is_blocked(data) && 1076 ((Curl_pollset_want_read(data, ps, data->conn->sock[FIRSTSOCKET]) && 1077 Curl_conn_data_pending(data, FIRSTSOCKET)) || 1078 (Curl_pollset_want_read(data, ps, data->conn->sock[SECONDARYSOCKET]) && 1079 Curl_conn_data_pending(data, SECONDARYSOCKET)))) { 1080 CURL_TRC_M(data, "%s pollset[] has POLLIN, but there is still " 1081 "buffered input to consume -> mark as dirty", caller); 1082 Curl_multi_mark_dirty(data); 1083 } 1084 1085 switch(ps->num) { 1086 case 0: 1087 CURL_TRC_M(data, "%s pollset[], timeouts=%zu, paused %d/%d (r/w)", 1088 caller, Curl_llist_count(&data->state.timeoutlist), 1089 Curl_xfer_send_is_paused(data), 1090 Curl_xfer_recv_is_paused(data)); 1091 break; 1092 case 1: 1093 CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", 1094 caller, ps->sockets[0], 1095 (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", 1096 (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", 1097 Curl_llist_count(&data->state.timeoutlist)); 1098 break; 1099 case 2: 1100 CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s, " 1101 "fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", 1102 caller, ps->sockets[0], 1103 (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", 1104 (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", 1105 ps->sockets[1], 1106 (ps->actions[1] & CURL_POLL_IN) ? "IN" : "", 1107 (ps->actions[1] & CURL_POLL_OUT) ? "OUT" : "", 1108 Curl_llist_count(&data->state.timeoutlist)); 1109 break; 1110 default: 1111 CURL_TRC_M(data, "%s pollset[fds=%u], timeouts=%zu", 1112 caller, ps->num, Curl_llist_count(&data->state.timeoutlist)); 1113 break; 1114 } 1115 if(expect_sockets && !ps->num && 1116 !Curl_llist_count(&data->state.timeoutlist) && 1117 !Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) && 1118 Curl_conn_is_ip_connected(data, FIRSTSOCKET)) { 1119 /* We expected sockets for POLL monitoring, but none are set. 1120 * We are not waiting on any timer. 1121 * None of the READ/WRITE directions are paused. 1122 * We are connected to the server on IP level, at least. */ 1123 infof(data, "WARNING: no socket in pollset or timer, transfer may stall!"); 1124 DEBUGASSERT(0); 1125 } 1126 } 1127 1128 CURLMcode curl_multi_fdset(CURLM *m, 1129 fd_set *read_fd_set, fd_set *write_fd_set, 1130 fd_set *exc_fd_set, int *max_fd) 1131 { 1132 /* Scan through all the easy handles to get the file descriptors set. 1133 Some easy handles may not have connected to the remote host yet, 1134 and then we must make sure that is done. */ 1135 int this_max_fd = -1; 1136 struct Curl_multi *multi = m; 1137 unsigned int i, mid; 1138 (void)exc_fd_set; /* not used */ 1139 1140 if(!GOOD_MULTI_HANDLE(multi)) 1141 return CURLM_BAD_HANDLE; 1142 1143 if(multi->in_callback) 1144 return CURLM_RECURSIVE_API_CALL; 1145 1146 if(Curl_uint_bset_first(&multi->process, &mid)) { 1147 do { 1148 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 1149 struct easy_pollset ps; 1150 1151 if(!data) { 1152 DEBUGASSERT(0); 1153 continue; 1154 } 1155 1156 Curl_multi_getsock(data, &ps, "curl_multi_fdset"); 1157 for(i = 0; i < ps.num; i++) { 1158 if(!FDSET_SOCK(ps.sockets[i])) 1159 /* pretend it does not exist */ 1160 continue; 1161 #if defined(__DJGPP__) 1162 #pragma GCC diagnostic push 1163 #pragma GCC diagnostic ignored "-Warith-conversion" 1164 #endif 1165 if(ps.actions[i] & CURL_POLL_IN) 1166 FD_SET(ps.sockets[i], read_fd_set); 1167 if(ps.actions[i] & CURL_POLL_OUT) 1168 FD_SET(ps.sockets[i], write_fd_set); 1169 #if defined(__DJGPP__) 1170 #pragma GCC diagnostic pop 1171 #endif 1172 if((int)ps.sockets[i] > this_max_fd) 1173 this_max_fd = (int)ps.sockets[i]; 1174 } 1175 } 1176 while(Curl_uint_bset_next(&multi->process, mid, &mid)); 1177 } 1178 1179 Curl_cshutdn_setfds(&multi->cshutdn, multi->admin, 1180 read_fd_set, write_fd_set, &this_max_fd); 1181 1182 *max_fd = this_max_fd; 1183 1184 return CURLM_OK; 1185 } 1186 1187 CURLMcode curl_multi_waitfds(CURLM *m, 1188 struct curl_waitfd *ufds, 1189 unsigned int size, 1190 unsigned int *fd_count) 1191 { 1192 struct Curl_waitfds cwfds; 1193 CURLMcode result = CURLM_OK; 1194 struct Curl_multi *multi = m; 1195 unsigned int need = 0, mid; 1196 1197 if(!ufds && (size || !fd_count)) 1198 return CURLM_BAD_FUNCTION_ARGUMENT; 1199 1200 if(!GOOD_MULTI_HANDLE(multi)) 1201 return CURLM_BAD_HANDLE; 1202 1203 if(multi->in_callback) 1204 return CURLM_RECURSIVE_API_CALL; 1205 1206 Curl_waitfds_init(&cwfds, ufds, size); 1207 if(Curl_uint_bset_first(&multi->process, &mid)) { 1208 do { 1209 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 1210 struct easy_pollset ps; 1211 if(!data) { 1212 DEBUGASSERT(0); 1213 Curl_uint_bset_remove(&multi->process, mid); 1214 Curl_uint_bset_remove(&multi->dirty, mid); 1215 continue; 1216 } 1217 Curl_multi_getsock(data, &ps, "curl_multi_waitfds"); 1218 need += Curl_waitfds_add_ps(&cwfds, &ps); 1219 } 1220 while(Curl_uint_bset_next(&multi->process, mid, &mid)); 1221 } 1222 1223 need += Curl_cshutdn_add_waitfds(&multi->cshutdn, multi->admin, &cwfds); 1224 1225 if(need != cwfds.n && ufds) { 1226 result = CURLM_OUT_OF_MEMORY; 1227 } 1228 1229 if(fd_count) 1230 *fd_count = need; 1231 return result; 1232 } 1233 1234 #ifdef USE_WINSOCK 1235 /* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets cannot 1236 * be reset this way because an empty datagram would be sent. #9203 1237 * 1238 * "On Windows the internal state of FD_WRITE as returned from 1239 * WSAEnumNetworkEvents is only reset after successful send()." 1240 */ 1241 static void reset_socket_fdwrite(curl_socket_t s) 1242 { 1243 int t; 1244 int l = (int)sizeof(t); 1245 if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM) 1246 send(s, NULL, 0, 0); 1247 } 1248 #endif 1249 1250 #define NUM_POLLS_ON_STACK 10 1251 1252 static CURLMcode multi_wait(struct Curl_multi *multi, 1253 struct curl_waitfd extra_fds[], 1254 unsigned int extra_nfds, 1255 int timeout_ms, 1256 int *ret, 1257 bool extrawait, /* when no socket, wait */ 1258 bool use_wakeup) 1259 { 1260 size_t i; 1261 struct curltime expire_time; 1262 long timeout_internal; 1263 int retcode = 0; 1264 struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; 1265 struct curl_pollfds cpfds; 1266 unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */ 1267 struct Curl_easy *data = NULL; 1268 CURLMcode result = CURLM_OK; 1269 unsigned int mid; 1270 1271 #ifdef USE_WINSOCK 1272 WSANETWORKEVENTS wsa_events; 1273 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT); 1274 #endif 1275 #ifndef ENABLE_WAKEUP 1276 (void)use_wakeup; 1277 #endif 1278 1279 if(!GOOD_MULTI_HANDLE(multi)) 1280 return CURLM_BAD_HANDLE; 1281 1282 if(multi->in_callback) 1283 return CURLM_RECURSIVE_API_CALL; 1284 1285 if(timeout_ms < 0) 1286 return CURLM_BAD_FUNCTION_ARGUMENT; 1287 1288 Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK); 1289 1290 /* Add the curl handles to our pollfds first */ 1291 if(Curl_uint_bset_first(&multi->process, &mid)) { 1292 do { 1293 struct easy_pollset ps; 1294 data = Curl_multi_get_easy(multi, mid); 1295 if(!data) { 1296 DEBUGASSERT(0); 1297 Curl_uint_bset_remove(&multi->process, mid); 1298 Curl_uint_bset_remove(&multi->dirty, mid); 1299 continue; 1300 } 1301 Curl_multi_getsock(data, &ps, "multi_wait"); 1302 if(Curl_pollfds_add_ps(&cpfds, &ps)) { 1303 result = CURLM_OUT_OF_MEMORY; 1304 goto out; 1305 } 1306 } 1307 while(Curl_uint_bset_next(&multi->process, mid, &mid)); 1308 } 1309 1310 if(Curl_cshutdn_add_pollfds(&multi->cshutdn, multi->admin, &cpfds)) { 1311 result = CURLM_OUT_OF_MEMORY; 1312 goto out; 1313 } 1314 1315 curl_nfds = cpfds.n; /* what curl internally uses in cpfds */ 1316 /* Add external file descriptions from poll-like struct curl_waitfd */ 1317 for(i = 0; i < extra_nfds; i++) { 1318 unsigned short events = 0; 1319 if(extra_fds[i].events & CURL_WAIT_POLLIN) 1320 events |= POLLIN; 1321 if(extra_fds[i].events & CURL_WAIT_POLLPRI) 1322 events |= POLLPRI; 1323 if(extra_fds[i].events & CURL_WAIT_POLLOUT) 1324 events |= POLLOUT; 1325 if(Curl_pollfds_add_sock(&cpfds, extra_fds[i].fd, events)) { 1326 result = CURLM_OUT_OF_MEMORY; 1327 goto out; 1328 } 1329 } 1330 1331 #ifdef USE_WINSOCK 1332 /* Set the WSA events based on the collected pollds */ 1333 for(i = 0; i < cpfds.n; i++) { 1334 long mask = 0; 1335 if(cpfds.pfds[i].events & POLLIN) 1336 mask |= FD_READ|FD_ACCEPT|FD_CLOSE; 1337 if(cpfds.pfds[i].events & POLLPRI) 1338 mask |= FD_OOB; 1339 if(cpfds.pfds[i].events & POLLOUT) { 1340 mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; 1341 reset_socket_fdwrite(cpfds.pfds[i].fd); 1342 } 1343 if(mask) { 1344 if(WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, mask) != 0) { 1345 result = CURLM_OUT_OF_MEMORY; 1346 goto out; 1347 } 1348 } 1349 } 1350 #endif 1351 1352 #ifdef ENABLE_WAKEUP 1353 #ifndef USE_WINSOCK 1354 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { 1355 if(Curl_pollfds_add_sock(&cpfds, multi->wakeup_pair[0], POLLIN)) { 1356 result = CURLM_OUT_OF_MEMORY; 1357 goto out; 1358 } 1359 } 1360 #endif 1361 #endif 1362 1363 /* We check the internal timeout *AFTER* we collected all sockets to 1364 * poll. Collecting the sockets may install new timers by protocols 1365 * and connection filters. 1366 * Use the shorter one of the internal and the caller requested timeout. */ 1367 (void)multi_timeout(multi, &expire_time, &timeout_internal); 1368 if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms)) 1369 timeout_ms = (int)timeout_internal; 1370 1371 if(data) 1372 CURL_TRC_M(data, "multi_wait(fds=%d, timeout=%d) tinternal=%ld", 1373 cpfds.n, timeout_ms, timeout_internal); 1374 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) 1375 if(cpfds.n || use_wakeup) { 1376 #else 1377 if(cpfds.n) { 1378 #endif 1379 int pollrc; 1380 #ifdef USE_WINSOCK 1381 if(cpfds.n) /* just pre-check with Winsock */ 1382 pollrc = Curl_poll(cpfds.pfds, cpfds.n, 0); 1383 else 1384 pollrc = 0; 1385 #else 1386 pollrc = Curl_poll(cpfds.pfds, cpfds.n, timeout_ms); /* wait... */ 1387 #endif 1388 if(pollrc < 0) { 1389 result = CURLM_UNRECOVERABLE_POLL; 1390 goto out; 1391 } 1392 1393 if(pollrc > 0) { 1394 retcode = pollrc; 1395 #ifdef USE_WINSOCK 1396 } 1397 else { /* now wait... if not ready during the pre-check (pollrc == 0) */ 1398 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, (DWORD)timeout_ms, 1399 FALSE); 1400 } 1401 /* With Winsock, we have to run the following section unconditionally 1402 to call WSAEventSelect(fd, event, 0) on all the sockets */ 1403 { 1404 #endif 1405 /* copy revents results from the poll to the curl_multi_wait poll 1406 struct, the bit values of the actual underlying poll() implementation 1407 may not be the same as the ones in the public libcurl API! */ 1408 for(i = 0; i < extra_nfds; i++) { 1409 unsigned r = (unsigned)cpfds.pfds[curl_nfds + i].revents; 1410 unsigned short mask = 0; 1411 #ifdef USE_WINSOCK 1412 curl_socket_t s = extra_fds[i].fd; 1413 wsa_events.lNetworkEvents = 0; 1414 if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) { 1415 if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)) 1416 mask |= CURL_WAIT_POLLIN; 1417 if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE)) 1418 mask |= CURL_WAIT_POLLOUT; 1419 if(wsa_events.lNetworkEvents & FD_OOB) 1420 mask |= CURL_WAIT_POLLPRI; 1421 if(ret && !pollrc && wsa_events.lNetworkEvents) 1422 retcode++; 1423 } 1424 WSAEventSelect(s, multi->wsa_event, 0); 1425 if(!pollrc) { 1426 extra_fds[i].revents = (short)mask; 1427 continue; 1428 } 1429 #endif 1430 if(r & POLLIN) 1431 mask |= CURL_WAIT_POLLIN; 1432 if(r & POLLOUT) 1433 mask |= CURL_WAIT_POLLOUT; 1434 if(r & POLLPRI) 1435 mask |= CURL_WAIT_POLLPRI; 1436 extra_fds[i].revents = (short)mask; 1437 } 1438 1439 #ifdef USE_WINSOCK 1440 /* Count up all our own sockets that had activity, 1441 and remove them from the event. */ 1442 for(i = 0; i < curl_nfds; ++i) { 1443 wsa_events.lNetworkEvents = 0; 1444 if(WSAEnumNetworkEvents(cpfds.pfds[i].fd, NULL, &wsa_events) == 0) { 1445 if(ret && !pollrc && wsa_events.lNetworkEvents) 1446 retcode++; 1447 } 1448 WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, 0); 1449 } 1450 WSAResetEvent(multi->wsa_event); 1451 #else 1452 #ifdef ENABLE_WAKEUP 1453 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { 1454 if(cpfds.pfds[curl_nfds + extra_nfds].revents & POLLIN) { 1455 char buf[64]; 1456 ssize_t nread; 1457 while(1) { 1458 /* the reading socket is non-blocking, try to read 1459 data from it until it receives an error (except EINTR). 1460 In normal cases it will get EAGAIN or EWOULDBLOCK 1461 when there is no more data, breaking the loop. */ 1462 nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf)); 1463 if(nread <= 0) { 1464 if(nread < 0 && SOCKEINTR == SOCKERRNO) 1465 continue; 1466 break; 1467 } 1468 } 1469 /* do not count the wakeup socket into the returned value */ 1470 retcode--; 1471 } 1472 } 1473 #endif 1474 #endif 1475 } 1476 } 1477 1478 if(ret) 1479 *ret = retcode; 1480 #if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) 1481 if(extrawait && !cpfds.n && !use_wakeup) { 1482 #else 1483 if(extrawait && !cpfds.n) { 1484 #endif 1485 long sleep_ms = 0; 1486 1487 /* Avoid busy-looping when there is nothing particular to wait for */ 1488 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) { 1489 if(sleep_ms > timeout_ms) 1490 sleep_ms = timeout_ms; 1491 /* when there are no easy handles in the multi, this holds a -1 1492 timeout */ 1493 else if(sleep_ms < 0) 1494 sleep_ms = timeout_ms; 1495 curlx_wait_ms(sleep_ms); 1496 } 1497 } 1498 1499 out: 1500 Curl_pollfds_cleanup(&cpfds); 1501 return result; 1502 } 1503 1504 CURLMcode curl_multi_wait(CURLM *multi, 1505 struct curl_waitfd extra_fds[], 1506 unsigned int extra_nfds, 1507 int timeout_ms, 1508 int *ret) 1509 { 1510 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE, 1511 FALSE); 1512 } 1513 1514 CURLMcode curl_multi_poll(CURLM *multi, 1515 struct curl_waitfd extra_fds[], 1516 unsigned int extra_nfds, 1517 int timeout_ms, 1518 int *ret) 1519 { 1520 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE, 1521 TRUE); 1522 } 1523 1524 CURLMcode curl_multi_wakeup(CURLM *m) 1525 { 1526 /* this function is usually called from another thread, 1527 it has to be careful only to access parts of the 1528 Curl_multi struct that are constant */ 1529 struct Curl_multi *multi = m; 1530 1531 /* GOOD_MULTI_HANDLE can be safely called */ 1532 if(!GOOD_MULTI_HANDLE(multi)) 1533 return CURLM_BAD_HANDLE; 1534 1535 #ifdef ENABLE_WAKEUP 1536 #ifdef USE_WINSOCK 1537 if(WSASetEvent(multi->wsa_event)) 1538 return CURLM_OK; 1539 #else 1540 /* the wakeup_pair variable is only written during init and cleanup, 1541 making it safe to access from another thread after the init part 1542 and before cleanup */ 1543 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) { 1544 while(1) { 1545 #ifdef USE_EVENTFD 1546 /* eventfd has a stringent rule of requiring the 8-byte buffer when 1547 calling write(2) on it */ 1548 const uint64_t buf[1] = { 1 }; 1549 #else 1550 const char buf[1] = { 1 }; 1551 #endif 1552 /* swrite() is not thread-safe in general, because concurrent calls 1553 can have their messages interleaved, but in this case the content 1554 of the messages does not matter, which makes it ok to call. 1555 1556 The write socket is set to non-blocking, this way this function 1557 cannot block, making it safe to call even from the same thread 1558 that will call curl_multi_wait(). If swrite() returns that it 1559 would block, it is considered successful because it means that 1560 previous calls to this function will wake up the poll(). */ 1561 if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) { 1562 int err = SOCKERRNO; 1563 int return_success; 1564 #ifdef USE_WINSOCK 1565 return_success = SOCKEWOULDBLOCK == err; 1566 #else 1567 if(SOCKEINTR == err) 1568 continue; 1569 return_success = SOCKEWOULDBLOCK == err || EAGAIN == err; 1570 #endif 1571 if(!return_success) 1572 return CURLM_WAKEUP_FAILURE; 1573 } 1574 return CURLM_OK; 1575 } 1576 } 1577 #endif 1578 #endif 1579 return CURLM_WAKEUP_FAILURE; 1580 } 1581 1582 /* 1583 * multi_ischanged() is called 1584 * 1585 * Returns TRUE/FALSE whether the state is changed to trigger a CONNECT_PEND 1586 * => CONNECT action. 1587 * 1588 * Set 'clear' to TRUE to have it also clear the state variable. 1589 */ 1590 static bool multi_ischanged(struct Curl_multi *multi, bool clear) 1591 { 1592 bool retval = multi->recheckstate; 1593 if(clear) 1594 multi->recheckstate = FALSE; 1595 return retval; 1596 } 1597 1598 /* 1599 * Curl_multi_connchanged() is called to tell that there is a connection in 1600 * this multi handle that has changed state (multiplexing become possible, the 1601 * number of allowed streams changed or similar), and a subsequent use of this 1602 * multi handle should move CONNECT_PEND handles back to CONNECT to have them 1603 * retry. 1604 */ 1605 void Curl_multi_connchanged(struct Curl_multi *multi) 1606 { 1607 multi->recheckstate = TRUE; 1608 } 1609 1610 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, 1611 struct Curl_easy *data, 1612 struct connectdata *conn) 1613 { 1614 CURLMcode rc; 1615 1616 if(multi->in_callback) 1617 return CURLM_RECURSIVE_API_CALL; 1618 1619 rc = curl_multi_add_handle(multi, data); 1620 if(!rc) { 1621 struct SingleRequest *k = &data->req; 1622 CURLcode result; 1623 1624 /* pass in NULL for 'conn' here since we do not want to init the 1625 connection, only this transfer */ 1626 result = Curl_init_do(data, NULL); 1627 if(result) { 1628 curl_multi_remove_handle(multi, data); 1629 return CURLM_INTERNAL_ERROR; 1630 } 1631 1632 /* take this handle to the perform state right away */ 1633 multistate(data, MSTATE_PERFORMING); 1634 Curl_attach_connection(data, conn); 1635 k->keepon |= KEEP_RECV; /* setup to receive! */ 1636 } 1637 return rc; 1638 } 1639 1640 static CURLcode multi_do(struct Curl_easy *data, bool *done) 1641 { 1642 CURLcode result = CURLE_OK; 1643 struct connectdata *conn = data->conn; 1644 1645 DEBUGASSERT(conn); 1646 DEBUGASSERT(conn->handler); 1647 1648 if(conn->handler->do_it) 1649 result = conn->handler->do_it(data, done); 1650 1651 return result; 1652 } 1653 1654 /* 1655 * multi_do_more() is called during the DO_MORE multi state. It is basically a 1656 * second stage DO state which (wrongly) was introduced to support FTP's 1657 * second connection. 1658 * 1659 * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to 1660 * DOING state there is more work to do! 1661 */ 1662 1663 static CURLcode multi_do_more(struct Curl_easy *data, int *complete) 1664 { 1665 CURLcode result = CURLE_OK; 1666 struct connectdata *conn = data->conn; 1667 1668 *complete = 0; 1669 1670 if(conn->handler->do_more) 1671 result = conn->handler->do_more(data, complete); 1672 1673 return result; 1674 } 1675 1676 /* 1677 * Check whether a timeout occurred, and handle it if it did 1678 */ 1679 static bool multi_handle_timeout(struct Curl_easy *data, 1680 struct curltime *now, 1681 bool *stream_error, 1682 CURLcode *result) 1683 { 1684 bool connect_timeout = data->mstate < MSTATE_DO; 1685 timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout); 1686 if(timeout_ms < 0) { 1687 /* Handle timed out */ 1688 struct curltime since; 1689 if(connect_timeout) 1690 since = data->progress.t_startsingle; 1691 else 1692 since = data->progress.t_startop; 1693 if(data->mstate == MSTATE_RESOLVING) 1694 failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T 1695 " milliseconds", curlx_timediff(*now, since)); 1696 else if(data->mstate == MSTATE_CONNECTING) 1697 failf(data, "Connection timed out after %" FMT_TIMEDIFF_T 1698 " milliseconds", curlx_timediff(*now, since)); 1699 else { 1700 struct SingleRequest *k = &data->req; 1701 if(k->size != -1) { 1702 failf(data, "Operation timed out after %" FMT_TIMEDIFF_T 1703 " milliseconds with %" FMT_OFF_T " out of %" 1704 FMT_OFF_T " bytes received", 1705 curlx_timediff(*now, since), k->bytecount, k->size); 1706 } 1707 else { 1708 failf(data, "Operation timed out after %" FMT_TIMEDIFF_T 1709 " milliseconds with %" FMT_OFF_T " bytes received", 1710 curlx_timediff(*now, since), k->bytecount); 1711 } 1712 } 1713 *result = CURLE_OPERATION_TIMEDOUT; 1714 if(data->conn) { 1715 /* Force connection closed if the connection has indeed been used */ 1716 if(data->mstate > MSTATE_DO) { 1717 streamclose(data->conn, "Disconnect due to timeout"); 1718 *stream_error = TRUE; 1719 } 1720 (void)multi_done(data, *result, TRUE); 1721 } 1722 return TRUE; 1723 } 1724 1725 return FALSE; 1726 } 1727 1728 /* 1729 * We are doing protocol-specific connecting and this is being called over and 1730 * over from the multi interface until the connection phase is done on 1731 * protocol layer. 1732 */ 1733 1734 static CURLcode protocol_connecting(struct Curl_easy *data, bool *done) 1735 { 1736 CURLcode result = CURLE_OK; 1737 struct connectdata *conn = data->conn; 1738 1739 if(conn && conn->handler->connecting) { 1740 *done = FALSE; 1741 result = conn->handler->connecting(data, done); 1742 } 1743 else 1744 *done = TRUE; 1745 1746 return result; 1747 } 1748 1749 /* 1750 * We are DOING this is being called over and over from the multi interface 1751 * until the DOING phase is done on protocol layer. 1752 */ 1753 1754 static CURLcode protocol_doing(struct Curl_easy *data, bool *done) 1755 { 1756 CURLcode result = CURLE_OK; 1757 struct connectdata *conn = data->conn; 1758 1759 if(conn && conn->handler->doing) { 1760 *done = FALSE; 1761 result = conn->handler->doing(data, done); 1762 } 1763 else 1764 *done = TRUE; 1765 1766 return result; 1767 } 1768 1769 /* 1770 * We have discovered that the TCP connection has been successful, we can now 1771 * proceed with some action. 1772 * 1773 */ 1774 static CURLcode protocol_connect(struct Curl_easy *data, 1775 bool *protocol_done) 1776 { 1777 CURLcode result = CURLE_OK; 1778 struct connectdata *conn = data->conn; 1779 DEBUGASSERT(conn); 1780 DEBUGASSERT(protocol_done); 1781 1782 *protocol_done = FALSE; 1783 1784 if(Curl_conn_is_connected(conn, FIRSTSOCKET) 1785 && conn->bits.protoconnstart) { 1786 /* We already are connected, get back. This may happen when the connect 1787 worked fine in the first call, like when we connect to a local server 1788 or proxy. Note that we do not know if the protocol is actually done. 1789 1790 Unless this protocol does not have any protocol-connect callback, as 1791 then we know we are done. */ 1792 if(!conn->handler->connecting) 1793 *protocol_done = TRUE; 1794 1795 return CURLE_OK; 1796 } 1797 1798 if(!conn->bits.protoconnstart) { 1799 if(conn->handler->connect_it) { 1800 /* is there a protocol-specific connect() procedure? */ 1801 1802 /* Call the protocol-specific connect function */ 1803 result = conn->handler->connect_it(data, protocol_done); 1804 } 1805 else 1806 *protocol_done = TRUE; 1807 1808 /* it has started, possibly even completed but that knowledge is not stored 1809 in this bit! */ 1810 if(!result) 1811 conn->bits.protoconnstart = TRUE; 1812 } 1813 1814 return result; /* pass back status */ 1815 } 1816 1817 static void set_in_callback(struct Curl_multi *multi, bool value) 1818 { 1819 multi->in_callback = value; 1820 } 1821 1822 /* 1823 * posttransfer() is called immediately after a transfer ends 1824 */ 1825 static void multi_posttransfer(struct Curl_easy *data) 1826 { 1827 #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) 1828 /* restore the signal handler for SIGPIPE before we get back */ 1829 if(!data->set.no_signal) 1830 signal(SIGPIPE, data->state.prev_signal); 1831 #else 1832 (void)data; /* unused parameter */ 1833 #endif 1834 } 1835 1836 /* 1837 * multi_follow() handles the URL redirect magic. Pass in the 'newurl' string 1838 * as given by the remote server and set up the new URL to request. 1839 * 1840 * This function DOES NOT FREE the given url. 1841 */ 1842 static CURLcode multi_follow(struct Curl_easy *data, 1843 const struct Curl_handler *handler, 1844 const char *newurl, /* the Location: string */ 1845 followtype type) /* see transfer.h */ 1846 { 1847 if(handler && handler->follow) 1848 return handler->follow(data, newurl, type); 1849 return CURLE_TOO_MANY_REDIRECTS; 1850 } 1851 1852 static CURLMcode state_performing(struct Curl_easy *data, 1853 struct curltime *nowp, 1854 bool *stream_errorp, 1855 CURLcode *resultp) 1856 { 1857 char *newurl = NULL; 1858 bool retry = FALSE; 1859 timediff_t recv_timeout_ms = 0; 1860 timediff_t send_timeout_ms = 0; 1861 CURLMcode rc = CURLM_OK; 1862 CURLcode result = *resultp = CURLE_OK; 1863 *stream_errorp = FALSE; 1864 1865 /* check if over send speed */ 1866 if(data->set.max_send_speed) 1867 send_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.ul, 1868 data->set.max_send_speed, 1869 *nowp); 1870 1871 /* check if over recv speed */ 1872 if(data->set.max_recv_speed) 1873 recv_timeout_ms = Curl_pgrsLimitWaitTime(&data->progress.dl, 1874 data->set.max_recv_speed, 1875 *nowp); 1876 1877 if(send_timeout_ms || recv_timeout_ms) { 1878 Curl_ratelimit(data, *nowp); 1879 multistate(data, MSTATE_RATELIMITING); 1880 if(send_timeout_ms >= recv_timeout_ms) 1881 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); 1882 else 1883 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); 1884 return CURLM_OK; 1885 } 1886 1887 /* read/write data if it is ready to do so */ 1888 result = Curl_sendrecv(data, nowp); 1889 1890 if(data->req.done || (result == CURLE_RECV_ERROR)) { 1891 /* If CURLE_RECV_ERROR happens early enough, we assume it was a race 1892 * condition and the server closed the reused connection exactly when we 1893 * wanted to use it, so figure out if that is indeed the case. 1894 */ 1895 CURLcode ret = Curl_retry_request(data, &newurl); 1896 if(!ret) 1897 retry = !!newurl; 1898 else if(!result) 1899 result = ret; 1900 1901 if(retry) { 1902 /* if we are to retry, set the result to OK and consider the 1903 request as done */ 1904 result = CURLE_OK; 1905 data->req.done = TRUE; 1906 } 1907 } 1908 #ifndef CURL_DISABLE_HTTP 1909 else if((CURLE_HTTP2_STREAM == result) && 1910 Curl_h2_http_1_1_error(data)) { 1911 CURLcode ret = Curl_retry_request(data, &newurl); 1912 1913 if(!ret) { 1914 infof(data, "Downgrades to HTTP/1.1"); 1915 streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1"); 1916 data->state.http_neg.wanted = CURL_HTTP_V1x; 1917 data->state.http_neg.allowed = CURL_HTTP_V1x; 1918 /* clear the error message bit too as we ignore the one we got */ 1919 data->state.errorbuf = FALSE; 1920 if(!newurl) 1921 /* typically for HTTP_1_1_REQUIRED error on first flight */ 1922 newurl = strdup(data->state.url); 1923 /* if we are to retry, set the result to OK and consider the request 1924 as done */ 1925 retry = TRUE; 1926 result = CURLE_OK; 1927 data->req.done = TRUE; 1928 } 1929 else 1930 result = ret; 1931 } 1932 #endif 1933 1934 if(result) { 1935 /* 1936 * The transfer phase returned error, we mark the connection to get closed 1937 * to prevent being reused. This is because we cannot possibly know if the 1938 * connection is in a good shape or not now. Unless it is a protocol which 1939 * uses two "channels" like FTP, as then the error happened in the data 1940 * connection. 1941 */ 1942 1943 if(!(data->conn->handler->flags & PROTOPT_DUAL) && 1944 result != CURLE_HTTP2_STREAM) 1945 streamclose(data->conn, "Transfer returned error"); 1946 1947 multi_posttransfer(data); 1948 multi_done(data, result, TRUE); 1949 } 1950 else if(data->req.done && !Curl_cwriter_is_paused(data)) { 1951 const struct Curl_handler *handler = data->conn->handler; 1952 1953 /* call this even if the readwrite function returned error */ 1954 multi_posttransfer(data); 1955 1956 /* When we follow redirects or is set to retry the connection, we must to 1957 go back to the CONNECT state */ 1958 if(data->req.newurl || retry) { 1959 followtype follow = FOLLOW_NONE; 1960 if(!retry) { 1961 /* if the URL is a follow-location and not just a retried request then 1962 figure out the URL here */ 1963 free(newurl); 1964 newurl = data->req.newurl; 1965 data->req.newurl = NULL; 1966 follow = FOLLOW_REDIR; 1967 } 1968 else 1969 follow = FOLLOW_RETRY; 1970 (void)multi_done(data, CURLE_OK, FALSE); 1971 /* multi_done() might return CURLE_GOT_NOTHING */ 1972 result = multi_follow(data, handler, newurl, follow); 1973 if(!result) { 1974 multistate(data, MSTATE_SETUP); 1975 rc = CURLM_CALL_MULTI_PERFORM; 1976 } 1977 } 1978 else { 1979 /* after the transfer is done, go DONE */ 1980 1981 /* but first check to see if we got a location info even though we are 1982 not following redirects */ 1983 if(data->req.location) { 1984 free(newurl); 1985 newurl = data->req.location; 1986 data->req.location = NULL; 1987 result = multi_follow(data, handler, newurl, FOLLOW_FAKE); 1988 if(result) { 1989 *stream_errorp = TRUE; 1990 result = multi_done(data, result, TRUE); 1991 } 1992 } 1993 1994 if(!result) { 1995 multistate(data, MSTATE_DONE); 1996 rc = CURLM_CALL_MULTI_PERFORM; 1997 } 1998 } 1999 } 2000 free(newurl); 2001 *resultp = result; 2002 return rc; 2003 } 2004 2005 static CURLMcode state_do(struct Curl_easy *data, 2006 bool *stream_errorp, 2007 CURLcode *resultp) 2008 { 2009 CURLMcode rc = CURLM_OK; 2010 CURLcode result = CURLE_OK; 2011 if(data->set.fprereq) { 2012 int prereq_rc; 2013 2014 /* call the prerequest callback function */ 2015 Curl_set_in_callback(data, TRUE); 2016 prereq_rc = data->set.fprereq(data->set.prereq_userp, 2017 data->info.primary.remote_ip, 2018 data->info.primary.local_ip, 2019 data->info.primary.remote_port, 2020 data->info.primary.local_port); 2021 Curl_set_in_callback(data, FALSE); 2022 if(prereq_rc != CURL_PREREQFUNC_OK) { 2023 failf(data, "operation aborted by pre-request callback"); 2024 /* failure in pre-request callback - do not do any other processing */ 2025 result = CURLE_ABORTED_BY_CALLBACK; 2026 multi_posttransfer(data); 2027 multi_done(data, result, FALSE); 2028 *stream_errorp = TRUE; 2029 goto end; 2030 } 2031 } 2032 2033 if(data->set.connect_only && !data->set.connect_only_ws) { 2034 /* keep connection open for application to use the socket */ 2035 connkeep(data->conn, "CONNECT_ONLY"); 2036 multistate(data, MSTATE_DONE); 2037 rc = CURLM_CALL_MULTI_PERFORM; 2038 } 2039 else { 2040 bool dophase_done = FALSE; 2041 /* Perform the protocol's DO action */ 2042 result = multi_do(data, &dophase_done); 2043 2044 /* When multi_do() returns failure, data->conn might be NULL! */ 2045 2046 if(!result) { 2047 if(!dophase_done) { 2048 #ifndef CURL_DISABLE_FTP 2049 /* some steps needed for wildcard matching */ 2050 if(data->state.wildcardmatch) { 2051 struct WildcardData *wc = data->wildcard; 2052 if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { 2053 /* skip some states if it is important */ 2054 multi_done(data, CURLE_OK, FALSE); 2055 2056 /* if there is no connection left, skip the DONE state */ 2057 multistate(data, data->conn ? 2058 MSTATE_DONE : MSTATE_COMPLETED); 2059 rc = CURLM_CALL_MULTI_PERFORM; 2060 goto end; 2061 } 2062 } 2063 #endif 2064 /* DO was not completed in one function call, we must continue 2065 DOING... */ 2066 multistate(data, MSTATE_DOING); 2067 rc = CURLM_CALL_MULTI_PERFORM; 2068 } 2069 2070 /* after DO, go DO_DONE... or DO_MORE */ 2071 else if(data->conn->bits.do_more) { 2072 /* we are supposed to do more, but we need to sit down, relax and wait 2073 a little while first */ 2074 multistate(data, MSTATE_DOING_MORE); 2075 rc = CURLM_CALL_MULTI_PERFORM; 2076 } 2077 else { 2078 /* we are done with the DO, now DID */ 2079 multistate(data, MSTATE_DID); 2080 rc = CURLM_CALL_MULTI_PERFORM; 2081 } 2082 } 2083 else if((CURLE_SEND_ERROR == result) && 2084 data->conn->bits.reuse) { 2085 /* 2086 * In this situation, a connection that we were trying to use may have 2087 * unexpectedly died. If possible, send the connection back to the 2088 * CONNECT phase so we can try again. 2089 */ 2090 const struct Curl_handler *handler = data->conn->handler; 2091 char *newurl = NULL; 2092 followtype follow = FOLLOW_NONE; 2093 CURLcode drc; 2094 2095 drc = Curl_retry_request(data, &newurl); 2096 if(drc) { 2097 /* a failure here pretty much implies an out of memory */ 2098 result = drc; 2099 *stream_errorp = TRUE; 2100 } 2101 2102 multi_posttransfer(data); 2103 drc = multi_done(data, result, FALSE); 2104 2105 /* When set to retry the connection, we must go back to the CONNECT 2106 * state */ 2107 if(newurl) { 2108 if(!drc || (drc == CURLE_SEND_ERROR)) { 2109 follow = FOLLOW_RETRY; 2110 drc = multi_follow(data, handler, newurl, follow); 2111 if(!drc) { 2112 multistate(data, MSTATE_SETUP); 2113 rc = CURLM_CALL_MULTI_PERFORM; 2114 result = CURLE_OK; 2115 } 2116 else { 2117 /* Follow failed */ 2118 result = drc; 2119 } 2120 } 2121 else { 2122 /* done did not return OK or SEND_ERROR */ 2123 result = drc; 2124 } 2125 } 2126 else { 2127 /* Have error handler disconnect conn if we cannot retry */ 2128 *stream_errorp = TRUE; 2129 } 2130 free(newurl); 2131 } 2132 else { 2133 /* failure detected */ 2134 multi_posttransfer(data); 2135 if(data->conn) 2136 multi_done(data, result, FALSE); 2137 *stream_errorp = TRUE; 2138 } 2139 } 2140 end: 2141 *resultp = result; 2142 return rc; 2143 } 2144 2145 static CURLMcode state_ratelimiting(struct Curl_easy *data, 2146 struct curltime *nowp, 2147 CURLcode *resultp) 2148 { 2149 CURLcode result = CURLE_OK; 2150 CURLMcode rc = CURLM_OK; 2151 DEBUGASSERT(data->conn); 2152 /* if both rates are within spec, resume transfer */ 2153 if(Curl_pgrsUpdate(data)) 2154 result = CURLE_ABORTED_BY_CALLBACK; 2155 else 2156 result = Curl_speedcheck(data, *nowp); 2157 2158 if(result) { 2159 if(!(data->conn->handler->flags & PROTOPT_DUAL) && 2160 result != CURLE_HTTP2_STREAM) 2161 streamclose(data->conn, "Transfer returned error"); 2162 2163 multi_posttransfer(data); 2164 multi_done(data, result, TRUE); 2165 } 2166 else { 2167 timediff_t recv_timeout_ms = 0; 2168 timediff_t send_timeout_ms = 0; 2169 if(data->set.max_send_speed) 2170 send_timeout_ms = 2171 Curl_pgrsLimitWaitTime(&data->progress.ul, 2172 data->set.max_send_speed, 2173 *nowp); 2174 2175 if(data->set.max_recv_speed) 2176 recv_timeout_ms = 2177 Curl_pgrsLimitWaitTime(&data->progress.dl, 2178 data->set.max_recv_speed, 2179 *nowp); 2180 2181 if(!send_timeout_ms && !recv_timeout_ms) { 2182 multistate(data, MSTATE_PERFORMING); 2183 Curl_ratelimit(data, *nowp); 2184 /* start performing again right away */ 2185 rc = CURLM_CALL_MULTI_PERFORM; 2186 } 2187 else if(send_timeout_ms >= recv_timeout_ms) 2188 Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); 2189 else 2190 Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); 2191 } 2192 *resultp = result; 2193 return rc; 2194 } 2195 2196 static CURLMcode state_resolving(struct Curl_multi *multi, 2197 struct Curl_easy *data, 2198 bool *stream_errorp, 2199 CURLcode *resultp) 2200 { 2201 struct Curl_dns_entry *dns = NULL; 2202 CURLcode result; 2203 CURLMcode rc = CURLM_OK; 2204 2205 result = Curl_resolv_check(data, &dns); 2206 CURL_TRC_DNS(data, "Curl_resolv_check() -> %d, %s", 2207 result, dns ? "found" : "missing"); 2208 /* Update sockets here, because the socket(s) may have been closed and the 2209 application thus needs to be told, even if it is likely that the same 2210 socket(s) will again be used further down. If the name has not yet been 2211 resolved, it is likely that new sockets have been opened in an attempt to 2212 contact another resolver. */ 2213 rc = Curl_multi_ev_assess_xfer(multi, data); 2214 if(rc) 2215 return rc; 2216 2217 if(dns) { 2218 bool connected; 2219 /* Perform the next step in the connection phase, and then move on to the 2220 WAITCONNECT state */ 2221 result = Curl_once_resolved(data, dns, &connected); 2222 2223 if(result) 2224 /* if Curl_once_resolved() returns failure, the connection struct is 2225 already freed and gone */ 2226 data->conn = NULL; /* no more connection */ 2227 else { 2228 /* call again please so that we get the next socket setup */ 2229 rc = CURLM_CALL_MULTI_PERFORM; 2230 if(connected) 2231 multistate(data, MSTATE_PROTOCONNECT); 2232 else { 2233 multistate(data, MSTATE_CONNECTING); 2234 } 2235 } 2236 } 2237 2238 if(result) 2239 /* failure detected */ 2240 *stream_errorp = TRUE; 2241 2242 *resultp = result; 2243 return rc; 2244 } 2245 2246 static CURLMcode state_connect(struct Curl_multi *multi, 2247 struct Curl_easy *data, 2248 struct curltime *nowp, 2249 CURLcode *resultp) 2250 { 2251 /* Connect. We want to get a connection identifier filled in. This state can 2252 be entered from SETUP and from PENDING. */ 2253 bool connected; 2254 bool async; 2255 CURLMcode rc = CURLM_OK; 2256 CURLcode result = Curl_connect(data, &async, &connected); 2257 if(CURLE_NO_CONNECTION_AVAILABLE == result) { 2258 /* There was no connection available. We will go to the pending state and 2259 wait for an available connection. */ 2260 multistate(data, MSTATE_PENDING); 2261 /* move from process to pending set */ 2262 Curl_uint_bset_remove(&multi->process, data->mid); 2263 Curl_uint_bset_remove(&multi->dirty, data->mid); 2264 Curl_uint_bset_add(&multi->pending, data->mid); 2265 *resultp = CURLE_OK; 2266 return rc; 2267 } 2268 else 2269 process_pending_handles(data->multi); 2270 2271 if(!result) { 2272 *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE); 2273 if(async) 2274 /* We are now waiting for an asynchronous name lookup */ 2275 multistate(data, MSTATE_RESOLVING); 2276 else { 2277 /* after the connect has been sent off, go WAITCONNECT unless the 2278 protocol connect is already done and we can go directly to WAITDO or 2279 DO! */ 2280 rc = CURLM_CALL_MULTI_PERFORM; 2281 2282 if(connected) { 2283 if(!data->conn->bits.reuse && 2284 Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) { 2285 /* new connection, can multiplex, wake pending handles */ 2286 process_pending_handles(data->multi); 2287 } 2288 multistate(data, MSTATE_PROTOCONNECT); 2289 } 2290 else { 2291 multistate(data, MSTATE_CONNECTING); 2292 } 2293 } 2294 } 2295 *resultp = result; 2296 return rc; 2297 } 2298 2299 static CURLMcode multi_runsingle(struct Curl_multi *multi, 2300 struct curltime *nowp, 2301 struct Curl_easy *data) 2302 { 2303 struct Curl_message *msg = NULL; 2304 bool connected; 2305 bool protocol_connected = FALSE; 2306 bool dophase_done = FALSE; 2307 CURLMcode rc; 2308 CURLcode result = CURLE_OK; 2309 int control; 2310 2311 if(!GOOD_EASY_HANDLE(data)) 2312 return CURLM_BAD_EASY_HANDLE; 2313 2314 if(multi->dead) { 2315 /* a multi-level callback returned error before, meaning every individual 2316 transfer now has failed */ 2317 result = CURLE_ABORTED_BY_CALLBACK; 2318 multi_posttransfer(data); 2319 multi_done(data, result, FALSE); 2320 multistate(data, MSTATE_COMPLETED); 2321 } 2322 2323 multi_warn_debug(multi, data); 2324 2325 /* transfer runs now, clear the dirty bit. This may be set 2326 * again during processing, triggering a re-run later. */ 2327 Curl_uint_bset_remove(&multi->dirty, data->mid); 2328 2329 do { 2330 /* A "stream" here is a logical stream if the protocol can handle that 2331 (HTTP/2), or the full connection for older protocols */ 2332 bool stream_error = FALSE; 2333 rc = CURLM_OK; 2334 2335 if(multi_ischanged(multi, TRUE)) { 2336 CURL_TRC_M(data, "multi changed, check CONNECT_PEND queue"); 2337 process_pending_handles(multi); /* multiplexed */ 2338 } 2339 2340 if(data->mstate > MSTATE_CONNECT && 2341 data->mstate < MSTATE_COMPLETED) { 2342 /* Make sure we set the connection's current owner */ 2343 DEBUGASSERT(data->conn); 2344 if(!data->conn) 2345 return CURLM_INTERNAL_ERROR; 2346 } 2347 2348 /* Wait for the connect state as only then is the start time stored, but 2349 we must not check already completed handles */ 2350 if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) && 2351 multi_handle_timeout(data, nowp, &stream_error, &result)) 2352 /* Skip the statemachine and go directly to error handling section. */ 2353 goto statemachine_end; 2354 2355 switch(data->mstate) { 2356 case MSTATE_INIT: 2357 /* Transitional state. init this transfer. A handle never comes back to 2358 this state. */ 2359 result = Curl_pretransfer(data); 2360 if(result) 2361 break; 2362 2363 /* after init, go SETUP */ 2364 multistate(data, MSTATE_SETUP); 2365 (void)Curl_pgrsTime(data, TIMER_STARTOP); 2366 FALLTHROUGH(); 2367 2368 case MSTATE_SETUP: 2369 /* Transitional state. Setup things for a new transfer. The handle 2370 can come back to this state on a redirect. */ 2371 *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE); 2372 if(data->set.timeout) 2373 Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); 2374 if(data->set.connecttimeout) 2375 /* Since a connection might go to pending and back to CONNECT several 2376 times before it actually takes off, we need to set the timeout once 2377 in SETUP before we enter CONNECT the first time. */ 2378 Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT); 2379 2380 multistate(data, MSTATE_CONNECT); 2381 FALLTHROUGH(); 2382 2383 case MSTATE_CONNECT: 2384 rc = state_connect(multi, data, nowp, &result); 2385 break; 2386 2387 case MSTATE_RESOLVING: 2388 /* awaiting an asynch name resolve to complete */ 2389 rc = state_resolving(multi, data, &stream_error, &result); 2390 break; 2391 2392 #ifndef CURL_DISABLE_HTTP 2393 case MSTATE_TUNNELING: 2394 /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ 2395 DEBUGASSERT(data->conn); 2396 result = Curl_http_connect(data, &protocol_connected); 2397 if(!result) { 2398 rc = CURLM_CALL_MULTI_PERFORM; 2399 /* initiate protocol connect phase */ 2400 multistate(data, MSTATE_PROTOCONNECT); 2401 } 2402 else 2403 stream_error = TRUE; 2404 break; 2405 #endif 2406 2407 case MSTATE_CONNECTING: 2408 /* awaiting a completion of an asynch TCP connect */ 2409 DEBUGASSERT(data->conn); 2410 result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected); 2411 if(connected && !result) { 2412 if(!data->conn->bits.reuse && 2413 Curl_conn_is_multiplex(data->conn, FIRSTSOCKET)) { 2414 /* new connection, can multiplex, wake pending handles */ 2415 process_pending_handles(data->multi); 2416 } 2417 rc = CURLM_CALL_MULTI_PERFORM; 2418 multistate(data, MSTATE_PROTOCONNECT); 2419 } 2420 else if(result) { 2421 /* failure detected */ 2422 multi_posttransfer(data); 2423 multi_done(data, result, TRUE); 2424 stream_error = TRUE; 2425 break; 2426 } 2427 break; 2428 2429 case MSTATE_PROTOCONNECT: 2430 if(!result && data->conn->bits.reuse) { 2431 /* ftp seems to hang when protoconnect on reused connection since we 2432 * handle PROTOCONNECT in general inside the filers, it seems wrong to 2433 * restart this on a reused connection. 2434 */ 2435 multistate(data, MSTATE_DO); 2436 rc = CURLM_CALL_MULTI_PERFORM; 2437 break; 2438 } 2439 if(!result) 2440 result = protocol_connect(data, &protocol_connected); 2441 if(!result && !protocol_connected) { 2442 /* switch to waiting state */ 2443 multistate(data, MSTATE_PROTOCONNECTING); 2444 rc = CURLM_CALL_MULTI_PERFORM; 2445 } 2446 else if(!result) { 2447 /* protocol connect has completed, go WAITDO or DO */ 2448 multistate(data, MSTATE_DO); 2449 rc = CURLM_CALL_MULTI_PERFORM; 2450 } 2451 else { 2452 /* failure detected */ 2453 multi_posttransfer(data); 2454 multi_done(data, result, TRUE); 2455 stream_error = TRUE; 2456 } 2457 break; 2458 2459 case MSTATE_PROTOCONNECTING: 2460 /* protocol-specific connect phase */ 2461 result = protocol_connecting(data, &protocol_connected); 2462 if(!result && protocol_connected) { 2463 /* after the connect has completed, go WAITDO or DO */ 2464 multistate(data, MSTATE_DO); 2465 rc = CURLM_CALL_MULTI_PERFORM; 2466 } 2467 else if(result) { 2468 /* failure detected */ 2469 multi_posttransfer(data); 2470 multi_done(data, result, TRUE); 2471 stream_error = TRUE; 2472 } 2473 break; 2474 2475 case MSTATE_DO: 2476 rc = state_do(data, &stream_error, &result); 2477 break; 2478 2479 case MSTATE_DOING: 2480 /* we continue DOING until the DO phase is complete */ 2481 DEBUGASSERT(data->conn); 2482 result = protocol_doing(data, &dophase_done); 2483 if(!result) { 2484 if(dophase_done) { 2485 /* after DO, go DO_DONE or DO_MORE */ 2486 multistate(data, data->conn->bits.do_more ? 2487 MSTATE_DOING_MORE : MSTATE_DID); 2488 rc = CURLM_CALL_MULTI_PERFORM; 2489 } /* dophase_done */ 2490 } 2491 else { 2492 /* failure detected */ 2493 multi_posttransfer(data); 2494 multi_done(data, result, FALSE); 2495 stream_error = TRUE; 2496 } 2497 break; 2498 2499 case MSTATE_DOING_MORE: 2500 /* 2501 * When we are connected, DOING MORE and then go DID 2502 */ 2503 DEBUGASSERT(data->conn); 2504 result = multi_do_more(data, &control); 2505 2506 if(!result) { 2507 if(control) { 2508 /* if positive, advance to DO_DONE 2509 if negative, go back to DOING */ 2510 multistate(data, control == 1 ? 2511 MSTATE_DID : MSTATE_DOING); 2512 rc = CURLM_CALL_MULTI_PERFORM; 2513 } 2514 /* else 2515 stay in DO_MORE */ 2516 } 2517 else { 2518 /* failure detected */ 2519 multi_posttransfer(data); 2520 multi_done(data, result, FALSE); 2521 stream_error = TRUE; 2522 } 2523 break; 2524 2525 case MSTATE_DID: 2526 DEBUGASSERT(data->conn); 2527 if(data->conn->bits.multiplex) 2528 /* Check if we can move pending requests to send pipe */ 2529 process_pending_handles(multi); /* multiplexed */ 2530 2531 /* Only perform the transfer if there is a good socket to work with. 2532 Having both BAD is a signal to skip immediately to DONE */ 2533 if((data->conn->sockfd != CURL_SOCKET_BAD) || 2534 (data->conn->writesockfd != CURL_SOCKET_BAD)) 2535 multistate(data, MSTATE_PERFORMING); 2536 else { 2537 #ifndef CURL_DISABLE_FTP 2538 if(data->state.wildcardmatch && 2539 ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) { 2540 data->wildcard->state = CURLWC_DONE; 2541 } 2542 #endif 2543 multistate(data, MSTATE_DONE); 2544 } 2545 rc = CURLM_CALL_MULTI_PERFORM; 2546 break; 2547 2548 case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */ 2549 rc = state_ratelimiting(data, nowp, &result); 2550 break; 2551 2552 case MSTATE_PERFORMING: 2553 rc = state_performing(data, nowp, &stream_error, &result); 2554 break; 2555 2556 case MSTATE_DONE: 2557 /* this state is highly transient, so run another loop after this */ 2558 rc = CURLM_CALL_MULTI_PERFORM; 2559 2560 if(data->conn) { 2561 CURLcode res; 2562 2563 /* post-transfer command */ 2564 res = multi_done(data, result, FALSE); 2565 2566 /* allow a previously set error code take precedence */ 2567 if(!result) 2568 result = res; 2569 } 2570 2571 #ifndef CURL_DISABLE_FTP 2572 if(data->state.wildcardmatch) { 2573 if(data->wildcard->state != CURLWC_DONE) { 2574 /* if a wildcard is set and we are not ending -> lets start again 2575 with MSTATE_INIT */ 2576 multistate(data, MSTATE_INIT); 2577 break; 2578 } 2579 } 2580 #endif 2581 /* after we have DONE what we are supposed to do, go COMPLETED, and 2582 it does not matter what the multi_done() returned! */ 2583 multistate(data, MSTATE_COMPLETED); 2584 break; 2585 2586 case MSTATE_COMPLETED: 2587 break; 2588 2589 case MSTATE_PENDING: 2590 case MSTATE_MSGSENT: 2591 /* handles in these states should NOT be in this list */ 2592 break; 2593 2594 default: 2595 return CURLM_INTERNAL_ERROR; 2596 } 2597 2598 if(data->mstate >= MSTATE_CONNECT && 2599 data->mstate < MSTATE_DO && 2600 rc != CURLM_CALL_MULTI_PERFORM && 2601 !multi_ischanged(multi, FALSE)) { 2602 /* We now handle stream timeouts if and only if this will be the last 2603 * loop iteration. We only check this on the last iteration to ensure 2604 * that if we know we have additional work to do immediately 2605 * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before 2606 * declaring the connection timed out as we may almost have a completed 2607 * connection. */ 2608 multi_handle_timeout(data, nowp, &stream_error, &result); 2609 } 2610 2611 statemachine_end: 2612 2613 if(data->mstate < MSTATE_COMPLETED) { 2614 if(result) { 2615 /* 2616 * If an error was returned, and we are not in completed state now, 2617 * then we go to completed and consider this transfer aborted. 2618 */ 2619 2620 /* NOTE: no attempt to disconnect connections must be made 2621 in the case blocks above - cleanup happens only here */ 2622 2623 /* Check if we can move pending requests to send pipe */ 2624 process_pending_handles(multi); /* connection */ 2625 2626 if(data->conn) { 2627 if(stream_error) { 2628 /* Do not attempt to send data over a connection that timed out */ 2629 bool dead_connection = result == CURLE_OPERATION_TIMEDOUT; 2630 struct connectdata *conn = data->conn; 2631 2632 /* This is where we make sure that the conn pointer is reset. 2633 We do not have to do this in every case block above where a 2634 failure is detected */ 2635 Curl_detach_connection(data); 2636 Curl_conn_terminate(data, conn, dead_connection); 2637 } 2638 } 2639 else if(data->mstate == MSTATE_CONNECT) { 2640 /* Curl_connect() failed */ 2641 multi_posttransfer(data); 2642 Curl_pgrsUpdate_nometer(data); 2643 } 2644 2645 multistate(data, MSTATE_COMPLETED); 2646 rc = CURLM_CALL_MULTI_PERFORM; 2647 } 2648 /* if there is still a connection to use, call the progress function */ 2649 else if(data->conn && Curl_pgrsUpdate(data)) { 2650 /* aborted due to progress callback return code must close the 2651 connection */ 2652 result = CURLE_ABORTED_BY_CALLBACK; 2653 streamclose(data->conn, "Aborted by callback"); 2654 2655 /* if not yet in DONE state, go there, otherwise COMPLETED */ 2656 multistate(data, (data->mstate < MSTATE_DONE) ? 2657 MSTATE_DONE : MSTATE_COMPLETED); 2658 rc = CURLM_CALL_MULTI_PERFORM; 2659 } 2660 } 2661 2662 if(MSTATE_COMPLETED == data->mstate) { 2663 if(data->master_mid != UINT_MAX) { 2664 /* A sub transfer, not for msgsent to application */ 2665 struct Curl_easy *mdata; 2666 2667 CURL_TRC_M(data, "sub xfer done for master %u", data->master_mid); 2668 mdata = Curl_multi_get_easy(multi, data->master_mid); 2669 if(mdata) { 2670 if(mdata->sub_xfer_done) 2671 mdata->sub_xfer_done(mdata, data, result); 2672 else 2673 CURL_TRC_M(data, "master easy %u without sub_xfer_done callback.", 2674 data->master_mid); 2675 } 2676 else { 2677 CURL_TRC_M(data, "master easy %u already gone.", data->master_mid); 2678 } 2679 } 2680 else { 2681 /* now fill in the Curl_message with this info */ 2682 msg = &data->msg; 2683 2684 msg->extmsg.msg = CURLMSG_DONE; 2685 msg->extmsg.easy_handle = data; 2686 msg->extmsg.data.result = result; 2687 2688 multi_addmsg(multi, msg); 2689 DEBUGASSERT(!data->conn); 2690 } 2691 multistate(data, MSTATE_MSGSENT); 2692 2693 /* remove from the other sets, add to msgsent */ 2694 Curl_uint_bset_remove(&multi->process, data->mid); 2695 Curl_uint_bset_remove(&multi->dirty, data->mid); 2696 Curl_uint_bset_remove(&multi->pending, data->mid); 2697 Curl_uint_bset_add(&multi->msgsent, data->mid); 2698 --multi->xfers_alive; 2699 return CURLM_OK; 2700 } 2701 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); 2702 2703 data->result = result; 2704 return rc; 2705 } 2706 2707 2708 CURLMcode curl_multi_perform(CURLM *m, int *running_handles) 2709 { 2710 CURLMcode returncode = CURLM_OK; 2711 struct Curl_tree *t = NULL; 2712 struct curltime now = curlx_now(); 2713 struct Curl_multi *multi = m; 2714 unsigned int mid; 2715 SIGPIPE_VARIABLE(pipe_st); 2716 2717 if(!GOOD_MULTI_HANDLE(multi)) 2718 return CURLM_BAD_HANDLE; 2719 2720 if(multi->in_callback) 2721 return CURLM_RECURSIVE_API_CALL; 2722 2723 sigpipe_init(&pipe_st); 2724 if(Curl_uint_bset_first(&multi->process, &mid)) { 2725 CURL_TRC_M(multi->admin, "multi_perform(running=%u)", 2726 Curl_multi_xfers_running(multi)); 2727 do { 2728 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 2729 CURLMcode result; 2730 if(!data) { 2731 DEBUGASSERT(0); 2732 Curl_uint_bset_remove(&multi->process, mid); 2733 Curl_uint_bset_remove(&multi->dirty, mid); 2734 continue; 2735 } 2736 if(data != multi->admin) { 2737 /* admin handle is processed below */ 2738 sigpipe_apply(data, &pipe_st); 2739 result = multi_runsingle(multi, &now, data); 2740 if(result) 2741 returncode = result; 2742 } 2743 } 2744 while(Curl_uint_bset_next(&multi->process, mid, &mid)); 2745 } 2746 2747 sigpipe_apply(multi->admin, &pipe_st); 2748 Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT); 2749 sigpipe_restore(&pipe_st); 2750 2751 if(multi_ischanged(m, TRUE)) 2752 process_pending_handles(m); 2753 2754 /* 2755 * Simply remove all expired timers from the splay since handles are dealt 2756 * with unconditionally by this function and curl_multi_timeout() requires 2757 * that already passed/handled expire times are removed from the splay. 2758 * 2759 * It is important that the 'now' value is set at the entry of this function 2760 * and not for the current time as it may have ticked a little while since 2761 * then and then we risk this loop to remove timers that actually have not 2762 * been handled! 2763 */ 2764 do { 2765 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); 2766 if(t) { 2767 /* the removed may have another timeout in queue */ 2768 struct Curl_easy *data = Curl_splayget(t); 2769 if(data->mstate == MSTATE_PENDING) { 2770 bool stream_unused; 2771 CURLcode result_unused; 2772 if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) { 2773 infof(data, "PENDING handle timeout"); 2774 move_pending_to_connect(multi, data); 2775 } 2776 } 2777 (void)add_next_timeout(now, multi, Curl_splayget(t)); 2778 } 2779 } while(t); 2780 2781 if(running_handles) { 2782 unsigned int running = Curl_multi_xfers_running(multi); 2783 *running_handles = (running < INT_MAX) ? (int)running : INT_MAX; 2784 } 2785 2786 if(CURLM_OK >= returncode) 2787 returncode = Curl_update_timer(multi); 2788 2789 return returncode; 2790 } 2791 2792 CURLMcode curl_multi_cleanup(CURLM *m) 2793 { 2794 struct Curl_multi *multi = m; 2795 if(GOOD_MULTI_HANDLE(multi)) { 2796 void *entry; 2797 unsigned int mid; 2798 if(multi->in_callback) 2799 return CURLM_RECURSIVE_API_CALL; 2800 2801 /* First remove all remaining easy handles, 2802 * close internal ones. admin handle is special */ 2803 if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { 2804 do { 2805 struct Curl_easy *data = entry; 2806 if(!GOOD_EASY_HANDLE(data)) 2807 return CURLM_BAD_HANDLE; 2808 2809 #ifdef DEBUGBUILD 2810 if(mid != data->mid) { 2811 CURL_TRC_M(data, "multi_cleanup: still present with mid=%u, " 2812 "but unexpected data->mid=%u\n", mid, data->mid); 2813 DEBUGASSERT(0); 2814 } 2815 #endif 2816 2817 if(data == multi->admin) 2818 continue; 2819 2820 if(!data->state.done && data->conn) 2821 /* if DONE was never called for this handle */ 2822 (void)multi_done(data, CURLE_OK, TRUE); 2823 2824 data->multi = NULL; /* clear the association */ 2825 Curl_uint_tbl_remove(&multi->xfers, mid); 2826 data->mid = UINT_MAX; 2827 2828 #ifdef USE_LIBPSL 2829 if(data->psl == &multi->psl) 2830 data->psl = NULL; 2831 #endif 2832 if(data->state.internal) 2833 Curl_close(&data); 2834 } 2835 while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)); 2836 } 2837 2838 Curl_cpool_destroy(&multi->cpool); 2839 Curl_cshutdn_destroy(&multi->cshutdn, multi->admin); 2840 if(multi->admin) { 2841 CURL_TRC_M(multi->admin, "multi_cleanup, closing admin handle, done"); 2842 multi->admin->multi = NULL; 2843 Curl_uint_tbl_remove(&multi->xfers, multi->admin->mid); 2844 Curl_close(&multi->admin); 2845 } 2846 2847 multi->magic = 0; /* not good anymore */ 2848 2849 Curl_multi_ev_cleanup(multi); 2850 Curl_hash_destroy(&multi->proto_hash); 2851 Curl_dnscache_destroy(&multi->dnscache); 2852 Curl_psl_destroy(&multi->psl); 2853 #ifdef USE_SSL 2854 Curl_ssl_scache_destroy(multi->ssl_scache); 2855 #endif 2856 2857 #ifdef USE_WINSOCK 2858 WSACloseEvent(multi->wsa_event); 2859 #else 2860 #ifdef ENABLE_WAKEUP 2861 wakeup_close(multi->wakeup_pair[0]); 2862 #ifndef USE_EVENTFD 2863 wakeup_close(multi->wakeup_pair[1]); 2864 #endif 2865 #endif 2866 #endif 2867 2868 multi_xfer_bufs_free(multi); 2869 #ifdef DEBUGBUILD 2870 if(Curl_uint_tbl_count(&multi->xfers)) { 2871 multi_xfer_tbl_dump(multi); 2872 DEBUGASSERT(0); 2873 } 2874 #endif 2875 Curl_uint_bset_destroy(&multi->process); 2876 Curl_uint_bset_destroy(&multi->dirty); 2877 Curl_uint_bset_destroy(&multi->pending); 2878 Curl_uint_bset_destroy(&multi->msgsent); 2879 Curl_uint_tbl_destroy(&multi->xfers); 2880 free(multi); 2881 2882 return CURLM_OK; 2883 } 2884 return CURLM_BAD_HANDLE; 2885 } 2886 2887 /* 2888 * curl_multi_info_read() 2889 * 2890 * This function is the primary way for a multi/multi_socket application to 2891 * figure out if a transfer has ended. We MUST make this function as fast as 2892 * possible as it will be polled frequently and we MUST NOT scan any lists in 2893 * here to figure out things. We must scale fine to thousands of handles and 2894 * beyond. The current design is fully O(1). 2895 */ 2896 2897 CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue) 2898 { 2899 struct Curl_message *msg; 2900 struct Curl_multi *multi = m; 2901 2902 *msgs_in_queue = 0; /* default to none */ 2903 2904 if(GOOD_MULTI_HANDLE(multi) && 2905 !multi->in_callback && 2906 Curl_llist_count(&multi->msglist)) { 2907 /* there is one or more messages in the list */ 2908 struct Curl_llist_node *e; 2909 2910 /* extract the head of the list to return */ 2911 e = Curl_llist_head(&multi->msglist); 2912 2913 msg = Curl_node_elem(e); 2914 2915 /* remove the extracted entry */ 2916 Curl_node_remove(e); 2917 2918 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist)); 2919 2920 return &msg->extmsg; 2921 } 2922 return NULL; 2923 } 2924 2925 2926 void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s) 2927 { 2928 if(data) { 2929 struct Curl_multi *multi = data->multi; 2930 if(multi) { 2931 CURL_TRC_M(data, "Curl_multi_will_close fd=%" FMT_SOCKET_T, s); 2932 Curl_multi_ev_socket_done(multi, data, s); 2933 } 2934 } 2935 } 2936 2937 /* 2938 * add_next_timeout() 2939 * 2940 * Each Curl_easy has a list of timeouts. The add_next_timeout() is called 2941 * when it has just been removed from the splay tree because the timeout has 2942 * expired. This function is then to advance in the list to pick the next 2943 * timeout to use (skip the already expired ones) and add this node back to 2944 * the splay tree again. 2945 * 2946 * The splay tree only has each sessionhandle as a single node and the nearest 2947 * timeout is used to sort it on. 2948 */ 2949 static CURLMcode add_next_timeout(struct curltime now, 2950 struct Curl_multi *multi, 2951 struct Curl_easy *d) 2952 { 2953 struct curltime *tv = &d->state.expiretime; 2954 struct Curl_llist *list = &d->state.timeoutlist; 2955 struct Curl_llist_node *e; 2956 2957 /* move over the timeout list for this specific handle and remove all 2958 timeouts that are now passed tense and store the next pending 2959 timeout in *tv */ 2960 for(e = Curl_llist_head(list); e;) { 2961 struct Curl_llist_node *n = Curl_node_next(e); 2962 struct time_node *node = Curl_node_elem(e); 2963 timediff_t diff = curlx_timediff_us(node->time, now); 2964 if(diff <= 0) 2965 /* remove outdated entry */ 2966 Curl_node_remove(e); 2967 else 2968 /* the list is sorted so get out on the first mismatch */ 2969 break; 2970 e = n; 2971 } 2972 e = Curl_llist_head(list); 2973 if(!e) { 2974 /* clear the expire times within the handles that we remove from the 2975 splay tree */ 2976 tv->tv_sec = 0; 2977 tv->tv_usec = 0; 2978 } 2979 else { 2980 struct time_node *node = Curl_node_elem(e); 2981 /* copy the first entry to 'tv' */ 2982 memcpy(tv, &node->time, sizeof(*tv)); 2983 2984 /* Insert this node again into the splay. Keep the timer in the list in 2985 case we need to recompute future timers. */ 2986 multi->timetree = Curl_splayinsert(*tv, multi->timetree, 2987 &d->state.timenode); 2988 } 2989 return CURLM_OK; 2990 } 2991 2992 struct multi_run_ctx { 2993 struct Curl_multi *multi; 2994 struct curltime now; 2995 size_t run_xfers; 2996 SIGPIPE_MEMBER(pipe_st); 2997 bool run_cpool; 2998 }; 2999 3000 static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc) 3001 { 3002 struct Curl_multi *multi = mrc->multi; 3003 struct Curl_easy *data = NULL; 3004 struct Curl_tree *t = NULL; 3005 3006 /* 3007 * The loop following here will go on as long as there are expire-times left 3008 * to process (compared to mrc->now) in the splay and 'data' will be 3009 * re-assigned for every expired handle we deal with. 3010 */ 3011 while(1) { 3012 /* Check if there is one (more) expired timer to deal with! This function 3013 extracts a matching node if there is one */ 3014 multi->timetree = Curl_splaygetbest(mrc->now, multi->timetree, &t); 3015 if(!t) 3016 return; 3017 3018 data = Curl_splayget(t); /* assign this for next loop */ 3019 if(!data) 3020 continue; 3021 3022 (void)add_next_timeout(mrc->now, multi, data); 3023 Curl_multi_mark_dirty(data); 3024 } 3025 } 3026 3027 static CURLMcode multi_run_dirty(struct multi_run_ctx *mrc) 3028 { 3029 struct Curl_multi *multi = mrc->multi; 3030 CURLMcode result = CURLM_OK; 3031 unsigned int mid; 3032 3033 if(Curl_uint_bset_first(&multi->dirty, &mid)) { 3034 do { 3035 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 3036 if(data) { 3037 CURL_TRC_M(data, "multi_run_dirty"); 3038 3039 if(data == multi->admin) { 3040 Curl_uint_bset_remove(&multi->dirty, mid); 3041 mrc->run_cpool = TRUE; 3042 continue; 3043 } 3044 else if(!Curl_uint_bset_contains(&multi->process, mid)) { 3045 /* We are no longer processing this transfer */ 3046 Curl_uint_bset_remove(&multi->dirty, mid); 3047 continue; 3048 } 3049 3050 mrc->run_xfers++; 3051 sigpipe_apply(data, &mrc->pipe_st); 3052 /* runsingle() clears the dirty mid */ 3053 result = multi_runsingle(multi, &mrc->now, data); 3054 3055 if(CURLM_OK >= result) { 3056 /* reassess event handling of data */ 3057 result = Curl_multi_ev_assess_xfer(multi, data); 3058 if(result) 3059 goto out; 3060 } 3061 } 3062 else { 3063 CURL_TRC_M(multi->admin, "multi_run_dirty, %u no longer found", mid); 3064 Curl_uint_bset_remove(&multi->dirty, mid); 3065 } 3066 } 3067 while(Curl_uint_bset_next(&multi->dirty, mid, &mid)); 3068 } 3069 3070 out: 3071 return result; 3072 } 3073 3074 static CURLMcode multi_socket(struct Curl_multi *multi, 3075 bool checkall, 3076 curl_socket_t s, 3077 int ev_bitmask, 3078 int *running_handles) 3079 { 3080 CURLMcode result = CURLM_OK; 3081 struct multi_run_ctx mrc; 3082 3083 (void)ev_bitmask; 3084 memset(&mrc, 0, sizeof(mrc)); 3085 mrc.multi = multi; 3086 mrc.now = curlx_now(); 3087 sigpipe_init(&mrc.pipe_st); 3088 3089 if(checkall) { 3090 /* *perform() deals with running_handles on its own */ 3091 result = curl_multi_perform(multi, running_handles); 3092 3093 if(result != CURLM_BAD_HANDLE) { 3094 /* Reassess event status of all active transfers */ 3095 result = Curl_multi_ev_assess_xfer_bset(multi, &multi->process); 3096 } 3097 mrc.run_cpool = TRUE; 3098 goto out; 3099 } 3100 3101 if(s != CURL_SOCKET_TIMEOUT) { 3102 /* Mark all transfers of that socket as dirty */ 3103 Curl_multi_ev_dirty_xfers(multi, s, &mrc.run_cpool); 3104 } 3105 else { 3106 /* Asked to run due to time-out. Clear the 'last_expire_ts' variable to 3107 force Curl_update_timer() to trigger a callback to the app again even 3108 if the same timeout is still the one to run after this call. That 3109 handles the case when the application asks libcurl to run the timeout 3110 prematurely. */ 3111 memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts)); 3112 mrc.run_cpool = TRUE; 3113 } 3114 3115 multi_mark_expired_as_dirty(&mrc); 3116 result = multi_run_dirty(&mrc); 3117 if(result) 3118 goto out; 3119 3120 if(mrc.run_xfers) { 3121 /* Running transfers takes time. With a new timestamp, we might catch 3122 * other expires which are due now. Instead of telling the application 3123 * to set a 0 timeout and call us again, we run them here. 3124 * Do that only once or it might be unfair to transfers on other 3125 * sockets. */ 3126 mrc.now = curlx_now(); 3127 multi_mark_expired_as_dirty(&mrc); 3128 result = multi_run_dirty(&mrc); 3129 } 3130 3131 out: 3132 if(mrc.run_cpool) { 3133 sigpipe_apply(multi->admin, &mrc.pipe_st); 3134 Curl_cshutdn_perform(&multi->cshutdn, multi->admin, s); 3135 } 3136 sigpipe_restore(&mrc.pipe_st); 3137 3138 if(multi_ischanged(multi, TRUE)) 3139 process_pending_handles(multi); 3140 3141 if(running_handles) { 3142 unsigned int running = Curl_multi_xfers_running(multi); 3143 *running_handles = (running < INT_MAX) ? (int)running : INT_MAX; 3144 } 3145 3146 if(CURLM_OK >= result) 3147 result = Curl_update_timer(multi); 3148 return result; 3149 } 3150 3151 #undef curl_multi_setopt 3152 CURLMcode curl_multi_setopt(CURLM *m, 3153 CURLMoption option, ...) 3154 { 3155 CURLMcode res = CURLM_OK; 3156 va_list param; 3157 unsigned long uarg; 3158 struct Curl_multi *multi = m; 3159 3160 if(!GOOD_MULTI_HANDLE(multi)) 3161 return CURLM_BAD_HANDLE; 3162 3163 if(multi->in_callback) 3164 return CURLM_RECURSIVE_API_CALL; 3165 3166 va_start(param, option); 3167 3168 switch(option) { 3169 case CURLMOPT_SOCKETFUNCTION: 3170 multi->socket_cb = va_arg(param, curl_socket_callback); 3171 break; 3172 case CURLMOPT_SOCKETDATA: 3173 multi->socket_userp = va_arg(param, void *); 3174 break; 3175 case CURLMOPT_PUSHFUNCTION: 3176 multi->push_cb = va_arg(param, curl_push_callback); 3177 break; 3178 case CURLMOPT_PUSHDATA: 3179 multi->push_userp = va_arg(param, void *); 3180 break; 3181 case CURLMOPT_PIPELINING: 3182 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0; 3183 break; 3184 case CURLMOPT_TIMERFUNCTION: 3185 multi->timer_cb = va_arg(param, curl_multi_timer_callback); 3186 break; 3187 case CURLMOPT_TIMERDATA: 3188 multi->timer_userp = va_arg(param, void *); 3189 break; 3190 case CURLMOPT_MAXCONNECTS: 3191 uarg = va_arg(param, unsigned long); 3192 if(uarg <= UINT_MAX) 3193 multi->maxconnects = (unsigned int)uarg; 3194 break; 3195 case CURLMOPT_MAX_HOST_CONNECTIONS: 3196 multi->max_host_connections = va_arg(param, long); 3197 break; 3198 case CURLMOPT_MAX_TOTAL_CONNECTIONS: 3199 multi->max_total_connections = va_arg(param, long); 3200 break; 3201 /* options formerly used for pipelining */ 3202 case CURLMOPT_MAX_PIPELINE_LENGTH: 3203 break; 3204 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: 3205 break; 3206 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: 3207 break; 3208 case CURLMOPT_PIPELINING_SITE_BL: 3209 break; 3210 case CURLMOPT_PIPELINING_SERVER_BL: 3211 break; 3212 case CURLMOPT_MAX_CONCURRENT_STREAMS: 3213 { 3214 long streams = va_arg(param, long); 3215 if((streams < 1) || (streams > INT_MAX)) 3216 streams = 100; 3217 multi->max_concurrent_streams = (unsigned int)streams; 3218 } 3219 break; 3220 default: 3221 res = CURLM_UNKNOWN_OPTION; 3222 break; 3223 } 3224 va_end(param); 3225 return res; 3226 } 3227 3228 /* we define curl_multi_socket() in the public multi.h header */ 3229 #undef curl_multi_socket 3230 3231 CURLMcode curl_multi_socket(CURLM *m, curl_socket_t s, int *running_handles) 3232 { 3233 struct Curl_multi *multi = m; 3234 if(multi->in_callback) 3235 return CURLM_RECURSIVE_API_CALL; 3236 return multi_socket(multi, FALSE, s, 0, running_handles); 3237 } 3238 3239 CURLMcode curl_multi_socket_action(CURLM *m, curl_socket_t s, 3240 int ev_bitmask, int *running_handles) 3241 { 3242 struct Curl_multi *multi = m; 3243 if(multi->in_callback) 3244 return CURLM_RECURSIVE_API_CALL; 3245 return multi_socket(multi, FALSE, s, ev_bitmask, running_handles); 3246 } 3247 3248 CURLMcode curl_multi_socket_all(CURLM *m, int *running_handles) 3249 { 3250 struct Curl_multi *multi = m; 3251 if(multi->in_callback) 3252 return CURLM_RECURSIVE_API_CALL; 3253 return multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles); 3254 } 3255 3256 3257 static bool multi_has_dirties(struct Curl_multi *multi) 3258 { 3259 unsigned int mid; 3260 if(Curl_uint_bset_first(&multi->dirty, &mid)) { 3261 do { 3262 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 3263 if(data) { 3264 if(Curl_uint_bset_contains(&multi->process, mid)) 3265 return TRUE; 3266 /* We are no longer processing this transfer */ 3267 Curl_uint_bset_remove(&multi->dirty, mid); 3268 } 3269 else { 3270 CURL_TRC_M(multi->admin, "dirty transfer %u no longer found", mid); 3271 Curl_uint_bset_remove(&multi->dirty, mid); 3272 } 3273 } 3274 while(Curl_uint_bset_next(&multi->dirty, mid, &mid)); 3275 } 3276 return FALSE; 3277 } 3278 3279 static CURLMcode multi_timeout(struct Curl_multi *multi, 3280 struct curltime *expire_time, 3281 long *timeout_ms) 3282 { 3283 static const struct curltime tv_zero = {0, 0}; 3284 3285 if(multi->dead) { 3286 *timeout_ms = 0; 3287 return CURLM_OK; 3288 } 3289 3290 if(multi_has_dirties(multi)) { 3291 *expire_time = curlx_now(); 3292 *timeout_ms = 0; 3293 return CURLM_OK; 3294 } 3295 else if(multi->timetree) { 3296 /* we have a tree of expire times */ 3297 struct curltime now = curlx_now(); 3298 3299 /* splay the lowest to the bottom */ 3300 multi->timetree = Curl_splay(tv_zero, multi->timetree); 3301 /* this will not return NULL from a non-empty tree, but some compilers 3302 * are not convinced of that. Analyzers are hard. */ 3303 *expire_time = multi->timetree ? multi->timetree->key : tv_zero; 3304 3305 /* 'multi->timetree' will be non-NULL here but the compilers sometimes 3306 yell at us if we assume so */ 3307 if(multi->timetree && 3308 curlx_timediff_us(multi->timetree->key, now) > 0) { 3309 /* some time left before expiration */ 3310 timediff_t diff = curlx_timediff_ceil(multi->timetree->key, now); 3311 /* this should be safe even on 32-bit archs, as we do not use that 3312 overly long timeouts */ 3313 *timeout_ms = (long)diff; 3314 } 3315 else { 3316 if(multi->timetree) { 3317 struct Curl_easy *data = Curl_splayget(multi->timetree); 3318 CURL_TRC_M(data, "multi_timeout() says this has expired"); 3319 } 3320 /* 0 means immediately */ 3321 *timeout_ms = 0; 3322 } 3323 } 3324 else { 3325 *expire_time = tv_zero; 3326 *timeout_ms = -1; 3327 } 3328 3329 return CURLM_OK; 3330 } 3331 3332 CURLMcode curl_multi_timeout(CURLM *m, 3333 long *timeout_ms) 3334 { 3335 struct curltime expire_time; 3336 struct Curl_multi *multi = m; 3337 3338 /* First, make some basic checks that the CURLM handle is a good handle */ 3339 if(!GOOD_MULTI_HANDLE(multi)) 3340 return CURLM_BAD_HANDLE; 3341 3342 if(multi->in_callback) 3343 return CURLM_RECURSIVE_API_CALL; 3344 3345 return multi_timeout(multi, &expire_time, timeout_ms); 3346 } 3347 3348 #define DEBUG_UPDATE_TIMER 0 3349 3350 /* 3351 * Tell the application it should update its timers, if it subscribes to the 3352 * update timer callback. 3353 */ 3354 CURLMcode Curl_update_timer(struct Curl_multi *multi) 3355 { 3356 struct curltime expire_ts; 3357 long timeout_ms; 3358 int rc; 3359 bool set_value = FALSE; 3360 3361 if(!multi->timer_cb || multi->dead) 3362 return CURLM_OK; 3363 if(multi_timeout(multi, &expire_ts, &timeout_ms)) { 3364 return CURLM_OK; 3365 } 3366 3367 if(timeout_ms < 0 && multi->last_timeout_ms < 0) { 3368 #if DEBUG_UPDATE_TIMER 3369 fprintf(stderr, "Curl_update_timer(), still no timeout, no change\n"); 3370 #endif 3371 } 3372 else if(timeout_ms < 0) { 3373 /* there is no timeout now but there was one previously */ 3374 #if DEBUG_UPDATE_TIMER 3375 fprintf(stderr, "Curl_update_timer(), remove timeout, " 3376 " last_timeout=%ldms\n", multi->last_timeout_ms); 3377 #endif 3378 timeout_ms = -1; /* normalize */ 3379 set_value = TRUE; 3380 } 3381 else if(multi->last_timeout_ms < 0) { 3382 #if DEBUG_UPDATE_TIMER 3383 fprintf(stderr, "Curl_update_timer(), had no timeout, set now\n"); 3384 #endif 3385 set_value = TRUE; 3386 } 3387 else if(curlx_timediff_us(multi->last_expire_ts, expire_ts)) { 3388 /* We had a timeout before and have one now, the absolute timestamp 3389 * differs. The relative timeout_ms may be the same, but the starting 3390 * point differs. Let the application restart its timer. */ 3391 #if DEBUG_UPDATE_TIMER 3392 fprintf(stderr, "Curl_update_timer(), expire timestamp changed\n"); 3393 #endif 3394 set_value = TRUE; 3395 } 3396 else { 3397 /* We have same expire time as previously. Our relative 'timeout_ms' 3398 * may be different now, but the application has the timer running 3399 * and we do not to tell it to start this again. */ 3400 #if DEBUG_UPDATE_TIMER 3401 fprintf(stderr, "Curl_update_timer(), same expire timestamp, no change\n"); 3402 #endif 3403 } 3404 3405 if(set_value) { 3406 #if DEBUG_UPDATE_TIMER 3407 fprintf(stderr, "Curl_update_timer(), set timeout %ldms\n", timeout_ms); 3408 #endif 3409 multi->last_expire_ts = expire_ts; 3410 multi->last_timeout_ms = timeout_ms; 3411 set_in_callback(multi, TRUE); 3412 rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp); 3413 set_in_callback(multi, FALSE); 3414 if(rc == -1) { 3415 multi->dead = TRUE; 3416 return CURLM_ABORTED_BY_CALLBACK; 3417 } 3418 } 3419 return CURLM_OK; 3420 } 3421 3422 /* 3423 * multi_deltimeout() 3424 * 3425 * Remove a given timestamp from the list of timeouts. 3426 */ 3427 static void 3428 multi_deltimeout(struct Curl_easy *data, expire_id eid) 3429 { 3430 struct Curl_llist_node *e; 3431 struct Curl_llist *timeoutlist = &data->state.timeoutlist; 3432 /* find and remove the specific node from the list */ 3433 for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) { 3434 struct time_node *n = Curl_node_elem(e); 3435 if(n->eid == eid) { 3436 Curl_node_remove(e); 3437 return; 3438 } 3439 } 3440 } 3441 3442 /* 3443 * multi_addtimeout() 3444 * 3445 * Add a timestamp to the list of timeouts. Keep the list sorted so that head 3446 * of list is always the timeout nearest in time. 3447 * 3448 */ 3449 static CURLMcode 3450 multi_addtimeout(struct Curl_easy *data, 3451 struct curltime *stamp, 3452 expire_id eid) 3453 { 3454 struct Curl_llist_node *e; 3455 struct time_node *node; 3456 struct Curl_llist_node *prev = NULL; 3457 size_t n; 3458 struct Curl_llist *timeoutlist = &data->state.timeoutlist; 3459 3460 node = &data->state.expires[eid]; 3461 3462 /* copy the timestamp and id */ 3463 memcpy(&node->time, stamp, sizeof(*stamp)); 3464 node->eid = eid; /* also marks it as in use */ 3465 3466 n = Curl_llist_count(timeoutlist); 3467 if(n) { 3468 /* find the correct spot in the list */ 3469 for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) { 3470 struct time_node *check = Curl_node_elem(e); 3471 timediff_t diff = curlx_timediff(check->time, node->time); 3472 if(diff > 0) 3473 break; 3474 prev = e; 3475 } 3476 3477 } 3478 /* else 3479 this is the first timeout on the list */ 3480 3481 Curl_llist_insert_next(timeoutlist, prev, node, &node->list); 3482 return CURLM_OK; 3483 } 3484 3485 void Curl_expire_ex(struct Curl_easy *data, 3486 const struct curltime *nowp, 3487 timediff_t milli, expire_id id) 3488 { 3489 struct Curl_multi *multi = data->multi; 3490 struct curltime *curr_expire = &data->state.expiretime; 3491 struct curltime set; 3492 3493 /* this is only interesting while there is still an associated multi struct 3494 remaining! */ 3495 if(!multi) 3496 return; 3497 3498 DEBUGASSERT(id < EXPIRE_LAST); 3499 3500 set = *nowp; 3501 set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bits conversion */ 3502 set.tv_usec += (int)(milli%1000)*1000; 3503 3504 if(set.tv_usec >= 1000000) { 3505 set.tv_sec++; 3506 set.tv_usec -= 1000000; 3507 } 3508 3509 /* Remove any timer with the same id just in case. */ 3510 multi_deltimeout(data, id); 3511 3512 /* Add it to the timer list. It must stay in the list until it has expired 3513 in case we need to recompute the minimum timer later. */ 3514 multi_addtimeout(data, &set, id); 3515 3516 if(curr_expire->tv_sec || curr_expire->tv_usec) { 3517 /* This means that the struct is added as a node in the splay tree. 3518 Compare if the new time is earlier, and only remove-old/add-new if it 3519 is. */ 3520 timediff_t diff = curlx_timediff(set, *curr_expire); 3521 int rc; 3522 3523 if(diff > 0) { 3524 /* The current splay tree entry is sooner than this new expiry time. 3525 We do not need to update our splay tree entry. */ 3526 return; 3527 } 3528 3529 /* Since this is an updated time, we must remove the previous entry from 3530 the splay tree first and then re-add the new value */ 3531 rc = Curl_splayremove(multi->timetree, &data->state.timenode, 3532 &multi->timetree); 3533 if(rc) 3534 infof(data, "Internal error removing splay node = %d", rc); 3535 } 3536 3537 /* Indicate that we are in the splay tree and insert the new timer expiry 3538 value since it is our local minimum. */ 3539 *curr_expire = set; 3540 Curl_splayset(&data->state.timenode, data); 3541 multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree, 3542 &data->state.timenode); 3543 if(data->id >= 0) 3544 CURL_TRC_M(data, "set expire[%d] in %" FMT_TIMEDIFF_T "ns", 3545 id, curlx_timediff_us(set, *nowp)); 3546 } 3547 3548 /* 3549 * Curl_expire() 3550 * 3551 * given a number of milliseconds from now to use to set the 'act before 3552 * this'-time for the transfer, to be extracted by curl_multi_timeout() 3553 * 3554 * The timeout will be added to a queue of timeouts if it defines a moment in 3555 * time that is later than the current head of queue. 3556 * 3557 * Expire replaces a former timeout using the same id if already set. 3558 */ 3559 void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id) 3560 { 3561 struct curltime now = curlx_now(); 3562 Curl_expire_ex(data, &now, milli, id); 3563 } 3564 3565 /* 3566 * Curl_expire_done() 3567 * 3568 * Removes the expire timer. Marks it as done. 3569 * 3570 */ 3571 void Curl_expire_done(struct Curl_easy *data, expire_id id) 3572 { 3573 /* remove the timer, if there */ 3574 multi_deltimeout(data, id); 3575 } 3576 3577 /* 3578 * Curl_expire_clear() 3579 * 3580 * Clear ALL timeout values for this handle. 3581 */ 3582 bool Curl_expire_clear(struct Curl_easy *data) 3583 { 3584 struct Curl_multi *multi = data->multi; 3585 struct curltime *nowp = &data->state.expiretime; 3586 3587 /* this is only interesting while there is still an associated multi struct 3588 remaining! */ 3589 if(!multi) 3590 return FALSE; 3591 3592 if(nowp->tv_sec || nowp->tv_usec) { 3593 /* Since this is an cleared time, we must remove the previous entry from 3594 the splay tree */ 3595 struct Curl_llist *list = &data->state.timeoutlist; 3596 int rc; 3597 3598 rc = Curl_splayremove(multi->timetree, &data->state.timenode, 3599 &multi->timetree); 3600 if(rc) 3601 infof(data, "Internal error clearing splay node = %d", rc); 3602 3603 /* clear the timeout list too */ 3604 Curl_llist_destroy(list, NULL); 3605 3606 CURL_TRC_M(data, "Expire cleared"); 3607 nowp->tv_sec = 0; 3608 nowp->tv_usec = 0; 3609 return TRUE; 3610 } 3611 return FALSE; 3612 } 3613 3614 CURLMcode curl_multi_assign(CURLM *m, curl_socket_t s, 3615 void *hashp) 3616 { 3617 struct Curl_multi *multi = m; 3618 if(!GOOD_MULTI_HANDLE(multi)) 3619 return CURLM_BAD_HANDLE; 3620 3621 return Curl_multi_ev_assign(multi, s, hashp); 3622 } 3623 3624 static void move_pending_to_connect(struct Curl_multi *multi, 3625 struct Curl_easy *data) 3626 { 3627 DEBUGASSERT(data->mstate == MSTATE_PENDING); 3628 3629 /* Remove this node from the pending set, add into process set */ 3630 Curl_uint_bset_remove(&multi->pending, data->mid); 3631 Curl_uint_bset_add(&multi->process, data->mid); 3632 3633 multistate(data, MSTATE_CONNECT); 3634 3635 /* Make sure that the handle will be processed soonish. */ 3636 Curl_expire(data, 0, EXPIRE_RUN_NOW); 3637 } 3638 3639 /* process_pending_handles() moves a handle from PENDING back into the process 3640 list and change state to CONNECT. 3641 3642 We do not move all transfers because that can be a significant amount. 3643 Since this is tried every now and then doing too many too often becomes a 3644 performance problem. 3645 3646 When there is a change for connection limits like max host connections etc, 3647 this likely only allows one new transfer. When there is a pipewait change, 3648 it can potentially allow hundreds of new transfers. 3649 3650 We could consider an improvement where we store the queue reason and allow 3651 more pipewait rechecks than others. 3652 */ 3653 static void process_pending_handles(struct Curl_multi *multi) 3654 { 3655 unsigned int mid; 3656 if(Curl_uint_bset_first(&multi->pending, &mid)) { 3657 do { 3658 struct Curl_easy *data = Curl_multi_get_easy(multi, mid); 3659 DEBUGASSERT(data); 3660 if(data) 3661 move_pending_to_connect(multi, data); 3662 } 3663 while(Curl_uint_bset_next(&multi->pending, mid, &mid)); 3664 } 3665 } 3666 3667 void Curl_set_in_callback(struct Curl_easy *data, bool value) 3668 { 3669 if(data && data->multi) 3670 data->multi->in_callback = value; 3671 } 3672 3673 bool Curl_is_in_callback(struct Curl_easy *data) 3674 { 3675 return data && data->multi && data->multi->in_callback; 3676 } 3677 3678 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi) 3679 { 3680 DEBUGASSERT(multi); 3681 return multi->max_concurrent_streams; 3682 } 3683 3684 CURL **curl_multi_get_handles(CURLM *m) 3685 { 3686 struct Curl_multi *multi = m; 3687 void *entry; 3688 unsigned int count = Curl_uint_tbl_count(&multi->xfers); 3689 CURL **a = malloc(sizeof(struct Curl_easy *) * (count + 1)); 3690 if(a) { 3691 unsigned int i = 0, mid; 3692 3693 if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { 3694 do { 3695 struct Curl_easy *data = entry; 3696 DEBUGASSERT(i < count); 3697 if(!data->state.internal) 3698 a[i++] = data; 3699 } 3700 while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)); 3701 } 3702 a[i] = NULL; /* last entry is a NULL */ 3703 } 3704 return a; 3705 } 3706 3707 CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data, 3708 char **pbuf, size_t *pbuflen) 3709 { 3710 DEBUGASSERT(data); 3711 DEBUGASSERT(data->multi); 3712 *pbuf = NULL; 3713 *pbuflen = 0; 3714 if(!data->multi) { 3715 failf(data, "transfer has no multi handle"); 3716 return CURLE_FAILED_INIT; 3717 } 3718 if(!data->set.buffer_size) { 3719 failf(data, "transfer buffer size is 0"); 3720 return CURLE_FAILED_INIT; 3721 } 3722 if(data->multi->xfer_buf_borrowed) { 3723 failf(data, "attempt to borrow xfer_buf when already borrowed"); 3724 return CURLE_AGAIN; 3725 } 3726 3727 if(data->multi->xfer_buf && 3728 data->set.buffer_size > data->multi->xfer_buf_len) { 3729 /* not large enough, get a new one */ 3730 free(data->multi->xfer_buf); 3731 data->multi->xfer_buf = NULL; 3732 data->multi->xfer_buf_len = 0; 3733 } 3734 3735 if(!data->multi->xfer_buf) { 3736 data->multi->xfer_buf = malloc((size_t)data->set.buffer_size); 3737 if(!data->multi->xfer_buf) { 3738 failf(data, "could not allocate xfer_buf of %zu bytes", 3739 (size_t)data->set.buffer_size); 3740 return CURLE_OUT_OF_MEMORY; 3741 } 3742 data->multi->xfer_buf_len = data->set.buffer_size; 3743 } 3744 3745 data->multi->xfer_buf_borrowed = TRUE; 3746 *pbuf = data->multi->xfer_buf; 3747 *pbuflen = data->multi->xfer_buf_len; 3748 return CURLE_OK; 3749 } 3750 3751 void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf) 3752 { 3753 (void)buf; 3754 DEBUGASSERT(data); 3755 DEBUGASSERT(data->multi); 3756 DEBUGASSERT(!buf || data->multi->xfer_buf == buf); 3757 data->multi->xfer_buf_borrowed = FALSE; 3758 } 3759 3760 CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data, 3761 char **pbuf, size_t *pbuflen) 3762 { 3763 DEBUGASSERT(data); 3764 DEBUGASSERT(data->multi); 3765 *pbuf = NULL; 3766 *pbuflen = 0; 3767 if(!data->multi) { 3768 failf(data, "transfer has no multi handle"); 3769 return CURLE_FAILED_INIT; 3770 } 3771 if(!data->set.upload_buffer_size) { 3772 failf(data, "transfer upload buffer size is 0"); 3773 return CURLE_FAILED_INIT; 3774 } 3775 if(data->multi->xfer_ulbuf_borrowed) { 3776 failf(data, "attempt to borrow xfer_ulbuf when already borrowed"); 3777 return CURLE_AGAIN; 3778 } 3779 3780 if(data->multi->xfer_ulbuf && 3781 data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) { 3782 /* not large enough, get a new one */ 3783 free(data->multi->xfer_ulbuf); 3784 data->multi->xfer_ulbuf = NULL; 3785 data->multi->xfer_ulbuf_len = 0; 3786 } 3787 3788 if(!data->multi->xfer_ulbuf) { 3789 data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size); 3790 if(!data->multi->xfer_ulbuf) { 3791 failf(data, "could not allocate xfer_ulbuf of %zu bytes", 3792 (size_t)data->set.upload_buffer_size); 3793 return CURLE_OUT_OF_MEMORY; 3794 } 3795 data->multi->xfer_ulbuf_len = data->set.upload_buffer_size; 3796 } 3797 3798 data->multi->xfer_ulbuf_borrowed = TRUE; 3799 *pbuf = data->multi->xfer_ulbuf; 3800 *pbuflen = data->multi->xfer_ulbuf_len; 3801 return CURLE_OK; 3802 } 3803 3804 void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf) 3805 { 3806 (void)buf; 3807 DEBUGASSERT(data); 3808 DEBUGASSERT(data->multi); 3809 DEBUGASSERT(!buf || data->multi->xfer_ulbuf == buf); 3810 data->multi->xfer_ulbuf_borrowed = FALSE; 3811 } 3812 3813 CURLcode Curl_multi_xfer_sockbuf_borrow(struct Curl_easy *data, 3814 size_t blen, char **pbuf) 3815 { 3816 DEBUGASSERT(data); 3817 DEBUGASSERT(data->multi); 3818 *pbuf = NULL; 3819 if(!data->multi) { 3820 failf(data, "transfer has no multi handle"); 3821 return CURLE_FAILED_INIT; 3822 } 3823 if(data->multi->xfer_sockbuf_borrowed) { 3824 failf(data, "attempt to borrow xfer_sockbuf when already borrowed"); 3825 return CURLE_AGAIN; 3826 } 3827 3828 if(data->multi->xfer_sockbuf && blen > data->multi->xfer_sockbuf_len) { 3829 /* not large enough, get a new one */ 3830 free(data->multi->xfer_sockbuf); 3831 data->multi->xfer_sockbuf = NULL; 3832 data->multi->xfer_sockbuf_len = 0; 3833 } 3834 3835 if(!data->multi->xfer_sockbuf) { 3836 data->multi->xfer_sockbuf = malloc(blen); 3837 if(!data->multi->xfer_sockbuf) { 3838 failf(data, "could not allocate xfer_sockbuf of %zu bytes", blen); 3839 return CURLE_OUT_OF_MEMORY; 3840 } 3841 data->multi->xfer_sockbuf_len = blen; 3842 } 3843 3844 data->multi->xfer_sockbuf_borrowed = TRUE; 3845 *pbuf = data->multi->xfer_sockbuf; 3846 return CURLE_OK; 3847 } 3848 3849 void Curl_multi_xfer_sockbuf_release(struct Curl_easy *data, char *buf) 3850 { 3851 (void)buf; 3852 DEBUGASSERT(data); 3853 DEBUGASSERT(data->multi); 3854 DEBUGASSERT(!buf || data->multi->xfer_sockbuf == buf); 3855 data->multi->xfer_sockbuf_borrowed = FALSE; 3856 } 3857 3858 static void multi_xfer_bufs_free(struct Curl_multi *multi) 3859 { 3860 DEBUGASSERT(multi); 3861 Curl_safefree(multi->xfer_buf); 3862 multi->xfer_buf_len = 0; 3863 multi->xfer_buf_borrowed = FALSE; 3864 Curl_safefree(multi->xfer_ulbuf); 3865 multi->xfer_ulbuf_len = 0; 3866 multi->xfer_ulbuf_borrowed = FALSE; 3867 Curl_safefree(multi->xfer_sockbuf); 3868 multi->xfer_sockbuf_len = 0; 3869 multi->xfer_sockbuf_borrowed = FALSE; 3870 } 3871 3872 struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi, 3873 unsigned int mid) 3874 { 3875 struct Curl_easy *data = mid ? Curl_uint_tbl_get(&multi->xfers, mid) : NULL; 3876 if(data && GOOD_EASY_HANDLE(data)) 3877 return data; 3878 CURL_TRC_M(multi->admin, "invalid easy handle in xfer table for mid=%u", 3879 mid); 3880 Curl_uint_tbl_remove(&multi->xfers, mid); 3881 return NULL; 3882 } 3883 3884 unsigned int Curl_multi_xfers_running(struct Curl_multi *multi) 3885 { 3886 return multi->xfers_alive; 3887 } 3888 3889 void Curl_multi_mark_dirty(struct Curl_easy *data) 3890 { 3891 if(data->multi && data->mid != UINT_MAX) 3892 Curl_uint_bset_add(&data->multi->dirty, data->mid); 3893 } 3894 3895 #ifdef DEBUGBUILD 3896 static void multi_xfer_dump(struct Curl_multi *multi, unsigned int mid, 3897 void *entry) 3898 { 3899 struct Curl_easy *data = entry; 3900 3901 (void)multi; 3902 if(!data) { 3903 fprintf(stderr, "mid=%u, entry=NULL, bug in xfer table?\n", mid); 3904 } 3905 else { 3906 fprintf(stderr, "mid=%u, magic=%s, p=%p, id=%" FMT_OFF_T ", url=%s\n", 3907 mid, (data->magic == CURLEASY_MAGIC_NUMBER) ? "GOOD" : "BAD!", 3908 (void *)data, data->id, data->state.url); 3909 } 3910 } 3911 3912 static void multi_xfer_tbl_dump(struct Curl_multi *multi) 3913 { 3914 unsigned int mid; 3915 void *entry; 3916 fprintf(stderr, "=== multi xfer table (count=%u, capacity=%u\n", 3917 Curl_uint_tbl_count(&multi->xfers), 3918 Curl_uint_tbl_capacity(&multi->xfers)); 3919 if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { 3920 multi_xfer_dump(multi, mid, entry); 3921 while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)) 3922 multi_xfer_dump(multi, mid, entry); 3923 } 3924 fprintf(stderr, "===\n"); 3925 fflush(stderr); 3926 } 3927 #endif /* DEBUGBUILD */