diff options
-rw-r--r-- | CHANGES | 13 | ||||
-rw-r--r-- | RELEASE-NOTES | 4 | ||||
-rw-r--r-- | docs/libcurl/curl_easy_setopt.3 | 10 | ||||
-rw-r--r-- | include/curl/curl.h | 4 | ||||
-rw-r--r-- | lib/connect.c | 18 | ||||
-rw-r--r-- | lib/ftp.c | 24 | ||||
-rw-r--r-- | lib/gtls.c | 6 | ||||
-rw-r--r-- | lib/hostares.c | 12 | ||||
-rw-r--r-- | lib/hostthre.c | 4 | ||||
-rw-r--r-- | lib/http.c | 11 | ||||
-rw-r--r-- | lib/socks.c | 10 | ||||
-rw-r--r-- | lib/ssluse.c | 10 | ||||
-rw-r--r-- | lib/telnet.c | 2 | ||||
-rw-r--r-- | lib/tftp.c | 2 | ||||
-rw-r--r-- | lib/transfer.c | 6 | ||||
-rw-r--r-- | lib/url.c | 18 | ||||
-rw-r--r-- | lib/urldata.h | 6 |
17 files changed, 98 insertions, 62 deletions
@@ -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"... diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 3c5e860ad..bbe226975 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -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) diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index 08e7405e2..23d012de9 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -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 diff --git a/include/curl/curl.h b/include/curl/curl.h index f41067614..2c79f7dac 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -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; diff --git a/lib/connect.c b/lib/connect.c index 2b3897204..37db6e228 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -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; @@ -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); diff --git a/lib/gtls.c b/lib/gtls.c index 250ecada4..977263b12 100644 --- a/lib/gtls.c +++ b/lib/gtls.c @@ -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 */ diff --git a/lib/hostares.c b/lib/hostares.c index 1db0f4320..2738edcdf 100644 --- a/lib/hostares.c +++ b/lib/hostares.c @@ -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) { diff --git a/lib/hostthre.c b/lib/hostthre.c index 12e31ea34..f88bf15ec 100644 --- a/lib/hostthre.c +++ b/lib/hostthre.c @@ -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); diff --git a/lib/http.c b/lib/http.c index c07053bdd..ad42273cd 100644 --- a/lib/http.c +++ b/lib/http.c @@ -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"); diff --git a/lib/socks.c b/lib/socks.c index 3319e697e..32d0c4b54 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -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; diff --git a/lib/ssluse.c b/lib/ssluse.c index 55afb2446..4f5b7f94d 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -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); diff --git a/lib/telnet.c b/lib/telnet.c index 97d22b788..14501c624 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -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; diff --git a/lib/tftp.c b/lib/tftp.c index 2a28b0cb9..b1a34a5df 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -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 */ diff --git a/lib/transfer.c b/lib/transfer.c index bff16b4ff..91e468b64 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -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); } @@ -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. */ diff --git a/lib/urldata.h b/lib/urldata.h index 3bb3327ba..acc9d1ba6 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -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 */ |