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