1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-24 17:18:48 -05:00

upload: allocate upload buffer on-demand

Saves 16KB on the easy handle for operations that don't need that
buffer.

Part 1 of #2888
This commit is contained in:
Daniel Stenberg 2018-08-17 00:49:37 +02:00
parent 4939f36524
commit e6e9b006f7
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
7 changed files with 59 additions and 24 deletions

View File

@ -1123,7 +1123,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
CURLcode result; CURLcode result;
char *ptr; char *ptr;
size_t size; size_t size;
struct HTTP *http = conn->data->req.protop; struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
size_t sendsize; size_t sendsize;
curl_socket_t sockfd; curl_socket_t sockfd;
size_t headersize; size_t headersize;
@ -1143,7 +1144,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
DEBUGASSERT(size > included_body_bytes); DEBUGASSERT(size > included_body_bytes);
result = Curl_convert_to_network(conn->data, ptr, headersize); result = Curl_convert_to_network(data, ptr, headersize);
/* Curl_convert_to_network calls failf if unsuccessful */ /* Curl_convert_to_network calls failf if unsuccessful */
if(result) { if(result) {
/* conversion failed, free memory and return to the caller */ /* conversion failed, free memory and return to the caller */
@ -1168,8 +1169,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
must copy the data to the uploadbuffer first, since that is the buffer must copy the data to the uploadbuffer first, since that is the buffer
we will be using if this send is retried later. we will be using if this send is retried later.
*/ */
memcpy(conn->data->state.uploadbuffer, ptr, sendsize); result = Curl_get_upload_buffer(data);
ptr = conn->data->state.uploadbuffer; if(result) {
/* malloc failed, free memory and return to the caller */
Curl_add_buffer_free(in);
return result;
}
memcpy(data->state.ulbuf, ptr, sendsize);
ptr = data->state.ulbuf;
} }
else else
sendsize = size; sendsize = size;
@ -1186,13 +1193,13 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount; size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen; size_t bodylen = amount - headlen;
if(conn->data->set.verbose) { if(data->set.verbose) {
/* this data _may_ contain binary stuff */ /* this data _may_ contain binary stuff */
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen); Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
if(bodylen) { if(bodylen) {
/* there was body data sent beyond the initial header part, pass that /* there was body data sent beyond the initial header part, pass that
on to the debug callback too */ on to the debug callback too */
Curl_debug(conn->data, CURLINFO_DATA_OUT, Curl_debug(data, CURLINFO_DATA_OUT,
ptr + headlen, bodylen); ptr + headlen, bodylen);
} }
} }
@ -1217,14 +1224,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
ptr = in->buffer + amount; ptr = in->buffer + amount;
/* backup the currently set pointers */ /* backup the currently set pointers */
http->backup.fread_func = conn->data->state.fread_func; http->backup.fread_func = data->state.fread_func;
http->backup.fread_in = conn->data->state.in; http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata; http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize; http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */ /* set the new pointers for the request-sending */
conn->data->state.fread_func = (curl_read_callback)readmoredata; data->state.fread_func = (curl_read_callback)readmoredata;
conn->data->state.in = (void *)conn; data->state.in = (void *)conn;
http->postdata = ptr; http->postdata = ptr;
http->postsize = (curl_off_t)size; http->postsize = (curl_off_t)size;

View File

@ -592,6 +592,7 @@ static CURLcode multi_done(struct connectdata **connp,
conn->dns_entry = NULL; conn->dns_entry = NULL;
} }
Curl_hostcache_prune(data); Curl_hostcache_prune(data);
Curl_safefree(data->state.ulbuf);
/* if the transfer was completed in a paused state there can be buffered /* if the transfer was completed in a paused state there can be buffered
data left to free */ data left to free */
@ -1575,6 +1576,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_SENDPROTOCONNECT); multistate(data, CURLM_STATE_SENDPROTOCONNECT);
} }
} }
else if(result)
stream_error = TRUE;
break; break;
#endif #endif

View File

@ -367,7 +367,7 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
ssize_t bytes_written; ssize_t bytes_written;
CURLcode result; CURLcode result;
result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer, result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
len, &bytes_written); len, &bytes_written);
if(result) if(result)
return result; return result;
@ -393,7 +393,7 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
result = Curl_write(conn, FIRSTSOCKET, result = Curl_write(conn, FIRSTSOCKET,
conn->data->state.uploadbuffer + smbc->sent, conn->data->state.ulbuf + smbc->sent,
len, &bytes_written); len, &bytes_written);
if(result) if(result)
return result; return result;
@ -409,9 +409,12 @@ static CURLcode smb_flush(struct connectdata *conn)
static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd, static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
const void *msg, size_t msg_len) const void *msg, size_t msg_len)
{ {
smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer, CURLcode result = Curl_get_upload_buffer(conn->data);
if(result)
return result;
smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
cmd, msg_len); cmd, msg_len);
memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header), memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len); msg, msg_len);
return smb_send(conn, sizeof(struct smb_header) + msg_len, 0); return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
@ -572,11 +575,15 @@ static CURLcode smb_send_read(struct connectdata *conn)
static CURLcode smb_send_write(struct connectdata *conn) static CURLcode smb_send_write(struct connectdata *conn)
{ {
struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer; struct smb_write *msg;
struct smb_request *req = conn->data->req.protop; struct smb_request *req = conn->data->req.protop;
curl_off_t offset = conn->data->req.offset; curl_off_t offset = conn->data->req.offset;
curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount; curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
CURLcode result = Curl_get_upload_buffer(conn->data);
if(result)
return result;
msg = (struct smb_write *)conn->data->state.ulbuf;
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1; upload_size = MAX_PAYLOAD_SIZE - 1;
@ -605,7 +612,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
if(!smbc->send_size && smbc->upload_size) { if(!smbc->send_size && smbc->upload_size) {
int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE : int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
(int) smbc->upload_size; (int) smbc->upload_size;
conn->data->req.upload_fromhere = conn->data->state.uploadbuffer; conn->data->req.upload_fromhere = conn->data->state.ulbuf;
result = Curl_fillreadbuffer(conn, nread, &nread); result = Curl_fillreadbuffer(conn, nread, &nread);
if(result && result != CURLE_AGAIN) if(result && result != CURLE_AGAIN)
return result; return result;

View File

@ -106,6 +106,16 @@ char *Curl_checkheaders(const struct connectdata *conn,
} }
#endif #endif
CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
{
if(!data->state.ulbuf) {
data->state.ulbuf = malloc(data->set.upload_buffer_size);
if(!data->state.ulbuf)
return CURLE_OUT_OF_MEMORY;
}
return CURLE_OK;
}
/* /*
* This function will call the read callback to fill our buffer with data * This function will call the read callback to fill our buffer with data
* to upload. * to upload.
@ -914,8 +924,11 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* only read more data if there's no upload data already /* only read more data if there's no upload data already
present in the upload buffer */ present in the upload buffer */
if(0 == k->upload_present) { if(0 == k->upload_present) {
result = Curl_get_upload_buffer(data);
if(result)
return result;
/* init the "upload from here" pointer */ /* init the "upload from here" pointer */
k->upload_fromhere = data->state.uploadbuffer; k->upload_fromhere = data->state.ulbuf;
if(!k->upload_done) { if(!k->upload_done) {
/* HTTP pollution, this should be written nicer to become more /* HTTP pollution, this should be written nicer to become more
@ -1071,7 +1084,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
} }
else { else {
/* we've uploaded that buffer now */ /* we've uploaded that buffer now */
k->upload_fromhere = data->state.uploadbuffer; result = Curl_get_upload_buffer(data);
if(result)
return result;
k->upload_fromhere = data->state.ulbuf;
k->upload_present = 0; /* no more bytes left */ k->upload_present = 0; /* no more bytes left */
if(k->upload_done) { if(k->upload_done) {

View File

@ -54,6 +54,7 @@ CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp); CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
CURLcode Curl_retry_request(struct connectdata *conn, char **url); CURLcode Curl_retry_request(struct connectdata *conn, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
/* This sets up a forthcoming transfer */ /* This sets up a forthcoming transfer */
void void

View File

@ -367,11 +367,9 @@ CURLcode Curl_close(struct Curl_easy *data)
Curl_safefree(data->state.buffer); Curl_safefree(data->state.buffer);
Curl_safefree(data->state.headerbuff); Curl_safefree(data->state.headerbuff);
Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, 1); Curl_flush_cookies(data, 1);
Curl_digest_cleanup(data); Curl_digest_cleanup(data);
Curl_safefree(data->info.contenttype); Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect); Curl_safefree(data->info.wouldredirect);
@ -534,6 +532,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->expect_100_timeout = 1000L; /* Wait for a second by default. */ set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */ set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE; set->buffer_size = READBUFFER_SIZE;
set->upload_buffer_size = UPLOAD_BUFSIZE;
set->happy_eyeballs_timeout = CURL_HET_DEFAULT; set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
Curl_http2_init_userset(set); Curl_http2_init_userset(set);

View File

@ -1220,7 +1220,7 @@ struct UrlState {
size_t headersize; /* size of the allocation */ size_t headersize; /* size of the allocation */
char *buffer; /* download buffer */ char *buffer; /* download buffer */
char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */ char *ulbuf; /* alloced upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this, curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */ bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */ bool this_is_a_follow; /* this is a followed Location: request */
@ -1557,6 +1557,8 @@ struct UserDefined {
curl_proxytype proxytype; /* what kind of proxy that is in use */ curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */ long dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */ long buffer_size; /* size of receive buffer to use */
long upload_buffer_size; /* size of upload buffer to use,
keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */ void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */ struct curl_slist *http200aliases; /* linked list of aliases for http200 */