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