aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/multi.c31
-rw-r--r--lib/progress.c74
-rw-r--r--lib/progress.h1
3 files changed, 62 insertions, 44 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 98e5fca2a..69df90288 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1823,22 +1823,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
- send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now);
+ send_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
- recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now);
-
- if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
+ recv_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+
+ if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
+ Curl_ratelimit(data, now);
+ }
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
@@ -1870,7 +1874,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_start,
now);
- if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
+ if(send_timeout_ms || recv_timeout_ms) {
+ Curl_ratelimit(data, now);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
diff --git a/lib/progress.c b/lib/progress.c
index ce8be7ffb..f59faa3d3 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -28,6 +28,9 @@
#include "progress.h"
#include "curl_printf.h"
+/* check rate limits within this many recent milliseconds, at minimum. */
+#define MIN_RATE_LIMIT_PERIOD 3000
+
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
static void time2str(char *r, curl_off_t seconds)
@@ -235,6 +238,7 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+ Curl_ratelimit(data, data->progress.start);
}
/*
@@ -265,13 +269,13 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
time_t minimum;
time_t actual;
- /* we don't have a starting point yet -- return 0 so it gets (re)set */
- if(start.tv_sec == 0 && start.tv_usec == 0)
- return 0;
-
- if(!limit)
+ if(!limit || !size)
return 0;
+ /*
+ * 'minimum' is the number of milliseconds 'size' should take to download to
+ * stay below 'limit'.
+ */
if(size < CURL_OFF_T_MAX/1000)
minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
else {
@@ -282,48 +286,56 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
minimum = TIME_T_MAX;
}
+ /*
+ * 'actual' is the time in milliseconds it took to actually download the
+ * last 'size' bytes.
+ */
actual = Curl_timediff(now, start);
-
- if(actual < minimum)
+ if(actual < minimum) {
+ /* if it downloaded the data faster than the limit, make it wait the
+ difference */
return (minimum - actual);
+ }
return 0;
}
+/*
+ * Set the number of downloaded bytes so far.
+ */
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.downloaded = size;
+}
- /* download speed limit */
- if((data->set.max_recv_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now) == 0)) {
- data->progress.dl_limit_start = now;
- data->progress.dl_limit_size = size;
+/*
+ * Update the timestamp and sizestamp to use for rate limit calculations.
+ */
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
+{
+ /* don't set a new stamp unless the time since last update is long enough */
+ if(data->set.max_recv_speed > 0) {
+ if(Curl_timediff(now, data->progress.dl_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.dl_limit_start = now;
+ data->progress.dl_limit_size = data->progress.downloaded;
+ }
+ }
+ if(data->set.max_send_speed > 0) {
+ if(Curl_timediff(now, data->progress.ul_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.ul_limit_start = now;
+ data->progress.ul_limit_size = data->progress.uploaded;
+ }
}
}
+/*
+ * Set the number of uploaded bytes so far.
+ */
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.uploaded = size;
-
- /* upload speed limit */
- if((data->set.max_send_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now) == 0)) {
- data->progress.ul_limit_start = now;
- data->progress.ul_limit_size = size;
- }
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
diff --git a/lib/progress.h b/lib/progress.h
index 3c2231cb6..2baa925db 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -46,6 +46,7 @@ void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);