1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

- Michael Wallner provided a patch that adds support for CURLOPT_TIMEOUT_MS

and CURLOPT_CONNECTTIMEOUT_MS that, as their names should hint, do the
  timeouts with millisecond resolution instead. The only restriction to that
  is the alarm() (sometimes) used to abort name resolves as that uses full
  seconds. I fixed the FTP response timeout part of the patch.

  Internally we now count and keep the timeouts in milliseconds but it also
  means we multiply set timeouts with 1000. The effect of this is that no
  timeout can be set to more than 2^31 milliseconds (on 32 bit systems), which
  equals 24.86 days.  We probably couldn't before either since the code did
  *1000 on the timeout values on several places already.
This commit is contained in:
Daniel Stenberg 2007-02-05 22:51:32 +00:00
parent 0fc51ac5a6
commit 91386937ff
17 changed files with 98 additions and 62 deletions

13
CHANGES
View File

@ -6,6 +6,19 @@
Changelog
Daniel (5 February 2007)
- Michael Wallner added support for CURLOPT_TIMEOUT_MS and
CURLOPT_CONNECTTIMEOUT_MS that, as their names suggest, do the timeouts with
millisecond resolution. The only restriction to that is the alarm()
(sometimes) used to abort name resolves as that uses full seconds. I fixed
the FTP response timeout part of the patch.
Internally we now count and keep the timeouts in milliseconds but it also
means we multiply set timeouts with 1000. The effect of this is that no
timeout can be set to more than 2^31 milliseconds (on 32 bit systems), which
equals 24.86 days. We probably couldn't before either since the code did
*1000 on the timeout values on several places already.
Daniel (3 February 2007)
- Yang Tse fixed the cookie expiry date in several test cases that started to
fail since they used "1 feb 2007"...

View File

@ -11,7 +11,7 @@ Curl and libcurl 7.16.2
This release includes the following changes:
o
o Added CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS
This release includes the following bugfixes:
@ -33,6 +33,6 @@ New curl mirrors:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Yang Tse, Manfred Schwarb
Yang Tse, Manfred Schwarb, Michael Wallner
Thanks! (and sorry if I forgot to mention someone)

View File

@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
.TH curl_easy_setopt 3 "2 Nov 2006" "libcurl 7.16.1" "libcurl Manual"
.TH curl_easy_setopt 3 "5 Feb 2007" "libcurl 7.16.2" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@ -1078,6 +1078,10 @@ SIGALRM to enable time-outing system calls.
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_TIMEOUT_MS
Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If
libcurl is built to use the standard system name resolver, that part will
still use full-second resolution for timeouts. (Added in 7.16.2)
.IP CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second
that the transfer should be below during \fICURLOPT_LOW_SPEED_TIME\fP seconds
@ -1135,6 +1139,10 @@ timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_CONNECTTIMEOUT_MS
Like \fICURLOPT_CONNECTTIMEOUT\fP but takes number of milliseconds instead. If
libcurl is built to use the standard system name resolver, that part will
still use full-second resolution for timeouts. (Added in 7.16.2)
.IP CURLOPT_IPRESOLVE
Allows an application to select what kind of IP addresses to use when
resolving host names. This is only interesting when using host names that

View File

@ -1054,6 +1054,10 @@ typedef enum {
/* Send CCC (Clear Command Channel) after authentication */
CINIT(FTP_SSL_CCC, LONG, 154),
/* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
CINIT(TIMEOUT_MS, LONG, 155),
CINIT(CONNECTTIMEOUT_MS, LONG, 156),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -558,15 +558,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* subtract the most strict timeout of the ones */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
allow_total = allow = data->set.timeout*1000;
allow_total = allow = data->set.timeout;
else
allow = data->set.connecttimeout*1000;
allow = data->set.connecttimeout;
}
else if(data->set.timeout) {
allow_total = allow = data->set.timeout*1000;
allow_total = allow = data->set.timeout;
}
else if(data->set.connecttimeout) {
allow = data->set.connecttimeout*1000;
allow = data->set.connecttimeout;
}
if(has_passed > allow ) {
@ -826,14 +826,14 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
timeout_ms = data->set.timeout*1000;
timeout_ms = data->set.timeout;
else
timeout_ms = data->set.connecttimeout*1000;
timeout_ms = data->set.connecttimeout;
}
else if(data->set.timeout)
timeout_ms = data->set.timeout*1000;
timeout_ms = data->set.timeout;
else
timeout_ms = data->set.connecttimeout*1000;
timeout_ms = data->set.connecttimeout;
/* subtract the passed time */
timeout_ms -= has_passed;

View File

@ -184,7 +184,7 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
struct SessionHandle *data = conn->data;
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
struct timeval now = Curl_tvnow();
long timespent = Curl_tvdiff(Curl_tvnow(), now)/1000;
long timespent = Curl_tvdiff(Curl_tvnow(), now);
long timeout = data->set.connecttimeout?data->set.connecttimeout:
(data->set.timeout?data->set.timeout: 0);
@ -198,7 +198,7 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
/* We allow the server 60 seconds to connect to us, or a custom timeout.
Note the typecast here. */
timeout_ms = (timeout?(int)timeout:60) * 1000;
timeout_ms = (timeout?(int)timeout:60000);
switch (Curl_select(sock, CURL_SOCKET_BAD, timeout_ms)) {
case -1: /* error */
@ -444,7 +444,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
bool keepon=TRUE;
ssize_t gotbytes;
char *ptr;
long timeout; /* timeout in seconds */
long timeout; /* timeout in milliseconds */
int interval_ms;
struct SessionHandle *data = conn->data;
char *line_start;
@ -473,16 +473,16 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
the response for any given ftp response, not for the time
from connect to the given ftp response. */
timeout = data->set.ftp_response_timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
Curl_tvdiff(Curl_tvnow(), now); /* spent time */
else if(data->set.timeout)
/* if timeout is requested, find out how much remaining time we have */
timeout = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
else
/* Even without a requested timeout, we only wait response_time
seconds for the full response to arrive before we bail out */
timeout = ftpc->response_time -
Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
Curl_tvdiff(Curl_tvnow(), now); /* spent time */
if(timeout <=0 ) {
failf(data, "FTP response timeout");
@ -491,6 +491,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
if(!ftpc->cache) {
interval_ms = 1 * 1000; /* use 1 second timeout intervals */
if(timeout < interval_ms)
interval_ms = timeout;
switch (Curl_select(sockfd, CURL_SOCKET_BAD, interval_ms)) {
case -1: /* select() error, stop reading */
@ -2751,16 +2753,16 @@ static long ftp_state_timeout(struct connectdata *conn)
time. Also, use ftp->response because FTP_RESPONSE_TIMEOUT is supposed
to govern the response for any given ftp response, not for the time
from connect to the given ftp response. */
timeout_ms = data->set.ftp_response_timeout*1000 - /* timeout time */
timeout_ms = data->set.ftp_response_timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), ftpc->response); /* spent time */
else if(data->set.timeout)
/* if timeout is requested, find out how much remaining time we have */
timeout_ms = data->set.timeout*1000 - /* timeout time */
timeout_ms = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
else
/* Without a requested timeout, we only wait 'response_time' seconds for
the full response to arrive before we bail out */
timeout_ms = ftpc->response_time*1000 -
timeout_ms = ftpc->response_time -
Curl_tvdiff(Curl_tvnow(), ftpc->response); /* spent time */
return timeout_ms;
@ -2904,7 +2906,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
/* We always support persistant connections on ftp */
conn->bits.close = FALSE;
ftpc->response_time = 3600; /* set default response time-out */
ftpc->response_time = 3600000; /* set default response time-out */
#ifndef CURL_DISABLE_HTTP
if (conn->bits.tunnel_proxy && conn->bits.httpproxy) {
@ -3063,7 +3065,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature
*/
long old_time = ftpc->response_time;
ftpc->response_time = 60; /* give it only a minute for now */
ftpc->response_time = 60000; /* give it only a minute for now */
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);

View File

@ -144,12 +144,12 @@ static CURLcode handshake(struct connectdata *conn,
long has_passed;
if(duringconnect && data->set.connecttimeout)
timeout_ms = data->set.connecttimeout*1000;
timeout_ms = data->set.connecttimeout;
if(data->set.timeout) {
/* get the strictest timeout of the ones converted to milliseconds */
if((data->set.timeout*1000) < timeout_ms)
timeout_ms = data->set.timeout*1000;
if(data->set.timeout) < timeout_ms)
timeout_ms = data->set.timeout;
}
/* Evaluate in milliseconds how much time that has passed */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -183,7 +183,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
{
CURLcode rc=CURLE_OK;
struct SessionHandle *data = conn->data;
long timeout = CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
long timeout;
/* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */
@ -191,14 +191,8 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
timeout = conn->data->set.connecttimeout;
else if(conn->data->set.timeout)
timeout = conn->data->set.timeout;
/* We convert the number of seconds into number of milliseconds here: */
if(timeout < 2147483)
/* maximum amount of seconds that can be multiplied with 1000 and
still fit within 31 bits */
timeout *= 1000;
else
timeout = 0x7fffffff; /* ridiculous amount of time anyway */
timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
/* Wait for the name resolve query to complete. */
while (1) {

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -600,7 +600,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
ticks = GetTickCount();
/* wait for the thread to resolve the name */
status = WaitForSingleObject(td->event_resolved, 1000UL*timeout);
status = WaitForSingleObject(td->event_resolved, timeout);
/* mark that we are now done waiting */
ReleaseMutex(td->mutex_waiting);

View File

@ -1121,7 +1121,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
ssize_t gotbytes;
char *ptr;
long timeout =
data->set.timeout?data->set.timeout:3600; /* in seconds */
data->set.timeout?data->set.timeout:3600000; /* in milliseconds */
char *line_start;
char *host_port;
curl_socket_t tunnelsocket = conn->sock[sockindex];
@ -1225,15 +1225,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* if timeout is requested, find out how much remaining time we have */
long check = timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
if(check <=0 ) {
Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
if(check <= 0) {
failf(data, "Proxy CONNECT aborted due to timeout");
error = SELECT_TIMEOUT; /* already too little time */
break;
}
/* timeout each second and check the timeout */
switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD, 1000)) {
/* loop every second at least, less if the timeout is near */
switch (Curl_select(tunnelsocket, CURL_SOCKET_BAD,
check<1000?check:1000)) {
case -1: /* select() error, stop reading */
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted due to select() error");

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -120,14 +120,14 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* get timeout */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
timeout = data->set.timeout*1000;
timeout = data->set.timeout;
else
timeout = data->set.connecttimeout*1000;
timeout = data->set.connecttimeout;
}
else if(data->set.timeout)
timeout = data->set.timeout*1000;
timeout = data->set.timeout;
else if(data->set.connecttimeout)
timeout = data->set.connecttimeout*1000;
timeout = data->set.connecttimeout;
else
timeout = DEFAULT_CONNECT_TIMEOUT;

View File

@ -1459,17 +1459,17 @@ Curl_ossl_connect_step2(struct connectdata *conn,
if(data->set.timeout && data->set.connecttimeout) {
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout<data->set.connecttimeout)
*timeout_ms = data->set.timeout*1000;
*timeout_ms = data->set.timeout;
else
*timeout_ms = data->set.connecttimeout*1000;
*timeout_ms = data->set.connecttimeout;
}
else if(data->set.timeout)
*timeout_ms = data->set.timeout*1000;
*timeout_ms = data->set.timeout;
else if(data->set.connecttimeout)
*timeout_ms = data->set.connecttimeout*1000;
*timeout_ms = data->set.connecttimeout;
else
/* no particular time-out has been set */
*timeout_ms= DEFAULT_CONNECT_TIMEOUT;
*timeout_ms = DEFAULT_CONNECT_TIMEOUT;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);

View File

@ -1387,7 +1387,7 @@ CURLcode Curl_telnet(struct connectdata *conn, bool *done)
if(data->set.timeout) {
struct timeval now; /* current time */
now = Curl_tvnow();
if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) {
if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
failf(data, "Time-out");
code = CURLE_OPERATION_TIMEOUTED;
keepon = FALSE;

View File

@ -195,7 +195,7 @@ void tftp_set_timeouts(tftp_state_data_t *state)
else {
/* Compute drop-dead time */
maxtime = (time_t)(data->set.timeout?data->set.timeout:3600);
maxtime = (time_t)(data->set.timeout?data->set.timeout/1000L:3600);
state->max_time = state->start_time+maxtime;
/* Set per-block timeout to 10% of total */

View File

@ -1547,13 +1547,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
return result;
if (data->set.timeout &&
((Curl_tvdiff(k->now, k->start)/1000) >= data->set.timeout)) {
(Curl_tvdiff(k->now, k->start) >= data->set.timeout)) {
if (k->size != -1) {
failf(data, "Operation timed out after %d seconds with %"
failf(data, "Operation timed out after %d milliseconds with %"
FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received",
data->set.timeout, k->bytecount, k->size);
} else {
failf(data, "Operation timed out after %d seconds with %"
failf(data, "Operation timed out after %d milliseconds with %"
FORMAT_OFF_T " bytes received",
data->set.timeout, k->bytecount);
}

View File

@ -734,7 +734,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* An FTP option that specifies how quickly an FTP response must be
* obtained before it is considered failure.
*/
data->set.ftp_response_timeout = va_arg( param , long );
data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
break;
case CURLOPT_FTPLISTONLY:
/*
@ -1242,12 +1242,21 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* The maximum time you allow curl to use for a single transfer
* operation.
*/
data->set.timeout = va_arg(param, long) * 1000L;
break;
case CURLOPT_TIMEOUT_MS:
data->set.timeout = va_arg(param, long);
break;
case CURLOPT_CONNECTTIMEOUT:
/*
* The maximum time you allow curl to use to connect.
*/
data->set.connecttimeout = va_arg(param, long) * 1000L;
break;
case CURLOPT_CONNECTTIMEOUT_MS:
data->set.connecttimeout = va_arg(param, long);
break;
@ -3828,9 +3837,14 @@ else {
/* if timeout is not set, use the connect timeout */
shortest = data->set.connecttimeout;
if(shortest < 1000)
/* the alarm() function only provide integer second resolution, so if
we want to wait less than one second we must bail out already now. */
return CURLE_OPERATION_TIMEDOUT;
/* alarm() makes a signal get sent when the timeout fires off, and that
will abort system calls */
prev_alarm = alarm((unsigned int) shortest);
prev_alarm = alarm((unsigned int) (shortest ? shortest/1000L : shortest));
/* We can expect the conn->created time to be "now", as that was just
recently set in the beginning of this function and nothing slow
has been done since then until now. */

View File

@ -1176,9 +1176,9 @@ struct UserDefined {
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
long timeout; /* in seconds, 0 means no timeout */
long connecttimeout; /* in seconds, 0 means no timeout */
long ftp_response_timeout; /* in seconds, 0 means no timeout */
long timeout; /* in milliseconds, 0 means no timeout */
long connecttimeout; /* in milliseconds, 0 means no timeout */
long ftp_response_timeout; /* in milliseconds, 0 means no timeout */
curl_off_t infilesize; /* size of file to upload, -1 means unknown */
long low_speed_limit; /* bytes/second */
long low_speed_time; /* number of seconds */