summaryrefslogtreecommitdiff
path: root/lib/sendf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sendf.c')
-rw-r--r--lib/sendf.c176
1 files changed, 96 insertions, 80 deletions
diff --git a/lib/sendf.c b/lib/sendf.c
index 76016978..595c3617 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -33,6 +33,7 @@
#include "non-ascii.h"
#include "strerror.h"
#include "select.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -148,7 +149,7 @@ 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 * BUFSIZE;
+ psnd->allocated_size = 2 * conn->data->set.buffer_size;
psnd->buffer = malloc(psnd->allocated_size);
psnd->recv_size = 0;
psnd->recv_processed = 0;
@@ -242,27 +243,26 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
va_list ap;
size_t len;
+ char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
+ vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+ len = strlen(error);
if(data->set.errorbuffer && !data->state.errorbuf) {
- snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
+ strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
if(data->set.verbose) {
- len = strlen(data->state.buffer);
- if(len < BUFSIZE - 1) {
- data->state.buffer[len] = '\n';
- data->state.buffer[++len] = '\0';
- }
- Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
+ error[len] = '\n';
+ error[++len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
}
va_end(ap);
}
-/* Curl_sendf() sends formated data to the server */
+/* Curl_sendf() sends formatted data to the server */
CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
const char *fmt, ...)
{
@@ -474,21 +474,58 @@ static CURLcode pausewrite(struct Curl_easy *data,
we want to send we need to dup it to save a copy for when the sending
is again enabled */
struct SingleRequest *k = &data->req;
- char *dupl = malloc(len);
- if(!dupl)
- return CURLE_OUT_OF_MEMORY;
+ struct UrlState *s = &data->state;
+ char *dupl;
+ unsigned int i;
+ bool newtype = TRUE;
+
+ if(s->tempcount) {
+ for(i=0; i< s->tempcount; i++) {
+ if(s->tempwrite[i].type == type) {
+ /* data for this type exists */
+ newtype = FALSE;
+ break;
+ }
+ }
+ DEBUGASSERT(i < 3);
+ }
+ 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;
- memcpy(dupl, ptr, len);
+ /* store this information in the state struct for later use */
+ s->tempwrite[i].buf = dupl;
+ s->tempwrite[i].len = len;
+ s->tempwrite[i].type = type;
- /* store this information in the state struct for later use */
- data->state.tempwrite = dupl;
- data->state.tempwritesize = len;
- data->state.tempwritetype = type;
+ if(newtype)
+ s->tempcount++;
+ }
/* mark the connection as RECV paused */
k->keepon |= KEEP_RECV_PAUSE;
- DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
+ DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n",
len, type));
return CURLE_OK;
@@ -511,31 +548,10 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
if(!len)
return CURLE_OK;
- /* If reading is actually paused, we're forced to append this chunk of data
- to the already held data, but only if it is the same type as otherwise it
- can't work and it'll return error instead. */
- if(data->req.keepon & KEEP_RECV_PAUSE) {
- size_t newlen;
- char *newptr;
- if(type != data->state.tempwritetype)
- /* major internal confusion */
- return CURLE_RECV_ERROR;
-
- DEBUGASSERT(data->state.tempwrite);
-
- /* figure out the new size of the data to save */
- newlen = len + data->state.tempwritesize;
- /* allocate the new memory area */
- newptr = realloc(data->state.tempwrite, newlen);
- if(!newptr)
- return CURLE_OUT_OF_MEMORY;
- /* copy the new data to the end of the new area */
- memcpy(newptr + data->state.tempwritesize, ptr, len);
- /* update the pointer and the size */
- data->state.tempwrite = newptr;
- data->state.tempwritesize = newlen;
- return CURLE_OK;
- }
+ /* If reading is paused, append this data to the already held data for this
+ type. */
+ if(data->req.keepon & KEEP_RECV_PAUSE)
+ return pausewrite(data, type, ptr, len);
/* Determine the callback(s) to use. */
if(type & CLIENTWRITE_BODY)
@@ -565,10 +581,9 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
failf(data, "Write callback asked for PAUSE when not supported!");
return CURLE_WRITE_ERROR;
}
- else
- return pausewrite(data, type, ptr, len);
+ return pausewrite(data, type, ptr, len);
}
- else if(wrote != chunklen) {
+ if(wrote != chunklen) {
failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
return CURLE_WRITE_ERROR;
}
@@ -616,6 +631,8 @@ CURLcode Curl_client_write(struct connectdata *conn,
if(0 == len)
len = strlen(ptr);
+ DEBUGASSERT(type <= 3);
+
/* FTP data may need conversion. */
if((type & CLIENTWRITE_BODY) &&
(conn->handler->protocol & PROTO_FAMILY_FTP) &&
@@ -652,8 +669,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
#endif
if(return_error)
return CURLE_AGAIN;
- else
- return CURLE_RECV_ERROR;
+ return CURLE_RECV_ERROR;
}
/* we only return number of bytes read when we return OK */
@@ -677,9 +693,10 @@ 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;
/* if HTTP/1 pipelining is both wanted and possible */
- bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
+ bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
(conn->bundle->multiuse == BUNDLE_PIPELINING);
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
@@ -705,13 +722,11 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
}
/* If we come here, it means that there is no data to read from the buffer,
* so we read from the socket */
- bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
+ bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
buffertofill = conn->master_buffer;
}
else {
- bytesfromsocket = CURLMIN((long)sizerequested,
- conn->data->set.buffer_size ?
- conn->data->set.buffer_size : BUFSIZE);
+ bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
buffertofill = buf;
}
@@ -736,21 +751,19 @@ static int showit(struct Curl_easy *data, curl_infotype type,
{
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+ int rc = 0;
#ifdef CURL_DOES_CONVERSIONS
- char buf[BUFSIZE+1];
+ char *buf = NULL;
size_t conv_size = 0;
switch(type) {
case CURLINFO_HEADER_OUT:
- /* assume output headers are ASCII */
- /* copy the data into my buffer so the original is unchanged */
- if(size > BUFSIZE) {
- size = BUFSIZE; /* truncate if necessary */
- buf[BUFSIZE] = '\0';
- }
+ buf = Curl_memdup(ptr, size);
+ if(!buf)
+ return 1;
conv_size = size;
- memcpy(buf, ptr, 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.
@@ -778,26 +791,29 @@ static int showit(struct Curl_easy *data, curl_infotype type,
#endif /* CURL_DOES_CONVERSIONS */
if(data->set.fdebug)
- return (*data->set.fdebug)(data, type, ptr, size,
- data->set.debugdata);
-
- 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);
+ rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ 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;
+ }
}
- return 0;
+#ifdef CURL_DOES_CONVERSIONS
+ free(buf);
+#endif
+ return rc;
}
int Curl_debug(struct Curl_easy *data, curl_infotype type,