]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: cap body data amount during send speed limiting
authorDaniel Stenberg <daniel@haxx.se>
Fri, 26 Mar 2021 09:06:51 +0000 (10:06 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 27 Mar 2021 11:38:15 +0000 (12:38 +0100)
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
Closes #6797

lib/http.c
lib/http.h

index 51254201c3b3f2820fa8f5acce0dddafab305e0c..a0da9eadeb856d931b549100030d4afff5e20bfe 100644 (file)
@@ -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");
index 587e032cd68e28f00ccac805c7582cfbd49f83ec..36e2152fe309eb6518fda89088c31ea222ece9cc 100644 (file)
@@ -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