1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 /* 26 * See comment in curl_memory.h for the explanation of this sanity check. 27 */ 28 29 #ifdef CURLX_NO_MEMORY_CALLBACKS 30 #error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" 31 #endif 32 33 #ifdef HAVE_NETINET_IN_H 34 #include <netinet/in.h> 35 #endif 36 #ifdef HAVE_NETDB_H 37 #include <netdb.h> 38 #endif 39 #ifdef HAVE_ARPA_INET_H 40 #include <arpa/inet.h> 41 #endif 42 #ifdef HAVE_NET_IF_H 43 #include <net/if.h> 44 #endif 45 #ifdef HAVE_SYS_IOCTL_H 46 #include <sys/ioctl.h> 47 #endif 48 49 #ifdef HAVE_SYS_PARAM_H 50 #include <sys/param.h> 51 #endif 52 53 #include "urldata.h" 54 #include <curl/curl.h> 55 #include "transfer.h" 56 #include "vtls/vtls.h" 57 #include "url.h" 58 #include "getinfo.h" 59 #include "hostip.h" 60 #include "share.h" 61 #include "strdup.h" 62 #include "progress.h" 63 #include "easyif.h" 64 #include "multiif.h" 65 #include "select.h" 66 #include "sendf.h" /* for failf function prototype */ 67 #include "connect.h" /* for Curl_getconnectinfo */ 68 #include "slist.h" 69 #include "mime.h" 70 #include "amigaos.h" 71 #include "non-ascii.h" 72 #include "warnless.h" 73 #include "multiif.h" 74 #include "sigpipe.h" 75 #include "ssh.h" 76 #include "setopt.h" 77 #include "http_digest.h" 78 #include "system_win32.h" 79 80 /* The last 3 #include files should be in this order */ 81 #include "curl_printf.h" 82 #include "curl_memory.h" 83 #include "memdebug.h" 84 85 void Curl_version_init(void); 86 87 /* true globals -- for curl_global_init() and curl_global_cleanup() */ 88 static unsigned int initialized; 89 static long init_flags; 90 91 /* 92 * strdup (and other memory functions) is redefined in complicated 93 * ways, but at this point it must be defined as the system-supplied strdup 94 * so the callback pointer is initialized correctly. 95 */ 96 #if defined(_WIN32_WCE) 97 #define system_strdup _strdup 98 #elif !defined(HAVE_STRDUP) 99 #define system_strdup curlx_strdup 100 #else 101 #define system_strdup strdup 102 #endif 103 104 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) 105 # pragma warning(disable:4232) /* MSVC extension, dllimport identity */ 106 #endif 107 108 #ifndef __SYMBIAN32__ 109 /* 110 * If a memory-using function (like curl_getenv) is used before 111 * curl_global_init() is called, we need to have these pointers set already. 112 */ 113 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; 114 curl_free_callback Curl_cfree = (curl_free_callback)free; 115 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; 116 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; 117 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; 118 #if defined(WIN32) && defined(UNICODE) 119 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; 120 #endif 121 #else 122 /* 123 * Symbian OS doesn't support initialization to code in writable static data. 124 * Initialization will occur in the curl_global_init() call. 125 */ 126 curl_malloc_callback Curl_cmalloc; 127 curl_free_callback Curl_cfree; 128 curl_realloc_callback Curl_crealloc; 129 curl_strdup_callback Curl_cstrdup; 130 curl_calloc_callback Curl_ccalloc; 131 #endif 132 133 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) 134 # pragma warning(default:4232) /* MSVC extension, dllimport identity */ 135 #endif 136 137 /** 138 * curl_global_init() globally initializes curl given a bitwise set of the 139 * different features of what to initialize. 140 */ 141 static CURLcode global_init(long flags, bool memoryfuncs) 142 { 143 if(initialized++) 144 return CURLE_OK; 145 146 if(memoryfuncs) { 147 /* Setup the default memory functions here (again) */ 148 Curl_cmalloc = (curl_malloc_callback)malloc; 149 Curl_cfree = (curl_free_callback)free; 150 Curl_crealloc = (curl_realloc_callback)realloc; 151 Curl_cstrdup = (curl_strdup_callback)system_strdup; 152 Curl_ccalloc = (curl_calloc_callback)calloc; 153 #if defined(WIN32) && defined(UNICODE) 154 Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; 155 #endif 156 } 157 158 if(!Curl_ssl_init()) { 159 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); 160 return CURLE_FAILED_INIT; 161 } 162 163 #ifdef WIN32 164 if(Curl_win32_init(flags)) { 165 DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); 166 return CURLE_FAILED_INIT; 167 } 168 #endif 169 170 #ifdef __AMIGA__ 171 if(!Curl_amiga_init()) { 172 DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); 173 return CURLE_FAILED_INIT; 174 } 175 #endif 176 177 #ifdef NETWARE 178 if(netware_init()) { 179 DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); 180 } 181 #endif 182 183 if(Curl_resolver_global_init()) { 184 DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); 185 return CURLE_FAILED_INIT; 186 } 187 188 (void)Curl_ipv6works(); 189 190 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) 191 if(libssh2_init(0)) { 192 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); 193 return CURLE_FAILED_INIT; 194 } 195 #endif 196 197 #if defined(USE_LIBSSH) 198 if(ssh_init()) { 199 DEBUGF(fprintf(stderr, "Error: libssh_init failed\n")); 200 return CURLE_FAILED_INIT; 201 } 202 #endif 203 204 if(flags & CURL_GLOBAL_ACK_EINTR) 205 Curl_ack_eintr = 1; 206 207 init_flags = flags; 208 209 Curl_version_init(); 210 211 return CURLE_OK; 212 } 213 214 215 /** 216 * curl_global_init() globally initializes curl given a bitwise set of the 217 * different features of what to initialize. 218 */ 219 CURLcode curl_global_init(long flags) 220 { 221 return global_init(flags, TRUE); 222 } 223 224 /* 225 * curl_global_init_mem() globally initializes curl and also registers the 226 * user provided callback routines. 227 */ 228 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, 229 curl_free_callback f, curl_realloc_callback r, 230 curl_strdup_callback s, curl_calloc_callback c) 231 { 232 /* Invalid input, return immediately */ 233 if(!m || !f || !r || !s || !c) 234 return CURLE_FAILED_INIT; 235 236 if(initialized) { 237 /* Already initialized, don't do it again, but bump the variable anyway to 238 work like curl_global_init() and require the same amount of cleanup 239 calls. */ 240 initialized++; 241 return CURLE_OK; 242 } 243 244 /* set memory functions before global_init() in case it wants memory 245 functions */ 246 Curl_cmalloc = m; 247 Curl_cfree = f; 248 Curl_cstrdup = s; 249 Curl_crealloc = r; 250 Curl_ccalloc = c; 251 252 /* Call the actual init function, but without setting */ 253 return global_init(flags, FALSE); 254 } 255 256 /** 257 * curl_global_cleanup() globally cleanups curl, uses the value of 258 * "init_flags" to determine what needs to be cleaned up and what doesn't. 259 */ 260 void curl_global_cleanup(void) 261 { 262 if(!initialized) 263 return; 264 265 if(--initialized) 266 return; 267 268 Curl_global_host_cache_dtor(); 269 Curl_ssl_cleanup(); 270 Curl_resolver_global_cleanup(); 271 272 #ifdef WIN32 273 Curl_win32_cleanup(init_flags); 274 #endif 275 276 Curl_amiga_cleanup(); 277 278 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) 279 (void)libssh2_exit(); 280 #endif 281 282 #if defined(USE_LIBSSH) 283 (void)ssh_finalize(); 284 #endif 285 286 init_flags = 0; 287 } 288 289 /* 290 * curl_easy_init() is the external interface to alloc, setup and init an 291 * easy handle that is returned. If anything goes wrong, NULL is returned. 292 */ 293 struct Curl_easy *curl_easy_init(void) 294 { 295 CURLcode result; 296 struct Curl_easy *data; 297 298 /* Make sure we inited the global SSL stuff */ 299 if(!initialized) { 300 result = curl_global_init(CURL_GLOBAL_DEFAULT); 301 if(result) { 302 /* something in the global init failed, return nothing */ 303 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); 304 return NULL; 305 } 306 } 307 308 /* We use curl_open() with undefined URL so far */ 309 result = Curl_open(&data); 310 if(result) { 311 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); 312 return NULL; 313 } 314 315 return data; 316 } 317 318 #ifdef CURLDEBUG 319 320 struct socketmonitor { 321 struct socketmonitor *next; /* the next node in the list or NULL */ 322 struct pollfd socket; /* socket info of what to monitor */ 323 }; 324 325 struct events { 326 long ms; /* timeout, run the timeout function when reached */ 327 bool msbump; /* set TRUE when timeout is set by callback */ 328 int num_sockets; /* number of nodes in the monitor list */ 329 struct socketmonitor *list; /* list of sockets to monitor */ 330 int running_handles; /* store the returned number */ 331 }; 332 333 /* events_timer 334 * 335 * Callback that gets called with a new value when the timeout should be 336 * updated. 337 */ 338 339 static int events_timer(struct Curl_multi *multi, /* multi handle */ 340 long timeout_ms, /* see above */ 341 void *userp) /* private callback pointer */ 342 { 343 struct events *ev = userp; 344 (void)multi; 345 if(timeout_ms == -1) 346 /* timeout removed */ 347 timeout_ms = 0; 348 else if(timeout_ms == 0) 349 /* timeout is already reached! */ 350 timeout_ms = 1; /* trigger asap */ 351 352 ev->ms = timeout_ms; 353 ev->msbump = TRUE; 354 return 0; 355 } 356 357 358 /* poll2cselect 359 * 360 * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones 361 */ 362 static int poll2cselect(int pollmask) 363 { 364 int omask = 0; 365 if(pollmask & POLLIN) 366 omask |= CURL_CSELECT_IN; 367 if(pollmask & POLLOUT) 368 omask |= CURL_CSELECT_OUT; 369 if(pollmask & POLLERR) 370 omask |= CURL_CSELECT_ERR; 371 return omask; 372 } 373 374 375 /* socketcb2poll 376 * 377 * convert from libcurl' CURL_POLL_* bit definitions to poll()'s 378 */ 379 static short socketcb2poll(int pollmask) 380 { 381 short omask = 0; 382 if(pollmask & CURL_POLL_IN) 383 omask |= POLLIN; 384 if(pollmask & CURL_POLL_OUT) 385 omask |= POLLOUT; 386 return omask; 387 } 388 389 /* events_socket 390 * 391 * Callback that gets called with information about socket activity to 392 * monitor. 393 */ 394 static int events_socket(struct Curl_easy *easy, /* easy handle */ 395 curl_socket_t s, /* socket */ 396 int what, /* see above */ 397 void *userp, /* private callback 398 pointer */ 399 void *socketp) /* private socket 400 pointer */ 401 { 402 struct events *ev = userp; 403 struct socketmonitor *m; 404 struct socketmonitor *prev = NULL; 405 406 #if defined(CURL_DISABLE_VERBOSE_STRINGS) 407 (void) easy; 408 #endif 409 (void)socketp; 410 411 m = ev->list; 412 while(m) { 413 if(m->socket.fd == s) { 414 415 if(what == CURL_POLL_REMOVE) { 416 struct socketmonitor *nxt = m->next; 417 /* remove this node from the list of monitored sockets */ 418 if(prev) 419 prev->next = nxt; 420 else 421 ev->list = nxt; 422 free(m); 423 m = nxt; 424 infof(easy, "socket cb: socket %d REMOVED\n", s); 425 } 426 else { 427 /* The socket 's' is already being monitored, update the activity 428 mask. Convert from libcurl bitmask to the poll one. */ 429 m->socket.events = socketcb2poll(what); 430 infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, 431 what&CURL_POLL_IN?"IN":"", 432 what&CURL_POLL_OUT?"OUT":""); 433 } 434 break; 435 } 436 prev = m; 437 m = m->next; /* move to next node */ 438 } 439 if(!m) { 440 if(what == CURL_POLL_REMOVE) { 441 /* this happens a bit too often, libcurl fix perhaps? */ 442 /* fprintf(stderr, 443 "%s: socket %d asked to be REMOVED but not present!\n", 444 __func__, s); */ 445 } 446 else { 447 m = malloc(sizeof(struct socketmonitor)); 448 if(m) { 449 m->next = ev->list; 450 m->socket.fd = s; 451 m->socket.events = socketcb2poll(what); 452 m->socket.revents = 0; 453 ev->list = m; 454 infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, 455 what&CURL_POLL_IN?"IN":"", 456 what&CURL_POLL_OUT?"OUT":""); 457 } 458 else 459 return CURLE_OUT_OF_MEMORY; 460 } 461 } 462 463 return 0; 464 } 465 466 467 /* 468 * events_setup() 469 * 470 * Do the multi handle setups that only event-based transfers need. 471 */ 472 static void events_setup(struct Curl_multi *multi, struct events *ev) 473 { 474 /* timer callback */ 475 curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); 476 curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); 477 478 /* socket callback */ 479 curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); 480 curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); 481 } 482 483 484 /* wait_or_timeout() 485 * 486 * waits for activity on any of the given sockets, or the timeout to trigger. 487 */ 488 489 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) 490 { 491 bool done = FALSE; 492 CURLMcode mcode = CURLM_OK; 493 CURLcode result = CURLE_OK; 494 495 while(!done) { 496 CURLMsg *msg; 497 struct socketmonitor *m; 498 struct pollfd *f; 499 struct pollfd fds[4]; 500 int numfds = 0; 501 int pollrc; 502 int i; 503 struct curltime before; 504 struct curltime after; 505 506 /* populate the fds[] array */ 507 for(m = ev->list, f = &fds[0]; m; m = m->next) { 508 f->fd = m->socket.fd; 509 f->events = m->socket.events; 510 f->revents = 0; 511 /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ 512 f++; 513 numfds++; 514 } 515 516 /* get the time stamp to use to figure out how long poll takes */ 517 before = Curl_now(); 518 519 /* wait for activity or timeout */ 520 pollrc = Curl_poll(fds, numfds, (int)ev->ms); 521 522 after = Curl_now(); 523 524 ev->msbump = FALSE; /* reset here */ 525 526 if(0 == pollrc) { 527 /* timeout! */ 528 ev->ms = 0; 529 /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ 530 mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, 531 &ev->running_handles); 532 } 533 else if(pollrc > 0) { 534 /* loop over the monitored sockets to see which ones had activity */ 535 for(i = 0; i< numfds; i++) { 536 if(fds[i].revents) { 537 /* socket activity, tell libcurl */ 538 int act = poll2cselect(fds[i].revents); /* convert */ 539 infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", 540 fds[i].fd); 541 mcode = curl_multi_socket_action(multi, fds[i].fd, act, 542 &ev->running_handles); 543 } 544 } 545 546 if(!ev->msbump) { 547 /* If nothing updated the timeout, we decrease it by the spent time. 548 * If it was updated, it has the new timeout time stored already. 549 */ 550 timediff_t timediff = Curl_timediff(after, before); 551 if(timediff > 0) { 552 if(timediff > ev->ms) 553 ev->ms = 0; 554 else 555 ev->ms -= (long)timediff; 556 } 557 } 558 } 559 else 560 return CURLE_RECV_ERROR; 561 562 if(mcode) 563 return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */ 564 565 /* we don't really care about the "msgs_in_queue" value returned in the 566 second argument */ 567 msg = curl_multi_info_read(multi, &pollrc); 568 if(msg) { 569 result = msg->data.result; 570 done = TRUE; 571 } 572 } 573 574 return result; 575 } 576 577 578 /* easy_events() 579 * 580 * Runs a transfer in a blocking manner using the events-based API 581 */ 582 static CURLcode easy_events(struct Curl_multi *multi) 583 { 584 /* this struct is made static to allow it to be used after this function 585 returns and curl_multi_remove_handle() is called */ 586 static struct events evs = {2, FALSE, 0, NULL, 0}; 587 588 /* if running event-based, do some further multi inits */ 589 events_setup(multi, &evs); 590 591 return wait_or_timeout(multi, &evs); 592 } 593 #else /* CURLDEBUG */ 594 /* when not built with debug, this function doesn't exist */ 595 #define easy_events(x) CURLE_NOT_BUILT_IN 596 #endif 597 598 static CURLcode easy_transfer(struct Curl_multi *multi) 599 { 600 bool done = FALSE; 601 CURLMcode mcode = CURLM_OK; 602 CURLcode result = CURLE_OK; 603 604 while(!done && !mcode) { 605 int still_running = 0; 606 bool gotsocket = FALSE; 607 608 mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket); 609 610 if(!mcode) { 611 if(!gotsocket) { 612 long sleep_ms; 613 614 /* If it returns without any filedescriptor instantly, we need to 615 avoid busy-looping during periods where it has nothing particular 616 to wait for */ 617 curl_multi_timeout(multi, &sleep_ms); 618 if(sleep_ms) { 619 if(sleep_ms > 1000) 620 sleep_ms = 1000; 621 Curl_wait_ms((int)sleep_ms); 622 } 623 } 624 625 mcode = curl_multi_perform(multi, &still_running); 626 } 627 628 /* only read 'still_running' if curl_multi_perform() return OK */ 629 if(!mcode && !still_running) { 630 int rc; 631 CURLMsg *msg = curl_multi_info_read(multi, &rc); 632 if(msg) { 633 result = msg->data.result; 634 done = TRUE; 635 } 636 } 637 } 638 639 /* Make sure to return some kind of error if there was a multi problem */ 640 if(mcode) { 641 result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : 642 /* The other multi errors should never happen, so return 643 something suitably generic */ 644 CURLE_BAD_FUNCTION_ARGUMENT; 645 } 646 647 return result; 648 } 649 650 651 /* 652 * easy_perform() is the external interface that performs a blocking 653 * transfer as previously setup. 654 * 655 * CONCEPT: This function creates a multi handle, adds the easy handle to it, 656 * runs curl_multi_perform() until the transfer is done, then detaches the 657 * easy handle, destroys the multi handle and returns the easy handle's return 658 * code. 659 * 660 * REALITY: it can't just create and destroy the multi handle that easily. It 661 * needs to keep it around since if this easy handle is used again by this 662 * function, the same multi handle must be re-used so that the same pools and 663 * caches can be used. 664 * 665 * DEBUG: if 'events' is set TRUE, this function will use a replacement engine 666 * instead of curl_multi_perform() and use curl_multi_socket_action(). 667 */ 668 static CURLcode easy_perform(struct Curl_easy *data, bool events) 669 { 670 struct Curl_multi *multi; 671 CURLMcode mcode; 672 CURLcode result = CURLE_OK; 673 SIGPIPE_VARIABLE(pipe_st); 674 675 if(!data) 676 return CURLE_BAD_FUNCTION_ARGUMENT; 677 678 if(data->set.errorbuffer) 679 /* clear this as early as possible */ 680 data->set.errorbuffer[0] = 0; 681 682 if(data->multi) { 683 failf(data, "easy handle already used in multi handle"); 684 return CURLE_FAILED_INIT; 685 } 686 687 if(data->multi_easy) 688 multi = data->multi_easy; 689 else { 690 /* this multi handle will only ever have a single easy handled attached 691 to it, so make it use minimal hashes */ 692 multi = Curl_multi_handle(1, 3); 693 if(!multi) 694 return CURLE_OUT_OF_MEMORY; 695 data->multi_easy = multi; 696 } 697 698 if(multi->in_callback) 699 return CURLE_RECURSIVE_API_CALL; 700 701 /* Copy the MAXCONNECTS option to the multi handle */ 702 curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); 703 704 mcode = curl_multi_add_handle(multi, data); 705 if(mcode) { 706 curl_multi_cleanup(multi); 707 if(mcode == CURLM_OUT_OF_MEMORY) 708 return CURLE_OUT_OF_MEMORY; 709 return CURLE_FAILED_INIT; 710 } 711 712 sigpipe_ignore(data, &pipe_st); 713 714 /* assign this after curl_multi_add_handle() since that function checks for 715 it and rejects this handle otherwise */ 716 data->multi = multi; 717 718 /* run the transfer */ 719 result = events ? easy_events(multi) : easy_transfer(multi); 720 721 /* ignoring the return code isn't nice, but atm we can't really handle 722 a failure here, room for future improvement! */ 723 (void)curl_multi_remove_handle(multi, data); 724 725 sigpipe_restore(&pipe_st); 726 727 /* The multi handle is kept alive, owned by the easy handle */ 728 return result; 729 } 730 731 732 /* 733 * curl_easy_perform() is the external interface that performs a blocking 734 * transfer as previously setup. 735 */ 736 CURLcode curl_easy_perform(struct Curl_easy *data) 737 { 738 return easy_perform(data, FALSE); 739 } 740 741 #ifdef CURLDEBUG 742 /* 743 * curl_easy_perform_ev() is the external interface that performs a blocking 744 * transfer using the event-based API internally. 745 */ 746 CURLcode curl_easy_perform_ev(struct Curl_easy *data) 747 { 748 return easy_perform(data, TRUE); 749 } 750 751 #endif 752 753 /* 754 * curl_easy_cleanup() is the external interface to cleaning/freeing the given 755 * easy handle. 756 */ 757 void curl_easy_cleanup(struct Curl_easy *data) 758 { 759 SIGPIPE_VARIABLE(pipe_st); 760 761 if(!data) 762 return; 763 764 sigpipe_ignore(data, &pipe_st); 765 Curl_close(data); 766 sigpipe_restore(&pipe_st); 767 } 768 769 /* 770 * curl_easy_getinfo() is an external interface that allows an app to retrieve 771 * information from a performed transfer and similar. 772 */ 773 #undef curl_easy_getinfo 774 CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...) 775 { 776 va_list arg; 777 void *paramp; 778 CURLcode result; 779 780 va_start(arg, info); 781 paramp = va_arg(arg, void *); 782 783 result = Curl_getinfo(data, info, paramp); 784 785 va_end(arg); 786 return result; 787 } 788 789 static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) 790 { 791 CURLcode result = CURLE_OK; 792 enum dupstring i; 793 794 /* Copy src->set into dst->set first, then deal with the strings 795 afterwards */ 796 dst->set = src->set; 797 Curl_mime_initpart(&dst->set.mimepost, dst); 798 799 /* clear all string pointers first */ 800 memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); 801 802 /* duplicate all strings */ 803 for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { 804 result = Curl_setstropt(&dst->set.str[i], src->set.str[i]); 805 if(result) 806 return result; 807 } 808 809 /* duplicate memory areas pointed to */ 810 i = STRING_COPYPOSTFIELDS; 811 if(src->set.postfieldsize && src->set.str[i]) { 812 /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ 813 dst->set.str[i] = Curl_memdup(src->set.str[i], 814 curlx_sotouz(src->set.postfieldsize)); 815 if(!dst->set.str[i]) 816 return CURLE_OUT_OF_MEMORY; 817 /* point to the new copy */ 818 dst->set.postfields = dst->set.str[i]; 819 } 820 821 /* Duplicate mime data. */ 822 result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost); 823 824 if(src->set.resolve) 825 dst->change.resolve = dst->set.resolve; 826 827 return result; 828 } 829 830 /* 831 * curl_easy_duphandle() is an external interface to allow duplication of a 832 * given input easy handle. The returned handle will be a new working handle 833 * with all options set exactly as the input source handle. 834 */ 835 struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) 836 { 837 struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); 838 if(NULL == outcurl) 839 goto fail; 840 841 /* 842 * We setup a few buffers we need. We should probably make them 843 * get setup on-demand in the code, as that would probably decrease 844 * the likeliness of us forgetting to init a buffer here in the future. 845 */ 846 outcurl->set.buffer_size = data->set.buffer_size; 847 outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1); 848 if(!outcurl->state.buffer) 849 goto fail; 850 851 outcurl->state.headerbuff = malloc(HEADERSIZE); 852 if(!outcurl->state.headerbuff) 853 goto fail; 854 outcurl->state.headersize = HEADERSIZE; 855 856 /* copy all userdefined values */ 857 if(dupset(outcurl, data)) 858 goto fail; 859 860 /* the connection cache is setup on demand */ 861 outcurl->state.conn_cache = NULL; 862 863 outcurl->state.lastconnect = NULL; 864 865 outcurl->progress.flags = data->progress.flags; 866 outcurl->progress.callback = data->progress.callback; 867 868 if(data->cookies) { 869 /* If cookies are enabled in the parent handle, we enable them 870 in the clone as well! */ 871 outcurl->cookies = Curl_cookie_init(data, 872 data->cookies->filename, 873 outcurl->cookies, 874 data->set.cookiesession); 875 if(!outcurl->cookies) 876 goto fail; 877 } 878 879 /* duplicate all values in 'change' */ 880 if(data->change.cookielist) { 881 outcurl->change.cookielist = 882 Curl_slist_duplicate(data->change.cookielist); 883 if(!outcurl->change.cookielist) 884 goto fail; 885 } 886 887 if(data->change.url) { 888 outcurl->change.url = strdup(data->change.url); 889 if(!outcurl->change.url) 890 goto fail; 891 outcurl->change.url_alloc = TRUE; 892 } 893 894 if(data->change.referer) { 895 outcurl->change.referer = strdup(data->change.referer); 896 if(!outcurl->change.referer) 897 goto fail; 898 outcurl->change.referer_alloc = TRUE; 899 } 900 901 /* Reinitialize an SSL engine for the new handle 902 * note: the engine name has already been copied by dupset */ 903 if(outcurl->set.str[STRING_SSL_ENGINE]) { 904 if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE])) 905 goto fail; 906 } 907 908 /* Clone the resolver handle, if present, for the new handle */ 909 if(Curl_resolver_duphandle(outcurl, 910 &outcurl->state.resolver, 911 data->state.resolver)) 912 goto fail; 913 914 Curl_convert_setup(outcurl); 915 916 Curl_initinfo(outcurl); 917 918 outcurl->magic = CURLEASY_MAGIC_NUMBER; 919 920 /* we reach this point and thus we are OK */ 921 922 return outcurl; 923 924 fail: 925 926 if(outcurl) { 927 curl_slist_free_all(outcurl->change.cookielist); 928 outcurl->change.cookielist = NULL; 929 Curl_safefree(outcurl->state.buffer); 930 Curl_safefree(outcurl->state.headerbuff); 931 Curl_safefree(outcurl->change.url); 932 Curl_safefree(outcurl->change.referer); 933 Curl_freeset(outcurl); 934 free(outcurl); 935 } 936 937 return NULL; 938 } 939 940 /* 941 * curl_easy_reset() is an external interface that allows an app to re- 942 * initialize a session handle to the default values. 943 */ 944 void curl_easy_reset(struct Curl_easy *data) 945 { 946 Curl_free_request_state(data); 947 948 /* zero out UserDefined data: */ 949 Curl_freeset(data); 950 memset(&data->set, 0, sizeof(struct UserDefined)); 951 (void)Curl_init_userdefined(data); 952 953 /* zero out Progress data: */ 954 memset(&data->progress, 0, sizeof(struct Progress)); 955 956 /* zero out PureInfo data: */ 957 Curl_initinfo(data); 958 959 data->progress.flags |= PGRS_HIDE; 960 data->state.current_speed = -1; /* init to negative == impossible */ 961 962 /* zero out authentication data: */ 963 memset(&data->state.authhost, 0, sizeof(struct auth)); 964 memset(&data->state.authproxy, 0, sizeof(struct auth)); 965 Curl_digest_cleanup(data); 966 } 967 968 /* 969 * curl_easy_pause() allows an application to pause or unpause a specific 970 * transfer and direction. This function sets the full new state for the 971 * current connection this easy handle operates on. 972 * 973 * NOTE: if you have the receiving paused and you call this function to remove 974 * the pausing, you may get your write callback called at this point. 975 * 976 * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h 977 * 978 * NOTE: This is one of few API functions that are allowed to be called from 979 * within a callback. 980 */ 981 CURLcode curl_easy_pause(struct Curl_easy *data, int action) 982 { 983 struct SingleRequest *k = &data->req; 984 CURLcode result = CURLE_OK; 985 986 /* first switch off both pause bits */ 987 int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); 988 989 /* set the new desired pause bits */ 990 newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | 991 ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); 992 993 /* put it back in the keepon */ 994 k->keepon = newstate; 995 996 if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { 997 /* there are buffers for sending that can be delivered as the receive 998 pausing is lifted! */ 999 unsigned int i; 1000 unsigned int count = data->state.tempcount; 1001 struct tempbuf writebuf[3]; /* there can only be three */ 1002 struct connectdata *conn = data->conn; 1003 struct Curl_easy *saved_data = NULL; 1004 1005 /* copy the structs to allow for immediate re-pausing */ 1006 for(i = 0; i < data->state.tempcount; i++) { 1007 writebuf[i] = data->state.tempwrite[i]; 1008 data->state.tempwrite[i].buf = NULL; 1009 } 1010 data->state.tempcount = 0; 1011 1012 /* set the connection's current owner */ 1013 if(conn->data != data) { 1014 saved_data = conn->data; 1015 conn->data = data; 1016 } 1017 1018 for(i = 0; i < count; i++) { 1019 /* even if one function returns error, this loops through and frees all 1020 buffers */ 1021 if(!result) 1022 result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, 1023 writebuf[i].len); 1024 free(writebuf[i].buf); 1025 } 1026 1027 /* recover previous owner of the connection */ 1028 if(saved_data) 1029 conn->data = saved_data; 1030 1031 if(result) 1032 return result; 1033 } 1034 1035 /* if there's no error and we're not pausing both directions, we want 1036 to have this handle checked soon */ 1037 if(!result && 1038 ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != 1039 (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) 1040 Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ 1041 1042 /* This transfer may have been moved in or out of the bundle, update 1043 the corresponding socket callback, if used */ 1044 Curl_updatesocket(data); 1045 1046 return result; 1047 } 1048 1049 1050 static CURLcode easy_connection(struct Curl_easy *data, 1051 curl_socket_t *sfd, 1052 struct connectdata **connp) 1053 { 1054 if(data == NULL) 1055 return CURLE_BAD_FUNCTION_ARGUMENT; 1056 1057 /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ 1058 if(!data->set.connect_only) { 1059 failf(data, "CONNECT_ONLY is required!"); 1060 return CURLE_UNSUPPORTED_PROTOCOL; 1061 } 1062 1063 *sfd = Curl_getconnectinfo(data, connp); 1064 1065 if(*sfd == CURL_SOCKET_BAD) { 1066 failf(data, "Failed to get recent socket"); 1067 return CURLE_UNSUPPORTED_PROTOCOL; 1068 } 1069 1070 return CURLE_OK; 1071 } 1072 1073 /* 1074 * Receives data from the connected socket. Use after successful 1075 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 1076 * Returns CURLE_OK on success, error code on error. 1077 */ 1078 CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, 1079 size_t *n) 1080 { 1081 curl_socket_t sfd; 1082 CURLcode result; 1083 ssize_t n1; 1084 struct connectdata *c; 1085 1086 if(Curl_is_in_callback(data)) 1087 return CURLE_RECURSIVE_API_CALL; 1088 1089 result = easy_connection(data, &sfd, &c); 1090 if(result) 1091 return result; 1092 1093 *n = 0; 1094 result = Curl_read(c, sfd, buffer, buflen, &n1); 1095 1096 if(result) 1097 return result; 1098 1099 *n = (size_t)n1; 1100 1101 return CURLE_OK; 1102 } 1103 1104 /* 1105 * Sends data over the connected socket. Use after successful 1106 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 1107 */ 1108 CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, 1109 size_t buflen, size_t *n) 1110 { 1111 curl_socket_t sfd; 1112 CURLcode result; 1113 ssize_t n1; 1114 struct connectdata *c = NULL; 1115 1116 if(Curl_is_in_callback(data)) 1117 return CURLE_RECURSIVE_API_CALL; 1118 1119 result = easy_connection(data, &sfd, &c); 1120 if(result) 1121 return result; 1122 1123 *n = 0; 1124 result = Curl_write(c, sfd, buffer, buflen, &n1); 1125 1126 if(n1 == -1) 1127 return CURLE_SEND_ERROR; 1128 1129 /* detect EAGAIN */ 1130 if(!result && !n1) 1131 return CURLE_AGAIN; 1132 1133 *n = (size_t)n1; 1134 1135 return result; 1136 } 1137 1138 /* 1139 * Performs connection upkeep for the given session handle. 1140 */ 1141 CURLcode curl_easy_upkeep(struct Curl_easy *data) 1142 { 1143 /* Verify that we got an easy handle we can work with. */ 1144 if(!GOOD_EASY_HANDLE(data)) 1145 return CURLE_BAD_FUNCTION_ARGUMENT; 1146 1147 if(data->multi_easy) { 1148 /* Use the common function to keep connections alive. */ 1149 return Curl_upkeep(&data->multi_easy->conn_cache, data); 1150 } 1151 else { 1152 /* No connections, so just return success */ 1153 return CURLE_OK; 1154 } 1155 } 1156