summaryrefslogtreecommitdiff
path: root/lib/sendf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sendf.c')
-rw-r--r--lib/sendf.c111
1 files changed, 27 insertions, 84 deletions
diff --git a/lib/sendf.c b/lib/sendf.c
index 6c38b04b2..6cfc89b69 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -43,6 +43,7 @@
#include "strerror.h"
#include "select.h"
#include "strdup.h"
+#include "http2.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -139,7 +140,7 @@ 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 connectdata *conn, int num)
{
const curl_socket_t sockfd = conn->sock[num];
struct postponed_data * const psnd = &(conn->postponed[num]);
@@ -160,6 +161,8 @@ static void pre_receive_plain(struct connectdata *conn, int num)
/* Use buffer double default size for intermediate buffer */
psnd->allocated_size = 2 * conn->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
@@ -179,6 +182,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,
@@ -224,7 +228,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(c,n) CURLE_OK
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -266,7 +270,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
size_t len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+ (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
len = strlen(error);
if(data->set.errorbuffer && !data->state.errorbuf) {
@@ -282,52 +286,6 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
}
}
-/* 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.
@@ -378,7 +336,10 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
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(conn, num)) {
+ *code = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
if(conn->bits.tcp_fastopen) {
@@ -497,10 +458,12 @@ static CURLcode pausewrite(struct Curl_easy *data,
is again enabled */
struct SingleRequest *k = &data->req;
struct UrlState *s = &data->state;
- char *dupl;
unsigned int i;
bool newtype = TRUE;
+ /* If this transfers over HTTP/2, pause the stream! */
+ Curl_http2_stream_pause(data, TRUE);
+
if(s->tempcount) {
for(i = 0; i< s->tempcount; i++) {
if(s->tempwrite[i].type == type) {
@@ -514,42 +477,21 @@ static CURLcode pausewrite(struct Curl_easy *data,
else
i = 0;
- if(!newtype) {
- /* append new data to old data */
-
- /* figure out the new size of the data to save */
- size_t newlen = len + s->tempwrite[i].len;
- /* allocate the new memory area */
- char *newptr = realloc(s->tempwrite[i].buf, newlen);
- if(!newptr)
- return CURLE_OUT_OF_MEMORY;
- /* copy the new data to the end of the new area */
- memcpy(newptr + s->tempwrite[i].len, ptr, len);
-
- /* update the pointer and the size */
- s->tempwrite[i].buf = newptr;
- s->tempwrite[i].len = newlen;
- }
- else {
- dupl = Curl_memdup(ptr, len);
- if(!dupl)
- return CURLE_OUT_OF_MEMORY;
-
+ if(newtype) {
/* store this information in the state struct for later use */
- s->tempwrite[i].buf = dupl;
- s->tempwrite[i].len = len;
+ Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
s->tempwrite[i].type = type;
if(newtype)
s->tempcount++;
}
+ if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
+ return CURLE_OUT_OF_MEMORY;
+
/* mark the connection as RECV paused */
k->keepon |= KEEP_RECV_PAUSE;
- DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n",
- len, type));
-
return CURLE_OK;
}
@@ -611,7 +553,7 @@ static CURLcode chop_write(struct connectdata *conn,
return pausewrite(data, type, ptr, len);
}
if(wrote != chunklen) {
- failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
+ failf(data, "Failure writing output to destination");
return CURLE_WRITE_ERROR;
}
}
@@ -692,19 +634,20 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
ssize_t nread = sread(sockfd, buf, bytesfromsocket);
if(-1 == nread) {
- int err = SOCKERRNO;
- int return_error;
+ const int err = SOCKERRNO;
+ const bool return_error =
#ifdef USE_WINSOCK
- return_error = WSAEWOULDBLOCK == err;
+ WSAEWOULDBLOCK == err
#else
- return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
+ EWOULDBLOCK == err || EAGAIN == err || EINTR == err
#endif
+ ;
+ *n = 0; /* no data returned */
if(return_error)
return CURLE_AGAIN;
return CURLE_RECV_ERROR;
}
- /* we only return number of bytes read when we return OK */
*n = nread;
return CURLE_OK;
}