summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-03-26 10:06:51 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-03-26 23:08:04 +0100
commit9a4a8ef451ed0a14242dc9e347064cc4bf4cbb87 (patch)
tree3290903f8b6d9771823c5f131ebde1b80e1bf157
parentd003b0213a08678264db5c987a0556a2a6785438 (diff)
downloadcurl-9a4a8ef451ed0a14242dc9e347064cc4bf4cbb87.tar.gz
http: cap body data amount during send speed limiting
By making sure never to send off more than the allowed number of bytes per second the speed limit logic is given more room to actually work. Reported-by: Fabian Keil Bug: https://curl.se/mail/lib-2021-03/0042.html
-rw-r--r--lib/http.c49
-rw-r--r--lib/http.h2
2 files changed, 40 insertions, 11 deletions
diff --git a/lib/http.c b/lib/http.c
index cb065ed58..e467771a7 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1167,7 +1167,12 @@ static size_t readmoredata(char *buffer,
/* make sure that a HTTP request is never sent away chunked! */
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
- if(http->postsize <= (curl_off_t)fullsize) {
+ if((data->set.max_send_speed > 0) &&
+ (data->set.max_send_speed < http->postsize))
+ /* speed limit */
+ fullsize = (size_t)data->set.max_send_speed;
+
+ else if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize);
fullsize = (size_t)http->postsize;
@@ -1207,7 +1212,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
counter */
curl_off_t *bytes_written,
/* how much of the buffer contains body data */
- size_t included_body_bytes,
+ curl_off_t included_body_bytes,
int socketindex)
{
ssize_t amount;
@@ -1230,10 +1235,10 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
ptr = Curl_dyn_ptr(in);
size = Curl_dyn_len(in);
- headersize = size - included_body_bytes; /* the initial part that isn't body
- is header */
+ headersize = size - (size_t)included_body_bytes; /* the initial part that
+ isn't body is header */
- DEBUGASSERT(size > included_body_bytes);
+ DEBUGASSERT(size > (size_t)included_body_bytes);
result = Curl_convert_to_network(data, ptr, headersize);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -1249,13 +1254,25 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
#endif
)
&& conn->httpversion != 20) {
+ /* Make sure this doesn't send more body bytes than what the max send
+ speed says. The request bytes do not count to the max speed.
+ */
+ if(data->set.max_send_speed &&
+ (included_body_bytes > data->set.max_send_speed)) {
+ curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
+ DEBUGASSERT((size_t)overflow < size);
+ sendsize = size - (size_t)overflow;
+ }
+ else
+ sendsize = size;
+
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
needs to fit into the normal read-callback buffer later on and that
buffer is using this size.
*/
-
- sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE);
+ if(sendsize > CURL_MAX_WRITE_SIZE)
+ sendsize = CURL_MAX_WRITE_SIZE;
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
library when we attempt to re-send this buffer. Sending the same data
@@ -1287,7 +1304,19 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
else
#endif
- sendsize = size;
+ {
+ /* Make sure this doesn't send more body bytes than what the max send
+ speed says. The request bytes do not count to the max speed.
+ */
+ if(data->set.max_send_speed &&
+ (included_body_bytes > data->set.max_send_speed)) {
+ curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
+ DEBUGASSERT((size_t)overflow < size);
+ sendsize = size - (size_t)overflow;
+ }
+ else
+ sendsize = size;
+ }
}
result = Curl_write(data, sockfd, ptr, sendsize, &amount);
@@ -2629,8 +2658,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
}
/* issue the request */
- result = Curl_buffer_send(r, data, &data->info.request_size,
- (size_t)included_body, FIRSTSOCKET);
+ result = Curl_buffer_send(r, data, &data->info.request_size, included_body,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP POST request");
diff --git a/lib/http.h b/lib/http.h
index 587e032cd..36e2152fe 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -58,7 +58,7 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data,
curl_off_t *bytes_written,
- size_t included_body_bytes,
+ curl_off_t included_body_bytes,
int socketindex);
#else
#define Curl_buffer_send(a,b,c,d,e) CURLE_OK