1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, 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 #include <curl/curl.h> 26 27 #include "urldata.h" 28 #include "sendf.h" 29 #include "connect.h" 30 #include "vtls/vtls.h" 31 #include "ssh.h" 32 #include "multiif.h" 33 #include "non-ascii.h" 34 #include "strerror.h" 35 #include "select.h" 36 37 /* The last 3 #include files should be in this order */ 38 #include "curl_printf.h" 39 #include "curl_memory.h" 40 #include "memdebug.h" 41 42 #ifdef CURL_DO_LINEEND_CONV 43 /* 44 * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF 45 * (\n), with special processing for CRLF sequences that are split between two 46 * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new 47 * size of the data is returned. 48 */ 49 static size_t convert_lineends(struct Curl_easy *data, 50 char *startPtr, size_t size) 51 { 52 char *inPtr, *outPtr; 53 54 /* sanity check */ 55 if((startPtr == NULL) || (size < 1)) { 56 return size; 57 } 58 59 if(data->state.prev_block_had_trailing_cr) { 60 /* The previous block of incoming data 61 had a trailing CR, which was turned into a LF. */ 62 if(*startPtr == '\n') { 63 /* This block of incoming data starts with the 64 previous block's LF so get rid of it */ 65 memmove(startPtr, startPtr+1, size-1); 66 size--; 67 /* and it wasn't a bare CR but a CRLF conversion instead */ 68 data->state.crlf_conversions++; 69 } 70 data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ 71 } 72 73 /* find 1st CR, if any */ 74 inPtr = outPtr = memchr(startPtr, '\r', size); 75 if(inPtr) { 76 /* at least one CR, now look for CRLF */ 77 while(inPtr < (startPtr+size-1)) { 78 /* note that it's size-1, so we'll never look past the last byte */ 79 if(memcmp(inPtr, "\r\n", 2) == 0) { 80 /* CRLF found, bump past the CR and copy the NL */ 81 inPtr++; 82 *outPtr = *inPtr; 83 /* keep track of how many CRLFs we converted */ 84 data->state.crlf_conversions++; 85 } 86 else { 87 if(*inPtr == '\r') { 88 /* lone CR, move LF instead */ 89 *outPtr = '\n'; 90 } 91 else { 92 /* not a CRLF nor a CR, just copy whatever it is */ 93 *outPtr = *inPtr; 94 } 95 } 96 outPtr++; 97 inPtr++; 98 } /* end of while loop */ 99 100 if(inPtr < startPtr+size) { 101 /* handle last byte */ 102 if(*inPtr == '\r') { 103 /* deal with a CR at the end of the buffer */ 104 *outPtr = '\n'; /* copy a NL instead */ 105 /* note that a CRLF might be split across two blocks */ 106 data->state.prev_block_had_trailing_cr = TRUE; 107 } 108 else { 109 /* copy last byte */ 110 *outPtr = *inPtr; 111 } 112 outPtr++; 113 } 114 if(outPtr < startPtr+size) 115 /* tidy up by null terminating the now shorter data */ 116 *outPtr = '\0'; 117 118 return (outPtr - startPtr); 119 } 120 return size; 121 } 122 #endif /* CURL_DO_LINEEND_CONV */ 123 124 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND 125 static void pre_receive_plain(struct connectdata *conn, int num) 126 { 127 const curl_socket_t sockfd = conn->sock[num]; 128 struct postponed_data * const psnd = &(conn->postponed[num]); 129 size_t bytestorecv = psnd->allocated_size - psnd->recv_size; 130 /* WinSock will destroy unread received data if send() is 131 failed. 132 To avoid lossage of received data, recv() must be 133 performed before every send() if any incoming data is 134 available. However, skip this, if buffer is already full. */ 135 if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 && 136 conn->recv[num] == Curl_recv_plain && 137 (!psnd->buffer || bytestorecv)) { 138 const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD, 139 CURL_SOCKET_BAD, 0); 140 if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) { 141 /* Have some incoming data */ 142 if(!psnd->buffer) { 143 /* Use buffer double default size for intermediate buffer */ 144 psnd->allocated_size = 2 * BUFSIZE; 145 psnd->buffer = malloc(psnd->allocated_size); 146 psnd->recv_size = 0; 147 psnd->recv_processed = 0; 148 #ifdef DEBUGBUILD 149 psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */ 150 #endif /* DEBUGBUILD */ 151 bytestorecv = psnd->allocated_size; 152 } 153 if(psnd->buffer) { 154 ssize_t recvedbytes; 155 DEBUGASSERT(psnd->bindsock == sockfd); 156 recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size, 157 bytestorecv); 158 if(recvedbytes > 0) 159 psnd->recv_size += recvedbytes; 160 } 161 else 162 psnd->allocated_size = 0; 163 } 164 } 165 } 166 167 static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, 168 size_t len) 169 { 170 struct postponed_data * const psnd = &(conn->postponed[num]); 171 size_t copysize; 172 if(!psnd->buffer) 173 return 0; 174 175 DEBUGASSERT(psnd->allocated_size > 0); 176 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size); 177 DEBUGASSERT(psnd->recv_processed <= psnd->recv_size); 178 /* Check and process data that already received and storied in internal 179 intermediate buffer */ 180 if(psnd->recv_size > psnd->recv_processed) { 181 DEBUGASSERT(psnd->bindsock == conn->sock[num]); 182 copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed); 183 memcpy(buf, psnd->buffer + psnd->recv_processed, copysize); 184 psnd->recv_processed += copysize; 185 } 186 else 187 copysize = 0; /* buffer was allocated, but nothing was received */ 188 189 /* Free intermediate buffer if it has no unprocessed data */ 190 if(psnd->recv_processed == psnd->recv_size) { 191 free(psnd->buffer); 192 psnd->buffer = NULL; 193 psnd->allocated_size = 0; 194 psnd->recv_size = 0; 195 psnd->recv_processed = 0; 196 #ifdef DEBUGBUILD 197 psnd->bindsock = CURL_SOCKET_BAD; 198 #endif /* DEBUGBUILD */ 199 } 200 return (ssize_t)copysize; 201 } 202 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ 203 /* Use "do-nothing" macros instead of functions when workaround not used */ 204 #define pre_receive_plain(c,n) do {} WHILE_FALSE 205 #define get_pre_recved(c,n,b,l) 0 206 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ 207 208 /* Curl_infof() is for info message along the way */ 209 210 void Curl_infof(struct Curl_easy *data, const char *fmt, ...) 211 { 212 if(data && data->set.verbose) { 213 va_list ap; 214 size_t len; 215 char print_buffer[2048 + 1]; 216 va_start(ap, fmt); 217 vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); 218 va_end(ap); 219 len = strlen(print_buffer); 220 Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL); 221 } 222 } 223 224 /* Curl_failf() is for messages stating why we failed. 225 * The message SHALL NOT include any LF or CR. 226 */ 227 228 void Curl_failf(struct Curl_easy *data, const char *fmt, ...) 229 { 230 va_list ap; 231 size_t len; 232 va_start(ap, fmt); 233 234 vsnprintf(data->state.buffer, BUFSIZE, fmt, ap); 235 236 if(data->set.errorbuffer && !data->state.errorbuf) { 237 snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer); 238 data->state.errorbuf = TRUE; /* wrote error string */ 239 } 240 if(data->set.verbose) { 241 len = strlen(data->state.buffer); 242 if(len < BUFSIZE - 1) { 243 data->state.buffer[len] = '\n'; 244 data->state.buffer[++len] = '\0'; 245 } 246 Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL); 247 } 248 249 va_end(ap); 250 } 251 252 /* Curl_sendf() sends formated data to the server */ 253 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, 254 const char *fmt, ...) 255 { 256 struct Curl_easy *data = conn->data; 257 ssize_t bytes_written; 258 size_t write_len; 259 CURLcode result = CURLE_OK; 260 char *s; 261 char *sptr; 262 va_list ap; 263 va_start(ap, fmt); 264 s = vaprintf(fmt, ap); /* returns an allocated string */ 265 va_end(ap); 266 if(!s) 267 return CURLE_OUT_OF_MEMORY; /* failure */ 268 269 bytes_written=0; 270 write_len = strlen(s); 271 sptr = s; 272 273 for(;;) { 274 /* Write the buffer to the socket */ 275 result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); 276 277 if(result) 278 break; 279 280 if(data->set.verbose) 281 Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn); 282 283 if((size_t)bytes_written != write_len) { 284 /* if not all was written at once, we must advance the pointer, decrease 285 the size left and try again! */ 286 write_len -= bytes_written; 287 sptr += bytes_written; 288 } 289 else 290 break; 291 } 292 293 free(s); /* free the output string */ 294 295 return result; 296 } 297 298 /* 299 * Curl_write() is an internal write function that sends data to the 300 * server. Works with plain sockets, SCP, SSL or kerberos. 301 * 302 * If the write would block (CURLE_AGAIN), we return CURLE_OK and 303 * (*written == 0). Otherwise we return regular CURLcode value. 304 */ 305 CURLcode Curl_write(struct connectdata *conn, 306 curl_socket_t sockfd, 307 const void *mem, 308 size_t len, 309 ssize_t *written) 310 { 311 ssize_t bytes_written; 312 CURLcode result = CURLE_OK; 313 int num = (sockfd == conn->sock[SECONDARYSOCKET]); 314 315 bytes_written = conn->send[num](conn, num, mem, len, &result); 316 317 *written = bytes_written; 318 if(bytes_written >= 0) 319 /* we completely ignore the curlcode value when subzero is not returned */ 320 return CURLE_OK; 321 322 /* handle CURLE_AGAIN or a send failure */ 323 switch(result) { 324 case CURLE_AGAIN: 325 *written = 0; 326 return CURLE_OK; 327 328 case CURLE_OK: 329 /* general send failure */ 330 return CURLE_SEND_ERROR; 331 332 default: 333 /* we got a specific curlcode, forward it */ 334 return result; 335 } 336 } 337 338 ssize_t Curl_send_plain(struct connectdata *conn, int num, 339 const void *mem, size_t len, CURLcode *code) 340 { 341 curl_socket_t sockfd = conn->sock[num]; 342 ssize_t bytes_written; 343 /* WinSock will destroy unread received data if send() is 344 failed. 345 To avoid lossage of received data, recv() must be 346 performed before every send() if any incoming data is 347 available. */ 348 pre_receive_plain(conn, num); 349 350 #ifdef MSG_FASTOPEN /* Linux */ 351 if(conn->bits.tcp_fastopen) { 352 bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN, 353 conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen); 354 conn->bits.tcp_fastopen = FALSE; 355 } 356 else 357 #endif 358 bytes_written = swrite(sockfd, mem, len); 359 360 *code = CURLE_OK; 361 if(-1 == bytes_written) { 362 int err = SOCKERRNO; 363 364 if( 365 #ifdef WSAEWOULDBLOCK 366 /* This is how Windows does it */ 367 (WSAEWOULDBLOCK == err) 368 #else 369 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned 370 due to its inability to send off data without blocking. We therefor 371 treat both error codes the same here */ 372 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) || 373 (EINPROGRESS == err) 374 #endif 375 ) { 376 /* this is just a case of EWOULDBLOCK */ 377 bytes_written=0; 378 *code = CURLE_AGAIN; 379 } 380 else { 381 failf(conn->data, "Send failure: %s", 382 Curl_strerror(conn, err)); 383 conn->data->state.os_errno = err; 384 *code = CURLE_SEND_ERROR; 385 } 386 } 387 return bytes_written; 388 } 389 390 /* 391 * Curl_write_plain() is an internal write function that sends data to the 392 * server using plain sockets only. Otherwise meant to have the exact same 393 * proto as Curl_write() 394 */ 395 CURLcode Curl_write_plain(struct connectdata *conn, 396 curl_socket_t sockfd, 397 const void *mem, 398 size_t len, 399 ssize_t *written) 400 { 401 ssize_t bytes_written; 402 CURLcode result; 403 int num = (sockfd == conn->sock[SECONDARYSOCKET]); 404 405 bytes_written = Curl_send_plain(conn, num, mem, len, &result); 406 407 *written = bytes_written; 408 409 return result; 410 } 411 412 ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, 413 size_t len, CURLcode *code) 414 { 415 curl_socket_t sockfd = conn->sock[num]; 416 ssize_t nread; 417 /* Check and return data that already received and storied in internal 418 intermediate buffer */ 419 nread = get_pre_recved(conn, num, buf, len); 420 if(nread > 0) { 421 *code = CURLE_OK; 422 return nread; 423 } 424 425 nread = sread(sockfd, buf, len); 426 427 *code = CURLE_OK; 428 if(-1 == nread) { 429 int err = SOCKERRNO; 430 431 if( 432 #ifdef WSAEWOULDBLOCK 433 /* This is how Windows does it */ 434 (WSAEWOULDBLOCK == err) 435 #else 436 /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned 437 due to its inability to send off data without blocking. We therefor 438 treat both error codes the same here */ 439 (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) 440 #endif 441 ) { 442 /* this is just a case of EWOULDBLOCK */ 443 *code = CURLE_AGAIN; 444 } 445 else { 446 failf(conn->data, "Recv failure: %s", 447 Curl_strerror(conn, err)); 448 conn->data->state.os_errno = err; 449 *code = CURLE_RECV_ERROR; 450 } 451 } 452 return nread; 453 } 454 455 static CURLcode pausewrite(struct Curl_easy *data, 456 int type, /* what type of data */ 457 const char *ptr, 458 size_t len) 459 { 460 /* signalled to pause sending on this connection, but since we have data 461 we want to send we need to dup it to save a copy for when the sending 462 is again enabled */ 463 struct SingleRequest *k = &data->req; 464 char *dupl = malloc(len); 465 if(!dupl) 466 return CURLE_OUT_OF_MEMORY; 467 468 memcpy(dupl, ptr, len); 469 470 /* store this information in the state struct for later use */ 471 data->state.tempwrite = dupl; 472 data->state.tempwritesize = len; 473 data->state.tempwritetype = type; 474 475 /* mark the connection as RECV paused */ 476 k->keepon |= KEEP_RECV_PAUSE; 477 478 DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n", 479 len, type)); 480 481 return CURLE_OK; 482 } 483 484 485 /* Curl_client_chop_write() writes chunks of data not larger than 486 * CURL_MAX_WRITE_SIZE via client write callback(s) and 487 * takes care of pause requests from the callbacks. 488 */ 489 CURLcode Curl_client_chop_write(struct connectdata *conn, 490 int type, 491 char * ptr, 492 size_t len) 493 { 494 struct Curl_easy *data = conn->data; 495 curl_write_callback writeheader = NULL; 496 curl_write_callback writebody = NULL; 497 498 if(!len) 499 return CURLE_OK; 500 501 /* If reading is actually paused, we're forced to append this chunk of data 502 to the already held data, but only if it is the same type as otherwise it 503 can't work and it'll return error instead. */ 504 if(data->req.keepon & KEEP_RECV_PAUSE) { 505 size_t newlen; 506 char *newptr; 507 if(type != data->state.tempwritetype) 508 /* major internal confusion */ 509 return CURLE_RECV_ERROR; 510 511 DEBUGASSERT(data->state.tempwrite); 512 513 /* figure out the new size of the data to save */ 514 newlen = len + data->state.tempwritesize; 515 /* allocate the new memory area */ 516 newptr = realloc(data->state.tempwrite, newlen); 517 if(!newptr) 518 return CURLE_OUT_OF_MEMORY; 519 /* copy the new data to the end of the new area */ 520 memcpy(newptr + data->state.tempwritesize, ptr, len); 521 /* update the pointer and the size */ 522 data->state.tempwrite = newptr; 523 data->state.tempwritesize = newlen; 524 return CURLE_OK; 525 } 526 527 /* Determine the callback(s) to use. */ 528 if(type & CLIENTWRITE_BODY) 529 writebody = data->set.fwrite_func; 530 if((type & CLIENTWRITE_HEADER) && 531 (data->set.fwrite_header || data->set.writeheader)) { 532 /* 533 * Write headers to the same callback or to the especially setup 534 * header callback function (added after version 7.7.1). 535 */ 536 writeheader = 537 data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; 538 } 539 540 /* Chop data, write chunks. */ 541 while(len) { 542 size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; 543 544 if(writebody) { 545 size_t wrote = writebody(ptr, 1, chunklen, data->set.out); 546 547 if(CURL_WRITEFUNC_PAUSE == wrote) { 548 if(conn->handler->flags & PROTOPT_NONETWORK) { 549 /* Protocols that work without network cannot be paused. This is 550 actually only FILE:// just now, and it can't pause since the 551 transfer isn't done using the "normal" procedure. */ 552 failf(data, "Write callback asked for PAUSE when not supported!"); 553 return CURLE_WRITE_ERROR; 554 } 555 else 556 return pausewrite(data, type, ptr, len); 557 } 558 else if(wrote != chunklen) { 559 failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); 560 return CURLE_WRITE_ERROR; 561 } 562 } 563 564 if(writeheader) { 565 size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader); 566 567 if(CURL_WRITEFUNC_PAUSE == wrote) 568 /* here we pass in the HEADER bit only since if this was body as well 569 then it was passed already and clearly that didn't trigger the 570 pause, so this is saved for later with the HEADER bit only */ 571 return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); 572 573 if(wrote != chunklen) { 574 failf (data, "Failed writing header"); 575 return CURLE_WRITE_ERROR; 576 } 577 } 578 579 ptr += chunklen; 580 len -= chunklen; 581 } 582 583 return CURLE_OK; 584 } 585 586 587 /* Curl_client_write() sends data to the write callback(s) 588 589 The bit pattern defines to what "streams" to write to. Body and/or header. 590 The defines are in sendf.h of course. 591 592 If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the 593 local character encoding. This is a problem and should be changed in 594 the future to leave the original data alone. 595 */ 596 CURLcode Curl_client_write(struct connectdata *conn, 597 int type, 598 char *ptr, 599 size_t len) 600 { 601 struct Curl_easy *data = conn->data; 602 603 if(0 == len) 604 len = strlen(ptr); 605 606 /* FTP data may need conversion. */ 607 if((type & CLIENTWRITE_BODY) && 608 (conn->handler->protocol & PROTO_FAMILY_FTP) && 609 conn->proto.ftpc.transfertype == 'A') { 610 /* convert from the network encoding */ 611 CURLcode result = Curl_convert_from_network(data, ptr, len); 612 /* Curl_convert_from_network calls failf if unsuccessful */ 613 if(result) 614 return result; 615 616 #ifdef CURL_DO_LINEEND_CONV 617 /* convert end-of-line markers */ 618 len = convert_lineends(data, ptr, len); 619 #endif /* CURL_DO_LINEEND_CONV */ 620 } 621 622 return Curl_client_chop_write(conn, type, ptr, len); 623 } 624 625 CURLcode Curl_read_plain(curl_socket_t sockfd, 626 char *buf, 627 size_t bytesfromsocket, 628 ssize_t *n) 629 { 630 ssize_t nread = sread(sockfd, buf, bytesfromsocket); 631 632 if(-1 == nread) { 633 int err = SOCKERRNO; 634 int return_error; 635 #ifdef USE_WINSOCK 636 return_error = WSAEWOULDBLOCK == err; 637 #else 638 return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err; 639 #endif 640 if(return_error) 641 return CURLE_AGAIN; 642 else 643 return CURLE_RECV_ERROR; 644 } 645 646 /* we only return number of bytes read when we return OK */ 647 *n = nread; 648 return CURLE_OK; 649 } 650 651 /* 652 * Internal read-from-socket function. This is meant to deal with plain 653 * sockets, SSL sockets and kerberos sockets. 654 * 655 * Returns a regular CURLcode value. 656 */ 657 CURLcode Curl_read(struct connectdata *conn, /* connection data */ 658 curl_socket_t sockfd, /* read from this socket */ 659 char *buf, /* store read data here */ 660 size_t sizerequested, /* max amount to read */ 661 ssize_t *n) /* amount bytes read */ 662 { 663 CURLcode result = CURLE_RECV_ERROR; 664 ssize_t nread = 0; 665 size_t bytesfromsocket = 0; 666 char *buffertofill = NULL; 667 668 /* if HTTP/1 pipelining is both wanted and possible */ 669 bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) && 670 (conn->bundle->multiuse == BUNDLE_PIPELINING); 671 672 /* Set 'num' to 0 or 1, depending on which socket that has been sent here. 673 If it is the second socket, we set num to 1. Otherwise to 0. This lets 674 us use the correct ssl handle. */ 675 int num = (sockfd == conn->sock[SECONDARYSOCKET]); 676 677 *n=0; /* reset amount to zero */ 678 679 /* If session can pipeline, check connection buffer */ 680 if(pipelining) { 681 size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos, 682 sizerequested); 683 684 /* Copy from our master buffer first if we have some unread data there*/ 685 if(bytestocopy > 0) { 686 memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); 687 conn->read_pos += bytestocopy; 688 conn->bits.stream_was_rewound = FALSE; 689 690 *n = (ssize_t)bytestocopy; 691 return CURLE_OK; 692 } 693 /* If we come here, it means that there is no data to read from the buffer, 694 * so we read from the socket */ 695 bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char)); 696 buffertofill = conn->master_buffer; 697 } 698 else { 699 bytesfromsocket = CURLMIN((long)sizerequested, 700 conn->data->set.buffer_size ? 701 conn->data->set.buffer_size : BUFSIZE); 702 buffertofill = buf; 703 } 704 705 nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); 706 if(nread < 0) 707 return result; 708 709 if(pipelining) { 710 memcpy(buf, conn->master_buffer, nread); 711 conn->buf_len = nread; 712 conn->read_pos = nread; 713 } 714 715 *n += nread; 716 717 return CURLE_OK; 718 } 719 720 /* return 0 on success */ 721 static int showit(struct Curl_easy *data, curl_infotype type, 722 char *ptr, size_t size) 723 { 724 static const char s_infotype[CURLINFO_END][3] = { 725 "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; 726 727 #ifdef CURL_DOES_CONVERSIONS 728 char buf[BUFSIZE+1]; 729 size_t conv_size = 0; 730 731 switch(type) { 732 case CURLINFO_HEADER_OUT: 733 /* assume output headers are ASCII */ 734 /* copy the data into my buffer so the original is unchanged */ 735 if(size > BUFSIZE) { 736 size = BUFSIZE; /* truncate if necessary */ 737 buf[BUFSIZE] = '\0'; 738 } 739 conv_size = size; 740 memcpy(buf, ptr, size); 741 /* Special processing is needed for this block if it 742 * contains both headers and data (separated by CRLFCRLF). 743 * We want to convert just the headers, leaving the data as-is. 744 */ 745 if(size > 4) { 746 size_t i; 747 for(i = 0; i < size-4; i++) { 748 if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { 749 /* convert everything through this CRLFCRLF but no further */ 750 conv_size = i + 4; 751 break; 752 } 753 } 754 } 755 756 Curl_convert_from_network(data, buf, conv_size); 757 /* Curl_convert_from_network calls failf if unsuccessful */ 758 /* we might as well continue even if it fails... */ 759 ptr = buf; /* switch pointer to use my buffer instead */ 760 break; 761 default: 762 /* leave everything else as-is */ 763 break; 764 } 765 #endif /* CURL_DOES_CONVERSIONS */ 766 767 if(data->set.fdebug) 768 return (*data->set.fdebug)(data, type, ptr, size, 769 data->set.debugdata); 770 771 switch(type) { 772 case CURLINFO_TEXT: 773 case CURLINFO_HEADER_OUT: 774 case CURLINFO_HEADER_IN: 775 fwrite(s_infotype[type], 2, 1, data->set.err); 776 fwrite(ptr, size, 1, data->set.err); 777 #ifdef CURL_DOES_CONVERSIONS 778 if(size != conv_size) { 779 /* we had untranslated data so we need an explicit newline */ 780 fwrite("\n", 1, 1, data->set.err); 781 } 782 #endif 783 break; 784 default: /* nada */ 785 break; 786 } 787 return 0; 788 } 789 790 int Curl_debug(struct Curl_easy *data, curl_infotype type, 791 char *ptr, size_t size, 792 struct connectdata *conn) 793 { 794 int rc; 795 if(data->set.printhost && conn && conn->host.dispname) { 796 char buffer[160]; 797 const char *t=NULL; 798 const char *w="Data"; 799 switch (type) { 800 case CURLINFO_HEADER_IN: 801 w = "Header"; 802 /* FALLTHROUGH */ 803 case CURLINFO_DATA_IN: 804 t = "from"; 805 break; 806 case CURLINFO_HEADER_OUT: 807 w = "Header"; 808 /* FALLTHROUGH */ 809 case CURLINFO_DATA_OUT: 810 t = "to"; 811 break; 812 default: 813 break; 814 } 815 816 if(t) { 817 snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t, 818 conn->host.dispname); 819 rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer)); 820 if(rc) 821 return rc; 822 } 823 } 824 rc = showit(data, type, ptr, size); 825 return rc; 826 } 827