diff options
Diffstat (limited to 'Utilities/cmcurl/lib/sendf.c')
-rw-r--r-- | Utilities/cmcurl/lib/sendf.c | 252 |
1 files changed, 115 insertions, 137 deletions
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c index 6943fa84e..b3c7fe33d 100644 --- a/Utilities/cmcurl/lib/sendf.c +++ b/Utilities/cmcurl/lib/sendf.c @@ -5,11 +5,11 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -28,6 +28,8 @@ #ifdef HAVE_LINUX_TCP_H #include <linux/tcp.h> +#elif defined(HAVE_NETINET_TCP_H) +#include <netinet/tcp.h> #endif #include <curl/curl.h> @@ -140,7 +142,8 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) psnd->recv_size > psnd->recv_processed; } -static void pre_receive_plain(struct connectdata *conn, int num) +static CURLcode pre_receive_plain(struct Curl_easy *data, + struct connectdata *conn, int num) { const curl_socket_t sockfd = conn->sock[num]; struct postponed_data * const psnd = &(conn->postponed[num]); @@ -159,8 +162,10 @@ static void pre_receive_plain(struct connectdata *conn, int num) /* Have some incoming data */ if(!psnd->buffer) { /* Use buffer double default size for intermediate buffer */ - psnd->allocated_size = 2 * conn->data->set.buffer_size; + psnd->allocated_size = 2 * data->set.buffer_size; psnd->buffer = malloc(psnd->allocated_size); + if(!psnd->buffer) + return CURLE_OUT_OF_MEMORY; psnd->recv_size = 0; psnd->recv_processed = 0; #ifdef DEBUGBUILD @@ -180,6 +185,7 @@ static void pre_receive_plain(struct connectdata *conn, int num) psnd->allocated_size = 0; } } + return CURLE_OK; } static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, @@ -225,7 +231,7 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) (void)sockindex; return false; } -#define pre_receive_plain(c,n) do {} while(0) +#define pre_receive_plain(d,c,n) CURLE_OK #define get_pre_recved(c,n,b,l) 0 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ @@ -262,6 +268,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...) void Curl_failf(struct Curl_easy *data, const char *fmt, ...) { + DEBUGASSERT(!strchr(fmt, '\n')); if(data->set.verbose || data->set.errorbuffer) { va_list ap; size_t len; @@ -274,61 +281,12 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) strcpy(data->set.errorbuffer, error); data->state.errorbuf = TRUE; /* wrote error string */ } - if(data->set.verbose) { - error[len] = '\n'; - error[++len] = '\0'; - Curl_debug(data, CURLINFO_TEXT, error, len); - } + error[len++] = '\n'; + Curl_debug(data, CURLINFO_TEXT, error, len); va_end(ap); } } -/* Curl_sendf() sends formatted data to the server */ -CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, - const char *fmt, ...) -{ - struct Curl_easy *data = conn->data; - ssize_t bytes_written; - size_t write_len; - CURLcode result = CURLE_OK; - char *s; - char *sptr; - va_list ap; - va_start(ap, fmt); - s = vaprintf(fmt, ap); /* returns an allocated string */ - va_end(ap); - if(!s) - return CURLE_OUT_OF_MEMORY; /* failure */ - - bytes_written = 0; - write_len = strlen(s); - sptr = s; - - for(;;) { - /* Write the buffer to the socket */ - result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); - - if(result) - break; - - if(data->set.verbose) - Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written); - - if((size_t)bytes_written != write_len) { - /* if not all was written at once, we must advance the pointer, decrease - the size left and try again! */ - write_len -= bytes_written; - sptr += bytes_written; - } - else - break; - } - - free(s); /* free the output string */ - - return result; -} - /* * Curl_write() is an internal write function that sends data to the * server. Works with plain sockets, SCP, SSL or kerberos. @@ -336,7 +294,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, * If the write would block (CURLE_AGAIN), we return CURLE_OK and * (*written == 0). Otherwise we return regular CURLcode value. */ -CURLcode Curl_write(struct connectdata *conn, +CURLcode Curl_write(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, @@ -344,9 +302,14 @@ CURLcode Curl_write(struct connectdata *conn, { ssize_t bytes_written; CURLcode result = CURLE_OK; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); + struct connectdata *conn; + int num; + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + num = (sockfd == conn->sock[SECONDARYSOCKET]); - bytes_written = conn->send[num](conn, num, mem, len, &result); + bytes_written = conn->send[num](data, num, mem, len, &result); *written = bytes_written; if(bytes_written >= 0) @@ -369,17 +332,26 @@ CURLcode Curl_write(struct connectdata *conn, } } -ssize_t Curl_send_plain(struct connectdata *conn, int num, +ssize_t Curl_send_plain(struct Curl_easy *data, int num, const void *mem, size_t len, CURLcode *code) { - curl_socket_t sockfd = conn->sock[num]; + struct connectdata *conn; + curl_socket_t sockfd; ssize_t bytes_written; + + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + sockfd = conn->sock[num]; /* WinSock will destroy unread received data if send() is failed. To avoid lossage of received data, recv() must be performed before every send() if any incoming data is available. */ - pre_receive_plain(conn, num); + if(pre_receive_plain(data, conn, num)) { + *code = CURLE_OUT_OF_MEMORY; + return -1; + } #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ if(conn->bits.tcp_fastopen) { @@ -413,9 +385,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, } else { char buffer[STRERROR_LEN]; - failf(conn->data, "Send failure: %s", + failf(data, "Send failure: %s", Curl_strerror(err, buffer, sizeof(buffer))); - conn->data->state.os_errno = err; + data->state.os_errno = err; *code = CURLE_SEND_ERROR; } } @@ -427,28 +399,33 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, * server using plain sockets only. Otherwise meant to have the exact same * proto as Curl_write() */ -CURLcode Curl_write_plain(struct connectdata *conn, +CURLcode Curl_write_plain(struct Curl_easy *data, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written) { - ssize_t bytes_written; CURLcode result; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); + struct connectdata *conn = data->conn; + int num; + DEBUGASSERT(conn); + num = (sockfd == conn->sock[SECONDARYSOCKET]); - bytes_written = Curl_send_plain(conn, num, mem, len, &result); - - *written = bytes_written; + *written = Curl_send_plain(data, num, mem, len, &result); return result; } -ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, +ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf, size_t len, CURLcode *code) { - curl_socket_t sockfd = conn->sock[num]; + struct connectdata *conn; + curl_socket_t sockfd; ssize_t nread; + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + conn = data->conn; + sockfd = conn->sock[num]; /* Check and return data that already received and storied in internal intermediate buffer */ nread = get_pre_recved(conn, num, buf, len); @@ -479,9 +456,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, } else { char buffer[STRERROR_LEN]; - failf(conn->data, "Recv failure: %s", + failf(data, "Recv failure: %s", Curl_strerror(err, buffer, sizeof(buffer))); - conn->data->state.os_errno = err; + data->state.os_errno = err; *code = CURLE_RECV_ERROR; } } @@ -540,12 +517,12 @@ static CURLcode pausewrite(struct Curl_easy *data, * client write callback(s) and takes care of pause requests from the * callbacks. */ -static CURLcode chop_write(struct connectdata *conn, +static CURLcode chop_write(struct Curl_easy *data, int type, char *optr, size_t olen) { - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; curl_write_callback writeheader = NULL; curl_write_callback writebody = NULL; char *ptr = optr; @@ -635,13 +612,12 @@ static CURLcode chop_write(struct connectdata *conn, local character encoding. This is a problem and should be changed in the future to leave the original data alone. */ -CURLcode Curl_client_write(struct connectdata *conn, +CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, size_t len) { - struct Curl_easy *data = conn->data; - + struct connectdata *conn = data->conn; if(0 == len) len = strlen(ptr); @@ -663,7 +639,7 @@ CURLcode Curl_client_write(struct connectdata *conn, #endif /* CURL_DO_LINEEND_CONV */ } - return chop_write(conn, type, ptr, len); + return chop_write(data, type, ptr, len); } CURLcode Curl_read_plain(curl_socket_t sockfd, @@ -698,7 +674,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd, * * Returns a regular CURLcode value. */ -CURLcode Curl_read(struct connectdata *conn, /* connection data */ +CURLcode Curl_read(struct Curl_easy *data, /* transfer */ curl_socket_t sockfd, /* read from this socket */ char *buf, /* store read data here */ size_t sizerequested, /* max amount to read */ @@ -708,7 +684,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ ssize_t nread = 0; size_t bytesfromsocket = 0; char *buffertofill = NULL; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets @@ -720,7 +696,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); buffertofill = buf; - nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result); + nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result); if(nread < 0) return result; @@ -733,72 +709,74 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ int Curl_debug(struct Curl_easy *data, curl_infotype type, char *ptr, size_t size) { - static const char s_infotype[CURLINFO_END][3] = { - "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; int rc = 0; + if(data->set.verbose) { + static const char s_infotype[CURLINFO_END][3] = { + "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; #ifdef CURL_DOES_CONVERSIONS - char *buf = NULL; - size_t conv_size = 0; - - switch(type) { - case CURLINFO_HEADER_OUT: - buf = Curl_memdup(ptr, size); - if(!buf) - return 1; - conv_size = size; - - /* Special processing is needed for this block if it - * contains both headers and data (separated by CRLFCRLF). - * We want to convert just the headers, leaving the data as-is. - */ - if(size > 4) { - size_t i; - for(i = 0; i < size-4; i++) { - if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { - /* convert everything through this CRLFCRLF but no further */ - conv_size = i + 4; - break; + char *buf = NULL; + size_t conv_size = 0; + + switch(type) { + case CURLINFO_HEADER_OUT: + buf = Curl_memdup(ptr, size); + if(!buf) + return 1; + conv_size = size; + + /* Special processing is needed for this block if it + * contains both headers and data (separated by CRLFCRLF). + * We want to convert just the headers, leaving the data as-is. + */ + if(size > 4) { + size_t i; + for(i = 0; i < size-4; i++) { + if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { + /* convert everything through this CRLFCRLF but no further */ + conv_size = i + 4; + break; + } } } - } - Curl_convert_from_network(data, buf, conv_size); - /* Curl_convert_from_network calls failf if unsuccessful */ - /* we might as well continue even if it fails... */ - ptr = buf; /* switch pointer to use my buffer instead */ - break; - default: - /* leave everything else as-is */ - break; - } + Curl_convert_from_network(data, buf, conv_size); + /* Curl_convert_from_network calls failf if unsuccessful */ + /* we might as well continue even if it fails... */ + ptr = buf; /* switch pointer to use my buffer instead */ + break; + default: + /* leave everything else as-is */ + break; + } #endif /* CURL_DOES_CONVERSIONS */ - if(data->set.fdebug) { - Curl_set_in_callback(data, true); - rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); - Curl_set_in_callback(data, false); - } - else { - switch(type) { - case CURLINFO_TEXT: - case CURLINFO_HEADER_OUT: - case CURLINFO_HEADER_IN: - fwrite(s_infotype[type], 2, 1, data->set.err); - fwrite(ptr, size, 1, data->set.err); + if(data->set.fdebug) { + Curl_set_in_callback(data, true); + rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); + Curl_set_in_callback(data, false); + } + else { + switch(type) { + case CURLINFO_TEXT: + case CURLINFO_HEADER_OUT: + case CURLINFO_HEADER_IN: + fwrite(s_infotype[type], 2, 1, data->set.err); + fwrite(ptr, size, 1, data->set.err); #ifdef CURL_DOES_CONVERSIONS - if(size != conv_size) { - /* we had untranslated data so we need an explicit newline */ - fwrite("\n", 1, 1, data->set.err); - } + if(size != conv_size) { + /* we had untranslated data so we need an explicit newline */ + fwrite("\n", 1, 1, data->set.err); + } #endif - break; - default: /* nada */ - break; + break; + default: /* nada */ + break; + } } - } #ifdef CURL_DOES_CONVERSIONS - free(buf); + free(buf); #endif + } return rc; } |