summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/easy.c7
-rw-r--r--lib/http.c29
-rw-r--r--lib/http2.c20
-rw-r--r--lib/multi.c3
-rw-r--r--lib/setopt.c9
-rw-r--r--lib/smb.c21
-rw-r--r--lib/transfer.c22
-rw-r--r--lib/transfer.h1
-rw-r--r--lib/url.c5
-rw-r--r--lib/urldata.h14
10 files changed, 100 insertions, 31 deletions
diff --git a/lib/easy.c b/lib/easy.c
index 5af90e326..027d0bef3 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -958,6 +958,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->change.referer_alloc = TRUE;
}
+ /* Reinitialize an SSL engine for the new handle
+ * note: the engine name has already been copied by dupset */
+ if(outcurl->set.str[STRING_SSL_ENGINE]) {
+ if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
+ goto fail;
+ }
+
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(&outcurl->state.resolver,
data->state.resolver))
diff --git a/lib/http.c b/lib/http.c
index 2e9f40719..e727ed823 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1123,7 +1123,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
CURLcode result;
char *ptr;
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;
curl_socket_t sockfd;
size_t headersize;
@@ -1143,7 +1144,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
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 */
if(result) {
/* 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
we will be using if this send is retried later.
*/
- memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
- ptr = conn->data->state.uploadbuffer;
+ result = Curl_get_upload_buffer(data);
+ 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
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 bodylen = amount - headlen;
- if(conn->data->set.verbose) {
+ if(data->set.verbose) {
/* 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) {
/* there was body data sent beyond the initial header part, pass that
on to the debug callback too */
- Curl_debug(conn->data, CURLINFO_DATA_OUT,
+ Curl_debug(data, CURLINFO_DATA_OUT,
ptr + headlen, bodylen);
}
}
@@ -1217,14 +1224,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
ptr = in->buffer + amount;
/* backup the currently set pointers */
- http->backup.fread_func = conn->data->state.fread_func;
- http->backup.fread_in = conn->data->state.in;
+ http->backup.fread_func = data->state.fread_func;
+ http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */
- conn->data->state.fread_func = (curl_read_callback)readmoredata;
- conn->data->state.in = (void *)conn;
+ data->state.fread_func = (curl_read_callback)readmoredata;
+ data->state.in = (void *)conn;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
diff --git a/lib/http2.c b/lib/http2.c
index ea13ec935..702a71731 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -1147,6 +1147,9 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
struct HTTP *http = data->req.protop;
struct http_conn *httpc = &conn->proto.httpc;
+ if(!httpc->h2) /* not HTTP/2 ? */
+ return;
+
if(data->state.drain)
drained_transfer(data, httpc);
@@ -1167,8 +1170,10 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
if(premature) {
/* RST_STREAM */
- nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
- NGHTTP2_STREAM_CLOSED);
+ if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
+ http->stream_id, NGHTTP2_STREAM_CLOSED))
+ (void)nghttp2_session_send(httpc->h2);
+
if(http->stream_id == httpc->pause_stream_id) {
infof(data, "stopped the pause stream!\n");
httpc->pause_stream_id = 0;
@@ -1177,6 +1182,17 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
if(http->emap)
/* remove stream <=> easy association */
disassociate_easymap(http->emap);
+ /* -1 means unassigned and 0 means cleared */
+ if(http->stream_id > 0) {
+ int rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ http->stream_id, 0);
+ if(rv) {
+ infof(data, "http/2: failed to clear user_data for stream %u!\n",
+ http->stream_id);
+ DEBUGASSERT(0);
+ }
+ http->stream_id = 0;
+ }
}
/*
diff --git a/lib/multi.c b/lib/multi.c
index c2c5e1c27..0caf94322 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -592,6 +592,7 @@ static CURLcode multi_done(struct connectdata **connp,
conn->dns_entry = NULL;
}
Curl_hostcache_prune(data);
+ Curl_safefree(data->state.ulbuf);
/* if the transfer was completed in a paused state there can be buffered
data left to free */
@@ -1575,6 +1576,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
}
}
+ else if(result)
+ stream_error = TRUE;
break;
#endif
diff --git a/lib/setopt.c b/lib/setopt.c
index 5ecf5b97f..5c5f4b381 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -1603,14 +1603,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* String that holds the SSL crypto engine.
*/
argptr = va_arg(param, char *);
- if(argptr && argptr[0])
- result = Curl_ssl_set_engine(data, argptr);
+ if(argptr && argptr[0]) {
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr);
+ if(!result) {
+ result = Curl_ssl_set_engine(data, argptr);
+ }
+ }
break;
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
+ Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL);
result = Curl_ssl_set_engine_default(data);
break;
case CURLOPT_CRLF:
diff --git a/lib/smb.c b/lib/smb.c
index 09aa8efc7..32f0ac889 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -367,7 +367,7 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer,
+ result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
@@ -393,7 +393,7 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK;
result = Curl_write(conn, FIRSTSOCKET,
- conn->data->state.uploadbuffer + smbc->sent,
+ conn->data->state.ulbuf + smbc->sent,
len, &bytes_written);
if(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,
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);
- memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header),
+ memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len);
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)
{
- struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer;
+ struct smb_write *msg;
struct smb_request *req = conn->data->req.protop;
curl_off_t offset = conn->data->req.offset;
-
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 */
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) {
int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
(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);
if(result && result != CURLE_AGAIN)
return result;
diff --git a/lib/transfer.c b/lib/transfer.c
index 49f32568f..ab9094adc 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -106,6 +106,16 @@ char *Curl_checkheaders(const struct connectdata *conn,
}
#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
* 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
present in the upload buffer */
if(0 == k->upload_present) {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
/* init the "upload from here" pointer */
- k->upload_fromhere = data->state.uploadbuffer;
+ k->upload_fromhere = data->state.ulbuf;
if(!k->upload_done) {
/* HTTP pollution, this should be written nicer to become more
@@ -979,7 +992,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
if(!data->state.scratch) {
- data->state.scratch = malloc(2 * data->set.buffer_size);
+ data->state.scratch = malloc(2 * UPLOAD_BUFSIZE);
if(!data->state.scratch) {
failf(data, "Failed to alloc scratch buffer!");
@@ -1071,7 +1084,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
else {
/* 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 */
if(k->upload_done) {
diff --git a/lib/transfer.h b/lib/transfer.h
index 9ba398d27..df75f9a97 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -54,6 +54,7 @@ CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
CURLcode Curl_retry_request(struct connectdata *conn, char **url);
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 */
void
diff --git a/lib/url.c b/lib/url.c
index dcb7fcf6c..12f0f8ae7 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -367,11 +367,9 @@ CURLcode Curl_close(struct Curl_easy *data)
Curl_safefree(data->state.buffer);
Curl_safefree(data->state.headerbuff);
-
+ Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, 1);
-
Curl_digest_cleanup(data);
-
Curl_safefree(data->info.contenttype);
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->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
+ set->upload_buffer_size = UPLOAD_BUFSIZE;
set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
Curl_http2_init_userset(set);
diff --git a/lib/urldata.h b/lib/urldata.h
index 2a0540fa9..67db3b2fc 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -143,8 +143,13 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#endif /* HAVE_LIBSSH2_H */
/* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
- it needs to hold a full buffer as could be sent in a write callback */
-#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
+ it needs to hold a full buffer as could be sent in a write callback.
+
+ The size was 16KB for many years but was bumped to 64KB because it makes
+ libcurl able to do significantly faster uploads in some circumstances. Even
+ larger buffers can help further, but this is deemed a fair memory/speed
+ compromise. */
+#define UPLOAD_BUFSIZE 65536
/* The "master buffer" is for HTTP pipelining */
#define MASTERBUF_SIZE 16384
@@ -1220,7 +1225,7 @@ struct UrlState {
size_t headersize; /* size of the allocation */
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,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
@@ -1404,6 +1409,7 @@ enum dupstring {
STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
+ STRING_SSL_ENGINE, /* name of ssl engine */
STRING_USERNAME, /* <username>, if used */
STRING_PASSWORD, /* <password>, if used */
STRING_OPTIONS, /* <options>, if used */
@@ -1556,6 +1562,8 @@ struct UserDefined {
curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
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 */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */