7.12 FTPS directory listing hangs on Windows with Schannel
8. TELNET
- 8.1 TELNET and time limitations do not work
8.2 Microsoft telnet server
9. SFTP and SCP
8. TELNET
-8.1 TELNET and time limitations do not work
-
- When using telnet, the time limitation options do not work.
- https://curl.se/bug/view.cgi?id=846
-
8.2 Microsoft telnet server
There seems to be a problem when connecting to the Microsoft telnet server.
***************************************************************************/
#include "tool_setup.h"
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_cb_rea.h"
#include "tool_operate.h"
+#include "tool_util.h"
#include "memdebug.h" /* keep this as LAST include */
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
{
- ssize_t rc;
+ ssize_t rc = 0;
struct InStruct *in = userdata;
+ struct OperationConfig *config = in->config;
+
+ if(config->timeout_ms) {
+ struct timeval now = tvnow();
+ long msdelta = tvdiff(now, in->per->start);
+
+ if(msdelta > config->timeout_ms)
+ /* timeout */
+ return 0;
+#ifndef WIN32
+ /* this logic waits on read activity on a file descriptor that is not a
+ socket which makes it not work with select() on Windows */
+ else {
+ fd_set bits;
+ struct timeval timeout;
+ long wait = config->timeout_ms - msdelta;
+
+ /* wait this long at the most */
+ timeout.tv_sec = wait/1000;
+ timeout.tv_usec = (wait%1000)*1000;
+
+ FD_ZERO(&bits);
+ FD_SET(in->fd, &bits);
+ if(!select(in->fd + 1, &bits, NULL, NULL, &timeout))
+ return 0; /* timeout */
+ }
+#endif
+ }
rc = read(in->fd, buffer, sz*nmemb);
if(rc < 0) {
rc = 0;
}
in->config->readbusy = FALSE;
+
+ /* when select() rerturned zero here, it timed out */
return (size_t)rc;
}
char *postfields;
curl_off_t postfieldsize;
char *referer;
- double timeout;
- double connecttimeout;
+ long timeout_ms;
+ long connecttimeout_ms;
long maxredirs;
curl_off_t max_filesize;
char *output_dir;
bool abstract_unix_socket; /* path to an abstract Unix domain socket */
bool falsestart;
bool path_as_is;
- double expect100timeout;
+ long expect100timeout_ms;
bool suppress_connect_headers; /* suppress proxy CONNECT response headers
from user callbacks */
bool synthetic_error; /* if TRUE, this is tool-internal error */
config->authtype |= CURLAUTH_BEARER;
break;
case 'c': /* connect-timeout */
- err = str2udouble(&config->connecttimeout, nextarg,
- (double)LONG_MAX/1000);
+ err = secs2ms(&config->connecttimeout_ms, nextarg);
if(err)
return err;
break;
return err;
break;
case 'R': /* --expect100-timeout */
- err = str2udouble(&config->expect100timeout, nextarg,
- (double)LONG_MAX/1000);
+ err = secs2ms(&config->expect100timeout_ms, nextarg);
if(err)
return err;
break;
break;
case 'm':
/* specified max time */
- err = str2udouble(&config->timeout, nextarg, (double)LONG_MAX/1000);
+ err = secs2ms(&config->timeout_ms, nextarg);
if(err)
return err;
break;
}
per->input.fd = per->infd;
}
+ per->start = tvnow();
return result;
}
/* for uploads */
input->config = config;
+ input->per = per;
/* Note that if CURLOPT_READFUNCTION is fread (the default), then
* lib/telnet.c will Curl_poll() on the input file descriptor
* rather than calling the READFUNCTION at regular intervals.
per->errorbuffer = global_errorbuffer;
my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
}
- my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
switch(config->httpreq) {
case HTTPREQ_SIMPLEPOST:
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
/* new in libcurl 7.7: */
- my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
- (long)(config->connecttimeout * 1000));
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
if(config->doh_url)
my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
/* new in 7.47.0 */
- if(config->expect100timeout > 0)
+ if(config->expect100timeout_ms > 0)
my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
- (long)(config->expect100timeout*1000));
+ config->expect100timeout_ms);
/* new in 7.48.0 */
if(config->tftp_no_options && proto_tftp)
bool retry;
long delay_ms;
bool bailout = FALSE;
- struct timeval start;
result = pre_transfer(global, per);
if(result)
break;
break;
}
- start = tvnow();
#ifdef CURLDEBUG
if(global->test_event_based)
result = curl_easy_perform_ev(per->curl);
if(per && global->ms_per_transfer) {
/* how long time did the most recent transfer take in number of
milliseconds */
- long milli = tvdiff(tvnow(), start);
+ long milli = tvdiff(tvnow(), per->start);
if(milli < global->ms_per_transfer) {
notef(global, "Transfer took %ld ms, waits %ldms as set by --rate\n",
milli, global->ms_per_transfer - milli);
long retry_numretries;
long retry_sleep_default;
long retry_sleep;
+ struct timeval start; /* start of this transfer */
struct timeval retrystart;
char *this_url;
unsigned int urlnum; /* the index of the given URL */
}
/*
- * Parse the string and write the double in the given address. Return PARAM_OK
- * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ * Parse the string as seconds with decimals, and write the number of
+ * milliseconds that corresponds in the given address. Return PARAM_OK on
+ * success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
*
* The 'max' argument is the maximum value allowed, as the numbers are often
* multiplied when later used.
* data.
*/
-ParameterError str2udouble(double *valp, const char *str, double max)
+ParameterError secs2ms(long *valp, const char *str)
{
double value;
- ParameterError result = str2double(&value, str, max);
+ ParameterError result = str2double(&value, str, (double)LONG_MAX/1000);
if(result != PARAM_OK)
return result;
if(value < 0)
return PARAM_NEGATIVE_NUMERIC;
- *valp = value;
+ *valp = (long)(value*1000);
return PARAM_OK;
}
ParameterError str2unum(long *val, const char *str);
ParameterError oct2nummax(long *val, const char *str, long max);
ParameterError str2unummax(long *val, const char *str, long max);
-ParameterError str2udouble(double *val, const char *str, double max);
+ParameterError secs2ms(long *val, const char *str);
ParameterError proto2num(struct OperationConfig *config,
const char * const *val, char **obuf,
struct InStruct {
int fd;
struct OperationConfig *config;
+ struct per_transfer *per;
};