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_NETINET_IN_H 29#include <netinet/in.h> 30#endif 31#ifdef HAVE_UNISTD_H 32#include <unistd.h> 33#endif 34#ifdef HAVE_NETDB_H 35#include <netdb.h> 36#endif 37#ifdef HAVE_ARPA_INET_H 38#include <arpa/inet.h> 39#endif 40#ifdef HAVE_NET_IF_H 41#include <net/if.h> 42#endif 43#ifdef HAVE_SYS_IOCTL_H 44#include <sys/ioctl.h> 45#endif 46 47#ifdef HAVE_SYS_PARAM_H 48#include <sys/param.h> 49#endif 50 51#include "strequal.h" 52#include "urldata.h" 53#include <curl/curl.h> 54#include "transfer.h" 55#include "sslgen.h" 56#include "url.h" 57#include "getinfo.h" 58#include "hostip.h" 59#include "share.h" 60#include "strdup.h" 61#include "curl_memory.h" 62#include "progress.h" 63#include "easyif.h" 64#include "select.h" 65#include "sendf.h" /* for failf function prototype */ 66#include "curl_ntlm.h" 67#include "connect.h" /* for Curl_getconnectinfo */ 68#include "slist.h" 69#include "curl_rand.h" 70#include "non-ascii.h" 71#include "warnless.h" 72 73#define _MPRINTF_REPLACE /* use our functions only */ 74#include <curl/mprintf.h> 75 76/* The last #include file should be: */ 77#include "memdebug.h" 78 79/* win32_cleanup() is for win32 socket cleanup functionality, the opposite 80 of win32_init() */ 81static void win32_cleanup(void) 82{ 83#ifdef USE_WINSOCK 84 WSACleanup(); 85#endif 86#ifdef USE_WINDOWS_SSPI 87 Curl_sspi_global_cleanup(); 88#endif 89} 90 91/* win32_init() performs win32 socket initialization to properly setup the 92 stack to allow networking */ 93static CURLcode win32_init(void) 94{ 95#ifdef USE_WINSOCK 96 WORD wVersionRequested; 97 WSADATA wsaData; 98 int res; 99 100#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) 101 Error IPV6_requires_winsock2 102#endif 103 104 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); 105 106 res = WSAStartup(wVersionRequested, &wsaData); 107 108 if(res != 0) 109 /* Tell the user that we couldn't find a useable */ 110 /* winsock.dll. */ 111 return CURLE_FAILED_INIT; 112 113 /* Confirm that the Windows Sockets DLL supports what we need.*/ 114 /* Note that if the DLL supports versions greater */ 115 /* than wVersionRequested, it will still return */ 116 /* wVersionRequested in wVersion. wHighVersion contains the */ 117 /* highest supported version. */ 118 119 if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || 120 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { 121 /* Tell the user that we couldn't find a useable */ 122 123 /* winsock.dll. */ 124 WSACleanup(); 125 return CURLE_FAILED_INIT; 126 } 127 /* The Windows Sockets DLL is acceptable. Proceed. */ 128#elif defined(USE_LWIPSOCK) 129 lwip_init(); 130#endif 131 132#ifdef USE_WINDOWS_SSPI 133 { 134 CURLcode err = Curl_sspi_global_init(); 135 if(err != CURLE_OK) 136 return err; 137 } 138#endif 139 140 return CURLE_OK; 141} 142 143#ifdef USE_LIBIDN 144/* 145 * Initialise use of IDNA library. 146 * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for 147 * idna_to_ascii_lz(). 148 */ 149static void idna_init (void) 150{ 151#ifdef WIN32 152 char buf[60]; 153 UINT cp = GetACP(); 154 155 if(!getenv("CHARSET") && cp > 0) { 156 snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp); 157 putenv(buf); 158 } 159#else 160 /* to do? */ 161#endif 162} 163#endif /* USE_LIBIDN */ 164 165/* true globals -- for curl_global_init() and curl_global_cleanup() */ 166static unsigned int initialized; 167static long init_flags; 168 169/* 170 * strdup (and other memory functions) is redefined in complicated 171 * ways, but at this point it must be defined as the system-supplied strdup 172 * so the callback pointer is initialized correctly. 173 */ 174#if defined(_WIN32_WCE) 175#define system_strdup _strdup 176#elif !defined(HAVE_STRDUP) 177#define system_strdup curlx_strdup 178#else 179#define system_strdup strdup 180#endif 181 182#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) 183# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ 184#endif 185 186#ifndef __SYMBIAN32__ 187/* 188 * If a memory-using function (like curl_getenv) is used before 189 * curl_global_init() is called, we need to have these pointers set already. 190 */ 191curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; 192curl_free_callback Curl_cfree = (curl_free_callback)free; 193curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; 194curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; 195curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; 196#else 197/* 198 * Symbian OS doesn't support initialization to code in writeable static data. 199 * Initialization will occur in the curl_global_init() call. 200 */ 201curl_malloc_callback Curl_cmalloc; 202curl_free_callback Curl_cfree; 203curl_realloc_callback Curl_crealloc; 204curl_strdup_callback Curl_cstrdup; 205curl_calloc_callback Curl_ccalloc; 206#endif 207 208#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) 209# pragma warning(default:4232) /* MSVC extension, dllimport identity */ 210#endif 211 212/** 213 * curl_global_init() globally initializes cURL given a bitwise set of the 214 * different features of what to initialize. 215 */ 216CURLcode curl_global_init(long flags) 217{ 218 if(initialized++) 219 return CURLE_OK; 220 221 /* Setup the default memory functions here (again) */ 222 Curl_cmalloc = (curl_malloc_callback)malloc; 223 Curl_cfree = (curl_free_callback)free; 224 Curl_crealloc = (curl_realloc_callback)realloc; 225 Curl_cstrdup = (curl_strdup_callback)system_strdup; 226 Curl_ccalloc = (curl_calloc_callback)calloc; 227 228 if(flags & CURL_GLOBAL_SSL) 229 if(!Curl_ssl_init()) { 230 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); 231 return CURLE_FAILED_INIT; 232 } 233 234 if(flags & CURL_GLOBAL_WIN32) 235 if(win32_init() != CURLE_OK) { 236 DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); 237 return CURLE_FAILED_INIT; 238 } 239 240#ifdef __AMIGA__ 241 if(!amiga_init()) { 242 DEBUGF(fprintf(stderr, "Error: amiga_init failed\n")); 243 return CURLE_FAILED_INIT; 244 } 245#endif 246 247#ifdef NETWARE 248 if(netware_init()) { 249 DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); 250 } 251#endif 252 253#ifdef USE_LIBIDN 254 idna_init(); 255#endif 256 257 if(Curl_resolver_global_init() != CURLE_OK) { 258 DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); 259 return CURLE_FAILED_INIT; 260 } 261 262#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) 263 if(libssh2_init(0)) { 264 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); 265 return CURLE_FAILED_INIT; 266 } 267#endif 268 269 init_flags = flags; 270 271 /* Preset pseudo-random number sequence. */ 272 273 Curl_srand(); 274 275 return CURLE_OK; 276} 277 278/* 279 * curl_global_init_mem() globally initializes cURL and also registers the 280 * user provided callback routines. 281 */ 282CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, 283 curl_free_callback f, curl_realloc_callback r, 284 curl_strdup_callback s, curl_calloc_callback c) 285{ 286 CURLcode code = CURLE_OK; 287 288 /* Invalid input, return immediately */ 289 if(!m || !f || !r || !s || !c) 290 return CURLE_FAILED_INIT; 291 292 /* Already initialized, don't do it again */ 293 if(initialized) 294 return CURLE_OK; 295 296 /* Call the actual init function first */ 297 code = curl_global_init(flags); 298 if(code == CURLE_OK) { 299 Curl_cmalloc = m; 300 Curl_cfree = f; 301 Curl_cstrdup = s; 302 Curl_crealloc = r; 303 Curl_ccalloc = c; 304 } 305 306 return code; 307} 308 309/** 310 * curl_global_cleanup() globally cleanups cURL, uses the value of 311 * "init_flags" to determine what needs to be cleaned up and what doesn't. 312 */ 313void curl_global_cleanup(void) 314{ 315 if(!initialized) 316 return; 317 318 if(--initialized) 319 return; 320 321 Curl_global_host_cache_dtor(); 322 323 if(init_flags & CURL_GLOBAL_SSL) 324 Curl_ssl_cleanup(); 325 326 Curl_resolver_global_cleanup(); 327 328 if(init_flags & CURL_GLOBAL_WIN32) 329 win32_cleanup(); 330 331#ifdef __AMIGA__ 332 amiga_cleanup(); 333#endif 334 335#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) 336 (void)libssh2_exit(); 337#endif 338 339 init_flags = 0; 340} 341 342/* 343 * curl_easy_init() is the external interface to alloc, setup and init an 344 * easy handle that is returned. If anything goes wrong, NULL is returned. 345 */ 346CURL *curl_easy_init(void) 347{ 348 CURLcode res; 349 struct SessionHandle *data; 350 351 /* Make sure we inited the global SSL stuff */ 352 if(!initialized) { 353 res = curl_global_init(CURL_GLOBAL_DEFAULT); 354 if(res) { 355 /* something in the global init failed, return nothing */ 356 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); 357 return NULL; 358 } 359 } 360 361 /* We use curl_open() with undefined URL so far */ 362 res = Curl_open(&data); 363 if(res != CURLE_OK) { 364 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); 365 return NULL; 366 } 367 368 return data; 369} 370 371/* 372 * curl_easy_setopt() is the external interface for setting options on an 373 * easy handle. 374 */ 375 376#undef curl_easy_setopt 377CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...) 378{ 379 va_list arg; 380 struct SessionHandle *data = curl; 381 CURLcode ret; 382 383 if(!curl) 384 return CURLE_BAD_FUNCTION_ARGUMENT; 385 386 va_start(arg, tag); 387 388 ret = Curl_setopt(data, tag, arg); 389 390 va_end(arg); 391 return ret; 392} 393 394#ifdef CURL_MULTIEASY 395/*************************************************************************** 396 * This function is still only for testing purposes. It makes a great way 397 * to run the full test suite on the multi interface instead of the easy one. 398 *************************************************************************** 399 * 400 * The *new* curl_easy_perform() is the external interface that performs a 401 * transfer previously setup. 402 * 403 * Wrapper-function that: creates a multi handle, adds the easy handle to it, 404 * runs curl_multi_perform() until the transfer is done, then detaches the 405 * easy handle, destroys the multi handle and returns the easy handle's return 406 * code. This will make everything internally use and assume multi interface. 407 */ 408CURLcode curl_easy_perform(CURL *easy) 409{ 410 CURLM *multi; 411 CURLMcode mcode; 412 CURLcode code = CURLE_OK; 413 int still_running; 414 struct timeval timeout; 415 int rc; 416 CURLMsg *msg; 417 fd_set fdread; 418 fd_set fdwrite; 419 fd_set fdexcep; 420 int maxfd; 421 422 if(!easy) 423 return CURLE_BAD_FUNCTION_ARGUMENT; 424 425 multi = curl_multi_init(); 426 if(!multi) 427 return CURLE_OUT_OF_MEMORY; 428 429 mcode = curl_multi_add_handle(multi, easy); 430 if(mcode) { 431 curl_multi_cleanup(multi); 432 if(mcode == CURLM_OUT_OF_MEMORY) 433 return CURLE_OUT_OF_MEMORY; 434 else 435 return CURLE_FAILED_INIT; 436 } 437 438 /* we start some action by calling perform right away */ 439 440 do { 441 while(CURLM_CALL_MULTI_PERFORM == 442 curl_multi_perform(multi, &still_running)); 443 444 if(!still_running) 445 break; 446 447 FD_ZERO(&fdread); 448 FD_ZERO(&fdwrite); 449 FD_ZERO(&fdexcep); 450 451 /* timeout once per second */ 452 timeout.tv_sec = 1; 453 timeout.tv_usec = 0; 454 455 /* Old deprecated style: get file descriptors from the transfers */ 456 curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); 457 rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); 458 459 /* The way is to extract the sockets and wait for them without using 460 select. This whole alternative version should probably rather use the 461 curl_multi_socket() approach. */ 462 463 if(rc == -1) 464 /* select error */ 465 break; 466 467 /* timeout or data to send/receive => loop! */ 468 } while(still_running); 469 470 msg = curl_multi_info_read(multi, &rc); 471 if(msg) 472 code = msg->data.result; 473 474 mcode = curl_multi_remove_handle(multi, easy); 475 /* what to do if it fails? */ 476 477 mcode = curl_multi_cleanup(multi); 478 /* what to do if it fails? */ 479 480 return code; 481} 482#else 483/* 484 * curl_easy_perform() is the external interface that performs a transfer 485 * previously setup. 486 */ 487CURLcode curl_easy_perform(CURL *curl) 488{ 489 struct SessionHandle *data = (struct SessionHandle *)curl; 490 491 if(!data) 492 return CURLE_BAD_FUNCTION_ARGUMENT; 493 494 if(! (data->share && data->share->hostcache)) { 495 /* this handle is not using a shared dns cache */ 496 497 if(data->set.global_dns_cache && 498 (data->dns.hostcachetype != HCACHE_GLOBAL)) { 499 /* global dns cache was requested but still isn't */ 500 struct curl_hash *ptr; 501 502 if(data->dns.hostcachetype == HCACHE_PRIVATE) { 503 /* if the current cache is private, kill it first */ 504 Curl_hash_destroy(data->dns.hostcache); 505 data->dns.hostcachetype = HCACHE_NONE; 506 data->dns.hostcache = NULL; 507 } 508 509 ptr = Curl_global_host_cache_init(); 510 if(ptr) { 511 /* only do this if the global cache init works */ 512 data->dns.hostcache = ptr; 513 data->dns.hostcachetype = HCACHE_GLOBAL; 514 } 515 } 516 517 if(!data->dns.hostcache) { 518 data->dns.hostcachetype = HCACHE_PRIVATE; 519 data->dns.hostcache = Curl_mk_dnscache(); 520 521 if(!data->dns.hostcache) 522 /* While we possibly could survive and do good without a host cache, 523 the fact that creating it failed indicates that things are truly 524 screwed up and we should bail out! */ 525 return CURLE_OUT_OF_MEMORY; 526 } 527 528 } 529 530 if(!data->state.connc) { 531 /* oops, no connection cache, make one up */ 532 data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1L); 533 if(!data->state.connc) 534 return CURLE_OUT_OF_MEMORY; 535 } 536 537 return Curl_perform(data); 538} 539#endif 540 541/* 542 * curl_easy_cleanup() is the external interface to cleaning/freeing the given 543 * easy handle. 544 */ 545void curl_easy_cleanup(CURL *curl) 546{ 547 struct SessionHandle *data = (struct SessionHandle *)curl; 548 549 if(!data) 550 return; 551 552 Curl_close(data); 553} 554 555/* 556 * Store a pointed to the multi handle within the easy handle's data struct. 557 */ 558void Curl_easy_addmulti(struct SessionHandle *data, 559 void *multi) 560{ 561 data->multi = multi; 562 if(multi == NULL) 563 /* the association is cleared, mark the easy handle as not used by an 564 interface */ 565 data->state.used_interface = Curl_if_none; 566} 567 568void Curl_easy_initHandleData(struct SessionHandle *data) 569{ 570 memset(&data->req, 0, sizeof(struct SingleRequest)); 571 572 data->req.maxdownload = -1; 573} 574 575/* 576 * curl_easy_getinfo() is an external interface that allows an app to retrieve 577 * information from a performed transfer and similar. 578 */ 579#undef curl_easy_getinfo 580CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) 581{ 582 va_list arg; 583 void *paramp; 584 struct SessionHandle *data = (struct SessionHandle *)curl; 585 586 va_start(arg, info); 587 paramp = va_arg(arg, void *); 588 589 return Curl_getinfo(data, info, paramp); 590} 591 592/* 593 * curl_easy_duphandle() is an external interface to allow duplication of a 594 * given input easy handle. The returned handle will be a new working handle 595 * with all options set exactly as the input source handle. 596 */ 597CURL *curl_easy_duphandle(CURL *incurl) 598{ 599 struct SessionHandle *data=(struct SessionHandle *)incurl; 600 601 struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle)); 602 if(NULL == outcurl) 603 goto fail; 604 605 /* 606 * We setup a few buffers we need. We should probably make them 607 * get setup on-demand in the code, as that would probably decrease 608 * the likeliness of us forgetting to init a buffer here in the future. 609 */ 610 outcurl->state.headerbuff = malloc(HEADERSIZE); 611 if(!outcurl->state.headerbuff) 612 goto fail; 613 outcurl->state.headersize = HEADERSIZE; 614 615 /* copy all userdefined values */ 616 if(Curl_dupset(outcurl, data) != CURLE_OK) 617 goto fail; 618 619 /* the connection cache is setup on demand */ 620 outcurl->state.connc = NULL; 621 622 outcurl->state.lastconnect = -1; 623 624 outcurl->progress.flags = data->progress.flags; 625 outcurl->progress.callback = data->progress.callback; 626 627 if(data->cookies) { 628 /* If cookies are enabled in the parent handle, we enable them 629 in the clone as well! */ 630 outcurl->cookies = Curl_cookie_init(data, 631 data->cookies->filename, 632 outcurl->cookies, 633 data->set.cookiesession); 634 if(!outcurl->cookies) 635 goto fail; 636 } 637 638 /* duplicate all values in 'change' */ 639 if(data->change.cookielist) { 640 outcurl->change.cookielist = 641 Curl_slist_duplicate(data->change.cookielist); 642 if(!outcurl->change.cookielist) 643 goto fail; 644 } 645 646 if(data->change.url) { 647 outcurl->change.url = strdup(data->change.url); 648 if(!outcurl->change.url) 649 goto fail; 650 outcurl->change.url_alloc = TRUE; 651 } 652 653 if(data->change.referer) { 654 outcurl->change.referer = strdup(data->change.referer); 655 if(!outcurl->change.referer) 656 goto fail; 657 outcurl->change.referer_alloc = TRUE; 658 } 659 660 /* Clone the resolver handle, if present, for the new handle */ 661 if(Curl_resolver_duphandle(&outcurl->state.resolver, 662 data->state.resolver) != CURLE_OK) 663 goto fail; 664 665 Curl_convert_setup(outcurl); 666 667 Curl_easy_initHandleData(outcurl); 668 669 outcurl->magic = CURLEASY_MAGIC_NUMBER; 670 671 /* we reach this point and thus we are OK */ 672 673 return outcurl; 674 675 fail: 676 677 if(outcurl) { 678 if(outcurl->state.connc && 679 (outcurl->state.connc->type == CONNCACHE_PRIVATE)) { 680 Curl_rm_connc(outcurl->state.connc); 681 outcurl->state.connc = NULL; 682 } 683 curl_slist_free_all(outcurl->change.cookielist); 684 outcurl->change.cookielist = NULL; 685 Curl_safefree(outcurl->state.headerbuff); 686 Curl_safefree(outcurl->change.url); 687 Curl_safefree(outcurl->change.referer); 688 Curl_freeset(outcurl); 689 free(outcurl); 690 } 691 692 return NULL; 693} 694 695/* 696 * curl_easy_reset() is an external interface that allows an app to re- 697 * initialize a session handle to the default values. 698 */ 699void curl_easy_reset(CURL *curl) 700{ 701 struct SessionHandle *data = (struct SessionHandle *)curl; 702 703 Curl_safefree(data->state.pathbuffer); 704 705 data->state.path = NULL; 706 707 Curl_safefree(data->state.proto.generic); 708 709 /* zero out UserDefined data: */ 710 Curl_freeset(data); 711 memset(&data->set, 0, sizeof(struct UserDefined)); 712 (void)Curl_init_userdefined(&data->set); 713 714 /* zero out Progress data: */ 715 memset(&data->progress, 0, sizeof(struct Progress)); 716 717 /* init Handle data */ 718 Curl_easy_initHandleData(data); 719 720 data->progress.flags |= PGRS_HIDE; 721 data->state.current_speed = -1; /* init to negative == impossible */ 722} 723 724/* 725 * curl_easy_pause() allows an application to pause or unpause a specific 726 * transfer and direction. This function sets the full new state for the 727 * current connection this easy handle operates on. 728 * 729 * NOTE: if you have the receiving paused and you call this function to remove 730 * the pausing, you may get your write callback called at this point. 731 * 732 * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h 733 */ 734CURLcode curl_easy_pause(CURL *curl, int action) 735{ 736 struct SessionHandle *data = (struct SessionHandle *)curl; 737 struct SingleRequest *k = &data->req; 738 CURLcode result = CURLE_OK; 739 740 /* first switch off both pause bits */ 741 int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); 742 743 /* set the new desired pause bits */ 744 newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | 745 ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); 746 747 /* put it back in the keepon */ 748 k->keepon = newstate; 749 750 if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) { 751 /* we have a buffer for sending that we now seem to be able to deliver 752 since the receive pausing is lifted! */ 753 754 /* get the pointer, type and length in local copies since the function may 755 return PAUSE again and then we'll get a new copy allocted and stored in 756 the tempwrite variables */ 757 char *tempwrite = data->state.tempwrite; 758 char *freewrite = tempwrite; /* store this pointer to free it later */ 759 size_t tempsize = data->state.tempwritesize; 760 int temptype = data->state.tempwritetype; 761 size_t chunklen; 762 763 /* clear tempwrite here just to make sure it gets cleared if there's no 764 further use of it, and make sure we don't clear it after the function 765 invoke as it may have been set to a new value by then */ 766 data->state.tempwrite = NULL; 767 768 /* since the write callback API is define to never exceed 769 CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact 770 have more data than that in our buffer here, we must loop sending the 771 data in multiple calls until there's no data left or we get another 772 pause returned. 773 774 A tricky part is that the function we call will "buffer" the data 775 itself when it pauses on a particular buffer, so we may need to do some 776 extra trickery if we get a pause return here. 777 */ 778 do { 779 chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize; 780 781 result = Curl_client_write(data->state.current_conn, 782 temptype, tempwrite, chunklen); 783 if(result) 784 /* failures abort the loop at once */ 785 break; 786 787 if(data->state.tempwrite && (tempsize - chunklen)) { 788 /* Ouch, the reading is again paused and the block we send is now 789 "cached". If this is the final chunk we can leave it like this, but 790 if we have more chunks that are cached after this, we need to free 791 the newly cached one and put back a version that is truly the entire 792 contents that is saved for later 793 */ 794 char *newptr; 795 796 /* note that tempsize is still the size as before the callback was 797 used, and thus the whole piece of data to keep */ 798 newptr = realloc(data->state.tempwrite, tempsize); 799 800 if(!newptr) { 801 free(data->state.tempwrite); /* free old area */ 802 data->state.tempwrite = NULL; 803 result = CURLE_OUT_OF_MEMORY; 804 /* tempwrite will be freed further down */ 805 break; 806 } 807 data->state.tempwrite = newptr; /* store new pointer */ 808 memcpy(newptr, tempwrite, tempsize); 809 data->state.tempwritesize = tempsize; /* store new size */ 810 /* tempwrite will be freed further down */ 811 break; /* go back to pausing until further notice */ 812 } 813 else { 814 tempsize -= chunklen; /* left after the call above */ 815 tempwrite += chunklen; /* advance the pointer */ 816 } 817 818 } while((result == CURLE_OK) && tempsize); 819 820 free(freewrite); /* this is unconditionally no longer used */ 821 } 822 823 return result; 824} 825 826 827static CURLcode easy_connection(struct SessionHandle *data, 828 curl_socket_t *sfd, 829 struct connectdata **connp) 830{ 831 if(data == NULL) 832 return CURLE_BAD_FUNCTION_ARGUMENT; 833 834 /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ 835 if(!data->set.connect_only) { 836 failf(data, "CONNECT_ONLY is required!"); 837 return CURLE_UNSUPPORTED_PROTOCOL; 838 } 839 840 *sfd = Curl_getconnectinfo(data, connp); 841 842 if(*sfd == CURL_SOCKET_BAD) { 843 failf(data, "Failed to get recent socket"); 844 return CURLE_UNSUPPORTED_PROTOCOL; 845 } 846 847 return CURLE_OK; 848} 849 850/* 851 * Receives data from the connected socket. Use after successful 852 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 853 * Returns CURLE_OK on success, error code on error. 854 */ 855CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n) 856{ 857 curl_socket_t sfd; 858 CURLcode ret; 859 ssize_t n1; 860 struct connectdata *c; 861 struct SessionHandle *data = (struct SessionHandle *)curl; 862 863 ret = easy_connection(data, &sfd, &c); 864 if(ret) 865 return ret; 866 867 *n = 0; 868 ret = Curl_read(c, sfd, buffer, buflen, &n1); 869 870 if(ret != CURLE_OK) 871 return ret; 872 873 *n = (size_t)n1; 874 875 return CURLE_OK; 876} 877 878/* 879 * Sends data over the connected socket. Use after successful 880 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. 881 */ 882CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, 883 size_t *n) 884{ 885 curl_socket_t sfd; 886 CURLcode ret; 887 ssize_t n1; 888 struct connectdata *c = NULL; 889 struct SessionHandle *data = (struct SessionHandle *)curl; 890 891 ret = easy_connection(data, &sfd, &c); 892 if(ret) 893 return ret; 894 895 *n = 0; 896 ret = Curl_write(c, sfd, buffer, buflen, &n1); 897 898 if(n1 == -1) 899 return CURLE_SEND_ERROR; 900 901 /* detect EAGAIN */ 902 if((CURLE_OK == ret) && (0 == n1)) 903 return CURLE_AGAIN; 904 905 *n = (size_t)n1; 906 907 return ret; 908} 909