1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25#include "curl_setup.h" 26 27#ifdef HAVE_NETINET_IN_H 28#include <netinet/in.h> 29#endif 30 31#ifdef HAVE_LINUX_TCP_H 32#include <linux/tcp.h> 33#elif defined(HAVE_NETINET_TCP_H) 34#include <netinet/tcp.h> 35#endif 36 37#include <curl/curl.h> 38 39#include "urldata.h" 40#include "sendf.h" 41#include "cfilters.h" 42#include "connect.h" 43#include "content_encoding.h" 44#include "vtls/vtls.h" 45#include "vssh/ssh.h" 46#include "easyif.h" 47#include "multiif.h" 48#include "strerror.h" 49#include "select.h" 50#include "strdup.h" 51#include "http2.h" 52#include "headers.h" 53#include "progress.h" 54#include "ws.h" 55 56/* The last 3 #include files should be in this order */ 57#include "curl_printf.h" 58#include "curl_memory.h" 59#include "memdebug.h" 60 61 62static CURLcode do_init_stack(struct Curl_easy *data); 63 64#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP) 65/* 66 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF 67 * (\n), with special processing for CRLF sequences that are split between two 68 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new 69 * size of the data is returned. 70 */ 71static size_t convert_lineends(struct Curl_easy *data, 72 char *startPtr, size_t size) 73{ 74 char *inPtr, *outPtr; 75 76 /* sanity check */ 77 if(!startPtr || (size < 1)) { 78 return size; 79 } 80 81 if(data->state.prev_block_had_trailing_cr) { 82 /* The previous block of incoming data 83 had a trailing CR, which was turned into a LF. */ 84 if(*startPtr == '\n') { 85 /* This block of incoming data starts with the 86 previous block's LF so get rid of it */ 87 memmove(startPtr, startPtr + 1, size-1); 88 size--; 89 /* and it wasn't a bare CR but a CRLF conversion instead */ 90 data->state.crlf_conversions++; 91 } 92 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ 93 } 94 95 /* find 1st CR, if any */ 96 inPtr = outPtr = memchr(startPtr, '\r', size); 97 if(inPtr) { 98 /* at least one CR, now look for CRLF */ 99 while(inPtr < (startPtr + size-1)) { 100 /* note that it's size-1, so we'll never look past the last byte */ 101 if(memcmp(inPtr, "\r\n", 2) == 0) { 102 /* CRLF found, bump past the CR and copy the NL */ 103 inPtr++; 104 *outPtr = *inPtr; 105 /* keep track of how many CRLFs we converted */ 106 data->state.crlf_conversions++; 107 } 108 else { 109 if(*inPtr == '\r') { 110 /* lone CR, move LF instead */ 111 *outPtr = '\n'; 112 } 113 else { 114 /* not a CRLF nor a CR, just copy whatever it is */ 115 *outPtr = *inPtr; 116 } 117 } 118 outPtr++; 119 inPtr++; 120 } /* end of while loop */ 121 122 if(inPtr < startPtr + size) { 123 /* handle last byte */ 124 if(*inPtr == '\r') { 125 /* deal with a CR at the end of the buffer */ 126 *outPtr = '\n'; /* copy a NL instead */ 127 /* note that a CRLF might be split across two blocks */ 128 data->state.prev_block_had_trailing_cr = TRUE; 129 } 130 else { 131 /* copy last byte */ 132 *outPtr = *inPtr; 133 } 134 outPtr++; 135 } 136 if(outPtr < startPtr + size) 137 /* tidy up by null terminating the now shorter data */ 138 *outPtr = '\0'; 139 140 return (outPtr - startPtr); 141 } 142 return size; 143} 144#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */ 145 146/* 147 * Curl_nwrite() is an internal write function that sends data to the 148 * server. Works with a socket index for the connection. 149 * 150 * If the write would block (CURLE_AGAIN), it returns CURLE_OK and 151 * (*nwritten == 0). Otherwise we return regular CURLcode value. 152 */ 153CURLcode Curl_nwrite(struct Curl_easy *data, 154 int sockindex, 155 const void *buf, 156 size_t blen, 157 ssize_t *pnwritten) 158{ 159 ssize_t nwritten; 160 CURLcode result = CURLE_OK; 161 struct connectdata *conn; 162 163 DEBUGASSERT(sockindex >= 0 && sockindex < 2); 164 DEBUGASSERT(pnwritten); 165 DEBUGASSERT(data); 166 DEBUGASSERT(data->conn); 167 conn = data->conn; 168#ifdef CURLDEBUG 169 { 170 /* Allow debug builds to override this logic to force short sends 171 */ 172 char *p = getenv("CURL_SMALLSENDS"); 173 if(p) { 174 size_t altsize = (size_t)strtoul(p, NULL, 10); 175 if(altsize) 176 blen = CURLMIN(blen, altsize); 177 } 178 } 179#endif 180 nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result); 181 if(result == CURLE_AGAIN) { 182 nwritten = 0; 183 result = CURLE_OK; 184 } 185 else if(result) { 186 nwritten = -1; /* make sure */ 187 } 188 else { 189 DEBUGASSERT(nwritten >= 0); 190 } 191 192 *pnwritten = nwritten; 193 return result; 194} 195 196/* 197 * Curl_write() is an internal write function that sends data to the 198 * server. Works with plain sockets, SCP, SSL or kerberos. 199 * 200 * If the write would block (CURLE_AGAIN), we return CURLE_OK and 201 * (*written == 0). Otherwise we return regular CURLcode value. 202 */ 203CURLcode Curl_write(struct Curl_easy *data, 204 curl_socket_t sockfd, 205 const void *mem, 206 size_t len, 207 ssize_t *written) 208{ 209 struct connectdata *conn; 210 int num; 211 212 DEBUGASSERT(data); 213 DEBUGASSERT(data->conn); 214 conn = data->conn; 215 num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]); 216 return Curl_nwrite(data, num, mem, len, written); 217} 218 219static CURLcode pausewrite(struct Curl_easy *data, 220 int type, /* what type of data */ 221 bool paused_body, 222 const char *ptr, 223 size_t len) 224{ 225 /* signalled to pause sending on this connection, but since we have data 226 we want to send we need to dup it to save a copy for when the sending 227 is again enabled */ 228 struct SingleRequest *k = &data->req; 229 struct UrlState *s = &data->state; 230 unsigned int i; 231 bool newtype = TRUE; 232 233 Curl_conn_ev_data_pause(data, TRUE); 234 235 if(s->tempcount) { 236 for(i = 0; i< s->tempcount; i++) { 237 if(s->tempwrite[i].type == type && 238 !!s->tempwrite[i].paused_body == !!paused_body) { 239 /* data for this type exists */ 240 newtype = FALSE; 241 break; 242 } 243 } 244 DEBUGASSERT(i < 3); 245 if(i >= 3) 246 /* There are more types to store than what fits: very bad */ 247 return CURLE_OUT_OF_MEMORY; 248 } 249 else 250 i = 0; 251 252 if(newtype) { 253 /* store this information in the state struct for later use */ 254 Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER); 255 s->tempwrite[i].type = type; 256 s->tempwrite[i].paused_body = paused_body; 257 s->tempcount++; 258 } 259 260 if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len)) 261 return CURLE_OUT_OF_MEMORY; 262 263 /* mark the connection as RECV paused */ 264 k->keepon |= KEEP_RECV_PAUSE; 265 266 return CURLE_OK; 267} 268 269 270/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via 271 * client write callback(s) and takes care of pause requests from the 272 * callbacks. 273 */ 274static CURLcode chop_write(struct Curl_easy *data, 275 int type, 276 bool skip_body_write, 277 char *optr, 278 size_t olen) 279{ 280 struct connectdata *conn = data->conn; 281 curl_write_callback writeheader = NULL; 282 curl_write_callback writebody = NULL; 283 char *ptr = optr; 284 size_t len = olen; 285 void *writebody_ptr = data->set.out; 286 287 if(!len) 288 return CURLE_OK; 289 290 /* If reading is paused, append this data to the already held data for this 291 type. */ 292 if(data->req.keepon & KEEP_RECV_PAUSE) 293 return pausewrite(data, type, !skip_body_write, ptr, len); 294 295 /* Determine the callback(s) to use. */ 296 if(!skip_body_write && 297 ((type & CLIENTWRITE_BODY) || 298 ((type & CLIENTWRITE_HEADER) && data->set.include_header))) { 299 writebody = data->set.fwrite_func; 300 } 301 if((type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) && 302 (data->set.fwrite_header || data->set.writeheader)) { 303 /* 304 * Write headers to the same callback or to the especially setup 305 * header callback function (added after version 7.7.1). 306 */ 307 writeheader = 308 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; 309 } 310 311 /* Chop data, write chunks. */ 312 while(len) { 313 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; 314 315 if(writebody) { 316 size_t wrote; 317 Curl_set_in_callback(data, true); 318 wrote = writebody(ptr, 1, chunklen, writebody_ptr); 319 Curl_set_in_callback(data, false); 320 321 if(CURL_WRITEFUNC_PAUSE == wrote) { 322 if(conn->handler->flags & PROTOPT_NONETWORK) { 323 /* Protocols that work without network cannot be paused. This is 324 actually only FILE:// just now, and it can't pause since the 325 transfer isn't done using the "normal" procedure. */ 326 failf(data, "Write callback asked for PAUSE when not supported"); 327 return CURLE_WRITE_ERROR; 328 } 329 return pausewrite(data, type, TRUE, ptr, len); 330 } 331 if(wrote != chunklen) { 332 failf(data, "Failure writing output to destination"); 333 return CURLE_WRITE_ERROR; 334 } 335 } 336 337 ptr += chunklen; 338 len -= chunklen; 339 } 340 341#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API) 342 /* HTTP header, but not status-line */ 343 if((conn->handler->protocol & PROTO_FAMILY_HTTP) && 344 (type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) { 345 unsigned char htype = (unsigned char) 346 (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT : 347 (type & CLIENTWRITE_1XX ? CURLH_1XX : 348 (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER : 349 CURLH_HEADER))); 350 CURLcode result = Curl_headers_push(data, optr, htype); 351 if(result) 352 return result; 353 } 354#endif 355 356 if(writeheader) { 357 size_t wrote; 358 359 Curl_set_in_callback(data, true); 360 wrote = writeheader(optr, 1, olen, data->set.writeheader); 361 Curl_set_in_callback(data, false); 362 363 if(CURL_WRITEFUNC_PAUSE == wrote) 364 return pausewrite(data, type, FALSE, optr, olen); 365 if(wrote != olen) { 366 failf(data, "Failed writing header"); 367 return CURLE_WRITE_ERROR; 368 } 369 } 370 371 return CURLE_OK; 372} 373 374 375/* Curl_client_write() sends data to the write callback(s) 376 377 The bit pattern defines to what "streams" to write to. Body and/or header. 378 The defines are in sendf.h of course. 379 380 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the 381 local character encoding. This is a problem and should be changed in 382 the future to leave the original data alone. 383 */ 384CURLcode Curl_client_write(struct Curl_easy *data, 385 int type, char *buf, size_t blen) 386{ 387 CURLcode result; 388 389#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV) 390 /* FTP data may need conversion. */ 391 if((type & CLIENTWRITE_BODY) && 392 (data->conn->handler->protocol & PROTO_FAMILY_FTP) && 393 data->conn->proto.ftpc.transfertype == 'A') { 394 /* convert end-of-line markers */ 395 blen = convert_lineends(data, buf, blen); 396 } 397#endif 398 /* it is one of those, at least */ 399 DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO)); 400 /* BODY is only BODY (with optional EOS) */ 401 DEBUGASSERT(!(type & CLIENTWRITE_BODY) || 402 ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0)); 403 /* INFO is only INFO (with optional EOS) */ 404 DEBUGASSERT(!(type & CLIENTWRITE_INFO) || 405 ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0)); 406 407 if(!data->req.writer_stack) { 408 result = do_init_stack(data); 409 if(result) 410 return result; 411 DEBUGASSERT(data->req.writer_stack); 412 } 413 414 return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen); 415} 416 417CURLcode Curl_client_unpause(struct Curl_easy *data) 418{ 419 CURLcode result = CURLE_OK; 420 421 if(data->state.tempcount) { 422 /* there are buffers for sending that can be delivered as the receive 423 pausing is lifted! */ 424 unsigned int i; 425 unsigned int count = data->state.tempcount; 426 struct tempbuf writebuf[3]; /* there can only be three */ 427 428 /* copy the structs to allow for immediate re-pausing */ 429 for(i = 0; i < data->state.tempcount; i++) { 430 writebuf[i] = data->state.tempwrite[i]; 431 Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER); 432 } 433 data->state.tempcount = 0; 434 435 for(i = 0; i < count; i++) { 436 /* even if one function returns error, this loops through and frees 437 all buffers */ 438 if(!result) 439 result = chop_write(data, writebuf[i].type, 440 !writebuf[i].paused_body, 441 Curl_dyn_ptr(&writebuf[i].b), 442 Curl_dyn_len(&writebuf[i].b)); 443 Curl_dyn_free(&writebuf[i].b); 444 } 445 } 446 return result; 447} 448 449void Curl_client_cleanup(struct Curl_easy *data) 450{ 451 struct Curl_cwriter *writer = data->req.writer_stack; 452 size_t i; 453 454 while(writer) { 455 data->req.writer_stack = writer->next; 456 writer->cwt->do_close(data, writer); 457 free(writer); 458 writer = data->req.writer_stack; 459 } 460 461 for(i = 0; i < data->state.tempcount; i++) { 462 Curl_dyn_free(&data->state.tempwrite[i].b); 463 } 464 data->state.tempcount = 0; 465 data->req.bytecount = 0; 466 data->req.headerline = 0; 467} 468 469/* Write data using an unencoding writer stack. "nbytes" is not 470 allowed to be 0. */ 471CURLcode Curl_cwriter_write(struct Curl_easy *data, 472 struct Curl_cwriter *writer, int type, 473 const char *buf, size_t nbytes) 474{ 475 if(!writer) 476 return CURLE_WRITE_ERROR; 477 return writer->cwt->do_write(data, writer, type, buf, nbytes); 478} 479 480CURLcode Curl_cwriter_def_init(struct Curl_easy *data, 481 struct Curl_cwriter *writer) 482{ 483 (void)data; 484 (void)writer; 485 return CURLE_OK; 486} 487 488CURLcode Curl_cwriter_def_write(struct Curl_easy *data, 489 struct Curl_cwriter *writer, int type, 490 const char *buf, size_t nbytes) 491{ 492 return Curl_cwriter_write(data, writer->next, type, buf, nbytes); 493} 494 495void Curl_cwriter_def_close(struct Curl_easy *data, 496 struct Curl_cwriter *writer) 497{ 498 (void) data; 499 (void) writer; 500} 501 502/* Real client writer to installed callbacks. */ 503static CURLcode cw_client_write(struct Curl_easy *data, 504 struct Curl_cwriter *writer, int type, 505 const char *buf, size_t nbytes) 506{ 507 (void)writer; 508 if(!nbytes) 509 return CURLE_OK; 510 return chop_write(data, type, FALSE, (char *)buf, nbytes); 511} 512 513static const struct Curl_cwtype cw_client = { 514 "client", 515 NULL, 516 Curl_cwriter_def_init, 517 cw_client_write, 518 Curl_cwriter_def_close, 519 sizeof(struct Curl_cwriter) 520}; 521 522static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit) 523{ 524 if(limit != -1) { 525 /* How much more are we allowed to write? */ 526 curl_off_t remain_diff; 527 remain_diff = limit - data->req.bytecount; 528 if(remain_diff < 0) { 529 /* already written too much! */ 530 return 0; 531 } 532#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T 533 else if(remain_diff > SSIZE_T_MAX) { 534 return SIZE_T_MAX; 535 } 536#endif 537 else { 538 return (size_t)remain_diff; 539 } 540 } 541 return SIZE_T_MAX; 542} 543 544/* Download client writer in phase CURL_CW_PROTOCOL that 545 * sees the "real" download body data. */ 546static CURLcode cw_download_write(struct Curl_easy *data, 547 struct Curl_cwriter *writer, int type, 548 const char *buf, size_t nbytes) 549{ 550 CURLcode result; 551 size_t nwrite, excess_len = 0; 552 553 if(!(type & CLIENTWRITE_BODY)) { 554 if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers) 555 return CURLE_OK; 556 return Curl_cwriter_write(data, writer->next, type, buf, nbytes); 557 } 558 559 if(!data->req.bytecount) { 560 Curl_pgrsTime(data, TIMER_STARTTRANSFER); 561 if(data->req.exp100 > EXP100_SEND_DATA) 562 /* set time stamp to compare with when waiting for the 100 */ 563 data->req.start100 = Curl_now(); 564 } 565 566 /* Here, we deal with REAL BODY bytes. All filtering and transfer 567 * encodings have been applied and only the true content, e.g. BODY, 568 * bytes are passed here. 569 * This allows us to check sizes, update stats, etc. independent 570 * from the protocol in play. */ 571 572 if(data->req.no_body && nbytes > 0) { 573 /* BODY arrives although we want none, bail out */ 574 streamclose(data->conn, "ignoring body"); 575 DEBUGF(infof(data, "did not want a BODY, but seeing %zu bytes", 576 nbytes)); 577 data->req.download_done = TRUE; 578 return CURLE_WEIRD_SERVER_REPLY; 579 } 580 581 /* Determine if we see any bytes in excess to what is allowed. 582 * We write the allowed bytes and handle excess further below. 583 * This gives deterministic BODY writes on varying buffer receive 584 * lengths. */ 585 nwrite = nbytes; 586 if(-1 != data->req.maxdownload) { 587 size_t wmax = get_max_body_write_len(data, data->req.maxdownload); 588 if(nwrite > wmax) { 589 excess_len = nbytes - wmax; 590 nwrite = wmax; 591 } 592 593 if(nwrite == wmax) { 594 data->req.download_done = TRUE; 595 } 596 } 597 598 /* Error on too large filesize is handled below, after writing 599 * the permitted bytes */ 600 if(data->set.max_filesize) { 601 size_t wmax = get_max_body_write_len(data, data->set.max_filesize); 602 if(nwrite > wmax) { 603 nwrite = wmax; 604 } 605 } 606 607 /* Update stats, write and report progress */ 608 data->req.bytecount += nwrite; 609 ++data->req.bodywrites; 610 if(!data->req.ignorebody && nwrite) { 611 result = Curl_cwriter_write(data, writer->next, type, buf, nwrite); 612 if(result) 613 return result; 614 } 615 result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); 616 if(result) 617 return result; 618 619 if(excess_len) { 620 if(!data->req.ignorebody) { 621 infof(data, 622 "Excess found writing body:" 623 " excess = %zu" 624 ", size = %" CURL_FORMAT_CURL_OFF_T 625 ", maxdownload = %" CURL_FORMAT_CURL_OFF_T 626 ", bytecount = %" CURL_FORMAT_CURL_OFF_T, 627 excess_len, data->req.size, data->req.maxdownload, 628 data->req.bytecount); 629 connclose(data->conn, "excess found in a read"); 630 } 631 } 632 else if(nwrite < nbytes) { 633 failf(data, "Exceeded the maximum allowed file size " 634 "(%" CURL_FORMAT_CURL_OFF_T ") with %" 635 CURL_FORMAT_CURL_OFF_T " bytes", 636 data->set.max_filesize, data->req.bytecount); 637 return CURLE_FILESIZE_EXCEEDED; 638 } 639 640 return CURLE_OK; 641} 642 643static const struct Curl_cwtype cw_download = { 644 "download", 645 NULL, 646 Curl_cwriter_def_init, 647 cw_download_write, 648 Curl_cwriter_def_close, 649 sizeof(struct Curl_cwriter) 650}; 651 652/* RAW client writer in phase CURL_CW_RAW that 653 * enabled tracing of raw data. */ 654static CURLcode cw_raw_write(struct Curl_easy *data, 655 struct Curl_cwriter *writer, int type, 656 const char *buf, size_t nbytes) 657{ 658 if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) { 659 Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes); 660 } 661 return Curl_cwriter_write(data, writer->next, type, buf, nbytes); 662} 663 664static const struct Curl_cwtype cw_raw = { 665 "raw", 666 NULL, 667 Curl_cwriter_def_init, 668 cw_raw_write, 669 Curl_cwriter_def_close, 670 sizeof(struct Curl_cwriter) 671}; 672 673/* Create an unencoding writer stage using the given handler. */ 674CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, 675 struct Curl_easy *data, 676 const struct Curl_cwtype *cwt, 677 Curl_cwriter_phase phase) 678{ 679 struct Curl_cwriter *writer; 680 CURLcode result = CURLE_OUT_OF_MEMORY; 681 682 DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter)); 683 writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size); 684 if(!writer) 685 goto out; 686 687 writer->cwt = cwt; 688 writer->phase = phase; 689 result = cwt->do_init(data, writer); 690 691out: 692 *pwriter = result? NULL : writer; 693 if(result) 694 free(writer); 695 return result; 696} 697 698void Curl_cwriter_free(struct Curl_easy *data, 699 struct Curl_cwriter *writer) 700{ 701 if(writer) { 702 writer->cwt->do_close(data, writer); 703 free(writer); 704 } 705} 706 707size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase) 708{ 709 struct Curl_cwriter *w; 710 size_t n = 0; 711 712 for(w = data->req.writer_stack; w; w = w->next) { 713 if(w->phase == phase) 714 ++n; 715 } 716 return n; 717} 718 719static CURLcode do_init_stack(struct Curl_easy *data) 720{ 721 struct Curl_cwriter *writer; 722 CURLcode result; 723 724 DEBUGASSERT(!data->req.writer_stack); 725 result = Curl_cwriter_create(&data->req.writer_stack, 726 data, &cw_client, CURL_CW_CLIENT); 727 if(result) 728 return result; 729 730 result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL); 731 if(result) 732 return result; 733 result = Curl_cwriter_add(data, writer); 734 if(result) { 735 Curl_cwriter_free(data, writer); 736 } 737 738 result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW); 739 if(result) 740 return result; 741 result = Curl_cwriter_add(data, writer); 742 if(result) { 743 Curl_cwriter_free(data, writer); 744 } 745 return result; 746} 747 748CURLcode Curl_cwriter_add(struct Curl_easy *data, 749 struct Curl_cwriter *writer) 750{ 751 CURLcode result; 752 struct Curl_cwriter **anchor = &data->req.writer_stack; 753 754 if(!*anchor) { 755 result = do_init_stack(data); 756 if(result) 757 return result; 758 } 759 760 /* Insert the writer as first in its phase. 761 * Skip existing writers of lower phases. */ 762 while(*anchor && (*anchor)->phase < writer->phase) 763 anchor = &((*anchor)->next); 764 writer->next = *anchor; 765 *anchor = writer; 766 return CURLE_OK; 767} 768 769void Curl_cwriter_remove_by_name(struct Curl_easy *data, 770 const char *name) 771{ 772 struct Curl_cwriter **anchor = &data->req.writer_stack; 773 774 while(*anchor) { 775 if(!strcmp(name, (*anchor)->cwt->name)) { 776 struct Curl_cwriter *w = (*anchor); 777 *anchor = w->next; 778 Curl_cwriter_free(data, w); 779 continue; 780 } 781 anchor = &((*anchor)->next); 782 } 783} 784 785/* 786 * Internal read-from-socket function. This is meant to deal with plain 787 * sockets, SSL sockets and kerberos sockets. 788 * 789 * Returns a regular CURLcode value. 790 */ 791CURLcode Curl_read(struct Curl_easy *data, /* transfer */ 792 curl_socket_t sockfd, /* read from this socket */ 793 char *buf, /* store read data here */ 794 size_t sizerequested, /* max amount to read */ 795 ssize_t *n) /* amount bytes read */ 796{ 797 CURLcode result = CURLE_RECV_ERROR; 798 ssize_t nread = 0; 799 size_t bytesfromsocket = 0; 800 char *buffertofill = NULL; 801 struct connectdata *conn = data->conn; 802 803 /* Set 'num' to 0 or 1, depending on which socket that has been sent here. 804 If it is the second socket, we set num to 1. Otherwise to 0. This lets 805 us use the correct ssl handle. */ 806 int num = (sockfd == conn->sock[SECONDARYSOCKET]); 807 808 *n = 0; /* reset amount to zero */ 809 810 bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); 811 buffertofill = buf; 812 813 nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result); 814 if(nread < 0) 815 goto out; 816 817 *n += nread; 818 result = CURLE_OK; 819out: 820 return result; 821} 822