Commit 2d5711dc authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

low_speed_limit: improved function for longer time periods

Previously, periods of fast speed between periods of slow speed would
not count and could still erroneously trigger a timeout.

Reported-by: Paul Harris
Fixes #1345
Closes #1390
parent ae485279
Loading
Loading
Loading
Loading
+30 −29
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *                             \___|\___/|_| \_\_____|
 *
 *
 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 *
 * This software is licensed as described in the file COPYING, which
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * you should have received as part of this distribution. The terms
@@ -33,21 +33,23 @@ void Curl_speedinit(struct Curl_easy *data)
  memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
  memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
}
}


/*
 * @unittest: 1606
 */
CURLcode Curl_speedcheck(struct Curl_easy *data,
CURLcode Curl_speedcheck(struct Curl_easy *data,
                         struct timeval now)
                         struct timeval now)
{
{
  if((data->progress.current_speed >= 0) &&
  if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
     data->set.low_speed_time &&
    if(data->progress.current_speed < data->set.low_speed_limit) {
     (Curl_tvlong(data->state.keeps_speed) != 0) &&
      if(!data->state.keeps_speed.tv_sec)
     (data->progress.current_speed < data->set.low_speed_limit)) {
        /* under the limit at this very moment */
        data->state.keeps_speed = now;
      else {
        /* how long has it been under the limit */
        time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
        time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
    time_t nextcheck = (data->set.low_speed_time * 1000) - howlong;


    /* We are now below the "low speed limit". If we are below it
        if(howlong >= data->set.low_speed_time * 1000) {
       for "low speed time" seconds we consider that enough reason
          /* too long */
       to abort the download. */
    if(nextcheck <= 0) {
      /* we have been this slow for long enough, now die */
          failf(data,
          failf(data,
                "Operation too slow. "
                "Operation too slow. "
                "Less than %ld bytes/sec transferred the last %ld seconds",
                "Less than %ld bytes/sec transferred the last %ld seconds",
@@ -55,18 +57,17 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
                data->set.low_speed_time);
                data->set.low_speed_time);
          return CURLE_OPERATION_TIMEDOUT;
          return CURLE_OPERATION_TIMEDOUT;
        }
        }
    /* wait complete low_speed_time */
    Curl_expire_latest(data, nextcheck);
      }
      }
  else {
    }
    /* we keep up the required speed all right */
    else
    data->state.keeps_speed = now;
      /* faster right now */
      data->state.keeps_speed.tv_sec = 0;
  }


  if(data->set.low_speed_limit)
  if(data->set.low_speed_limit)
      /* if there is a low speed limit enabled, we set the expire timer to
    /* if low speed limit is enabled, set the expire timer to make this
         make this connection's speed get checked again no later than when
       connection's speed get checked again in a second */
         this time is up */
    Curl_expire_latest(data, 1000);
      Curl_expire_latest(data, data->set.low_speed_time*1000);

  }
  return CURLE_OK;
  return CURLE_OK;
}
}