* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
#include "urldata.h"
#include "sendf.h"
#include "progress.h"
-
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
+#include "curl_printf.h"
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
int Curl_pgrsDone(struct connectdata *conn)
{
int rc;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
data->progress.lastshow=0;
rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
if(rc)
}
/* reset all times except redirect, and reset the known transfer sizes */
-void Curl_pgrsResetTimesSizes(struct SessionHandle *data)
+void Curl_pgrsResetTimesSizes(struct Curl_easy *data)
{
data->progress.t_nslookup = 0.0;
data->progress.t_connect = 0.0;
Curl_pgrsSetUploadSize(data, -1);
}
-void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
+void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
{
struct timeval now = Curl_tvnow();
}
}
-void Curl_pgrsStartNow(struct SessionHandle *data)
+void Curl_pgrsStartNow(struct Curl_easy *data)
{
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow();
+ data->progress.ul_limit_start.tv_sec = 0;
+ data->progress.ul_limit_start.tv_usec = 0;
+ data->progress.dl_limit_start.tv_sec = 0;
+ data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
}
-void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
+/*
+ * This is used to handle speed limits, calculating how much milliseconds we
+ * need to wait until we're back under the speed limit, if needed.
+ *
+ * The way it works is by having a "starting point" (time & amount of data
+ * transfered by then) used in the speed computation, to be used instead of the
+ * start of the transfer.
+ * This starting point is regularly moved as transfer goes on, to keep getting
+ * accurate values (instead of average over the entire tranfer).
+ *
+ * This function takes the current amount of data transfered, the amount at the
+ * starting point, the limit (in bytes/s), the time of the starting point and
+ * the current time.
+ *
+ * Returns -1 if no waiting is needed (not enough data transfered since
+ * starting point yet), 0 when no waiting is needed but the starting point
+ * should be reset (to current), or the number of milliseconds to wait to get
+ * back under the speed limit.
+ */
+long Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct timeval start,
+ struct timeval now)
+{
+ curl_off_t size = cursize - startsize;
+ 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;
+
+ /* not enough data yet */
+ if(size < limit)
+ return -1;
+
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ actual = Curl_tvdiff(now, start);
+
+ if(actual < minimum)
+ /* this is a conversion on some systems (64bit time_t => 32bit long) */
+ return (long)(minimum - actual);
+ else
+ return 0;
+}
+
+void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
+ struct timeval now = Curl_tvnow();
+
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;
+ }
}
-void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size)
+void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
+ struct timeval now = Curl_tvnow();
+
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 SessionHandle *data, curl_off_t size)
+void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
{
if(size >= 0) {
data->progress.size_dl = size;
}
}
-void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size)
+void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
{
if(size >= 0) {
data->progress.size_ul = size;
curl_off_t total_transfer;
curl_off_t total_expected_transfer;
curl_off_t timespent;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex;
int countindex; /* amount of seconds stored in the speeder array */
now = Curl_tvnow(); /* what time is it */
/* The time spent so far (from the start) */
- data->progress.timespent =
- (double)(now.tv_sec - data->progress.start.tv_sec) +
- (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+ data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start);
timespent = (curl_off_t)data->progress.timespent;
/* The average download speed this far */
(data->progress.timespent>0?data->progress.timespent:1));
/* Calculations done at most once a second, unless end is reached */
- if(data->progress.lastshow != (long)now.tv_sec) {
+ if(data->progress.lastshow != now.tv_sec) {
shownow = TRUE;
data->progress.lastshow = now.tv_sec;
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
- long span_ms;
+ time_t span_ms;
/* Get the index position to compare with the 'nowindex' position.
Get the oldest entry possible. While we have less than CURR_TIME