diff options
Diffstat (limited to 'lib/sendf.c')
-rw-r--r-- | lib/sendf.c | 111 |
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; } |