summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/sendf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/sendf.c')
-rw-r--r--Utilities/cmcurl/lib/sendf.c252
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;
}