mirror of
https://github.com/libssh2/libssh2.git
synced 2026-10-24 03:48:58 +03:00
src: use abstract internal time type, bump resolution to milliseconds
To honor the actual millisecond timeout set via `libssh2_session_set_timeout()`, to open the possibility for the same in other APIs, and to use monotonic time if available. - add internal abstract time types and macros for handling point in time and time intervals, and use them throughout the codebase. - bump internal abstract time resolution to milliseconds (from seconds). Use signed 64-bit integers. - replace existing millisecond-resolution code in `libssh2_poll()` with the internal abstract time interface. - bump 'now' function to retrieve millisecond-resolution monotonic time from the system, if available. Also: - append `_s` or `_ms` to public API arguments to tell the time unit. - keepalive: minor tidy-ups. - make `ssh2_now()` return at least 1 in the fallback, `time(NULL)`-based codepath to not confuse a zero value with unset time. Credits: Stefan Eissing Ref:5649b21297Ref: https://github.com/curl/curl/pull/21034 - this leaves existing `ssh2_gettimeofday()` (together with its Windows-specific local implementation) with a single caller, `ssh2_deb_low()`. Refs: https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html https://www.man7.org/linux/man-pages/man3/clock_gettime.3.html https://pubs.opengroup.org/onlinepubs/009604599/functions/gettimeofday.html https://www.man7.org/linux/man-pages/man2/gettimeofday.2.html https://learn.microsoft.com/windows/win32/api/profileapi/nf-profileapi-queryperformancefrequency https://learn.microsoft.com/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows Reported-and-patch-proposal-by: Trzik on github Based-on-patch-proposals-by: Ryan Kelley Fixes #1497 Ref: #1818 Closes #1893 Follow-up to772abc7a85#1919 Closes #2341
This commit is contained in:
@@ -19,16 +19,16 @@ libssh2_keepalive_config - short function description
|
||||
|
||||
void libssh2_keepalive_config(LIBSSH2_SESSION *session,
|
||||
int want_reply,
|
||||
unsigned int interval);
|
||||
unsigned int interval_s);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Set how often keepalive messages should be sent. **want_reply** indicates
|
||||
whether the keepalive messages should request a response from the server.
|
||||
**interval** is number of seconds that can pass without any I/O, use 0 (the
|
||||
**interval_s** is number of seconds that can pass without any I/O, use 0 (the
|
||||
default) to disable keepalives. To avoid some busy-loop corner-cases, if you
|
||||
specify an interval of 1 it is treated as 2.
|
||||
specify an **interval_s** of 1 it is treated as 2.
|
||||
|
||||
Note that non-blocking applications are responsible for sending the keepalive
|
||||
messages using **libssh2_keepalive_send(3)**.
|
||||
|
||||
@@ -17,7 +17,7 @@ libssh2_poll - poll for activity on a socket, channel or listener
|
||||
~~~c
|
||||
#include <libssh2.h>
|
||||
|
||||
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
|
||||
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout_ms);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
@@ -17,12 +17,13 @@ libssh2_session_set_read_timeout - set timeout for packet read functions
|
||||
~~~c
|
||||
#include <libssh2.h>
|
||||
|
||||
void libssh2_session_set_read_timeout(LIBSSH2_SESSION *session, long timeout);
|
||||
void libssh2_session_set_read_timeout(LIBSSH2_SESSION *session,
|
||||
long timeout_s);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Set the **timeout** in seconds for how long libssh2 packet read
|
||||
Set the **timeout_s** in seconds for how long libssh2 packet read
|
||||
function calls may wait until they consider the situation an error and return
|
||||
LIBSSH2_ERROR_TIMEOUT.
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ libssh2_session_set_timeout - set timeout for blocking functions
|
||||
~~~c
|
||||
#include <libssh2.h>
|
||||
|
||||
void libssh2_session_set_timeout(LIBSSH2_SESSION *session, long timeout);
|
||||
void libssh2_session_set_timeout(LIBSSH2_SESSION *session, long timeout_ms);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Set the **timeout** in milliseconds for how long a blocking the libssh2
|
||||
function calls may wait until they consider the situation an error and return
|
||||
Set the **timeout_ms** in milliseconds for how long a blocking libssh2 function
|
||||
call may wait before it considers the situation an error and returns
|
||||
LIBSSH2_ERROR_TIMEOUT.
|
||||
|
||||
By default or if you set the timeout to zero, libssh2 has no timeout for
|
||||
|
||||
@@ -781,7 +781,7 @@ LIBSSH2_API int libssh2_sign_sk(LIBSSH2_SESSION *session,
|
||||
#ifndef LIBSSH2_NO_DEPRECATED
|
||||
LIBSSH2_DEPRECATED(1.2.0, "Use system poll() or select()")
|
||||
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds,
|
||||
long timeout);
|
||||
long timeout_ms);
|
||||
#endif
|
||||
|
||||
/* Channel API */
|
||||
@@ -957,11 +957,11 @@ LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel,
|
||||
int blocking);
|
||||
|
||||
LIBSSH2_API void libssh2_session_set_timeout(LIBSSH2_SESSION *session,
|
||||
long timeout);
|
||||
long timeout_ms);
|
||||
LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION *session);
|
||||
|
||||
LIBSSH2_API void libssh2_session_set_read_timeout(LIBSSH2_SESSION *session,
|
||||
long timeout);
|
||||
long timeout_s);
|
||||
LIBSSH2_API long libssh2_session_get_read_timeout(LIBSSH2_SESSION *session);
|
||||
|
||||
#ifndef LIBSSH2_NO_DEPRECATED
|
||||
@@ -1430,7 +1430,7 @@ LIBSSH2_API const char *libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent);
|
||||
*/
|
||||
LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session,
|
||||
int want_reply,
|
||||
unsigned int interval);
|
||||
unsigned int interval_s);
|
||||
|
||||
/*
|
||||
* libssh2_keepalive_send()
|
||||
|
||||
@@ -37,21 +37,21 @@
|
||||
|
||||
void libssh2_keepalive_config(LIBSSH2_SESSION *session,
|
||||
int want_reply,
|
||||
unsigned int interval)
|
||||
unsigned int interval_s)
|
||||
{
|
||||
if(!session)
|
||||
return;
|
||||
|
||||
if(interval == 1)
|
||||
session->keepalive_interval = 2;
|
||||
if(interval_s == 1)
|
||||
session->keepalive_interval = ssh2_sec_to_timediff(2);
|
||||
else
|
||||
session->keepalive_interval = interval;
|
||||
session->keepalive_interval = ssh2_sec_to_timediff(interval_s);
|
||||
session->keepalive_want_reply = want_reply ? 1 : 0;
|
||||
}
|
||||
|
||||
int libssh2_keepalive_send(LIBSSH2_SESSION *session, int *seconds_to_next)
|
||||
{
|
||||
time_t now;
|
||||
ssh2_time_t now;
|
||||
|
||||
if(!session)
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
@@ -62,9 +62,9 @@ int libssh2_keepalive_send(LIBSSH2_SESSION *session, int *seconds_to_next)
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
now = ssh2_now();
|
||||
|
||||
if(session->keepalive_last_sent + session->keepalive_interval <= now) {
|
||||
if(now >= session->keepalive_last_sent + session->keepalive_interval) {
|
||||
/* Format is
|
||||
"SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
|
||||
unsigned char keepalive_data[] =
|
||||
@@ -84,12 +84,14 @@ int libssh2_keepalive_send(LIBSSH2_SESSION *session, int *seconds_to_next)
|
||||
}
|
||||
|
||||
session->keepalive_last_sent = now;
|
||||
if(seconds_to_next)
|
||||
*seconds_to_next = session->keepalive_interval;
|
||||
}
|
||||
else if(seconds_to_next)
|
||||
*seconds_to_next = (int)(session->keepalive_last_sent - now) +
|
||||
session->keepalive_interval;
|
||||
|
||||
if(seconds_to_next) {
|
||||
ssh2_timediff_t to_next = ssh2_timediff_to_sec(
|
||||
session->keepalive_interval +
|
||||
(session->keepalive_last_sent - now));
|
||||
*seconds_to_next = (int)SSH2_MIN(to_next, INT_MAX);
|
||||
}
|
||||
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -300,13 +300,21 @@ typedef enum {
|
||||
ssh2_NB_state_jumpauthagent
|
||||
} ssh2_NB_states;
|
||||
|
||||
#define ssh2_time_t libssh2_int64_t /* ms */
|
||||
#define ssh2_timediff_t libssh2_int64_t /* ms */
|
||||
#define ssh2_sec_to_timediff(sec) ((ssh2_time_t)(sec) * 1000)
|
||||
#define ssh2_timediff_to_sec(td) ((td) / 1000)
|
||||
#define ssh2_ms_to_timediff(ms) ((ssh2_time_t)(ms))
|
||||
#define ssh2_timediff_to_ms(td) (td)
|
||||
ssh2_time_t ssh2_now(void);
|
||||
|
||||
struct packet_require_state {
|
||||
ssh2_NB_states state;
|
||||
time_t start;
|
||||
ssh2_time_t start;
|
||||
};
|
||||
|
||||
struct packet_requirev_state {
|
||||
time_t start;
|
||||
ssh2_time_t start;
|
||||
};
|
||||
|
||||
struct kmdhgGPshakex_state {
|
||||
@@ -713,7 +721,7 @@ struct _LIBSSH2_SESSION {
|
||||
int api_block_mode;
|
||||
|
||||
/* Timeout used when blocking API behavior is active */
|
||||
long api_timeout;
|
||||
long api_timeout_ms;
|
||||
|
||||
/* Server's public key */
|
||||
const struct hostkey_method *hostkey;
|
||||
@@ -948,12 +956,12 @@ struct _LIBSSH2_SESSION {
|
||||
LIBSSH2_CHANNEL *scpSend_channel;
|
||||
|
||||
/* Keepalive variables used by keepalive.c. */
|
||||
int keepalive_interval;
|
||||
ssh2_timediff_t keepalive_interval;
|
||||
int keepalive_want_reply;
|
||||
time_t keepalive_last_sent;
|
||||
ssh2_time_t keepalive_last_sent;
|
||||
|
||||
/* Configurable timeout for packets. Replaces LIBSSH2_READ_TIMEOUT */
|
||||
long packet_read_timeout;
|
||||
ssh2_timediff_t packet_read_timeout;
|
||||
};
|
||||
#if defined(__clang__) && __clang_major__ >= 13
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
35
src/misc.c
35
src/misc.c
@@ -718,6 +718,41 @@ void ssh2_list_insert(struct list_node *after, /* insert before this */
|
||||
}
|
||||
#endif
|
||||
|
||||
ssh2_time_t ssh2_now(void) /* ms */
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ssh2_time_t sec, ns;
|
||||
LARGE_INTEGER freq, count;
|
||||
/* These never fail on supported Windows versions */
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&count);
|
||||
sec = (ssh2_time_t)(count.QuadPart / freq.QuadPart);
|
||||
ns = (ssh2_time_t)(((count.QuadPart % freq.QuadPart) *
|
||||
1000000000) / freq.QuadPart);
|
||||
return sec * 1000 + ns / 1000000;
|
||||
#else /* !_WIN32 */
|
||||
#if defined(CLOCK_MONOTONIC_RAW) /* Apple/Linux */
|
||||
struct timespec ts;
|
||||
if(!clock_gettime(CLOCK_MONOTONIC_RAW, &ts))
|
||||
return (ssh2_time_t)ts.tv_sec * 1000 +
|
||||
(ssh2_time_t)ts.tv_nsec / 1000000;
|
||||
#elif defined(CLOCK_MONOTONIC) /* POSIX */
|
||||
struct timespec ts;
|
||||
if(!clock_gettime(CLOCK_MONOTONIC, &ts))
|
||||
return (ssh2_time_t)ts.tv_sec * 1000 +
|
||||
(ssh2_time_t)ts.tv_nsec / 1000000;
|
||||
#elif defined(HAVE_GETTIMEOFDAY)
|
||||
struct timeval tv;
|
||||
if(!gettimeofday(&tv, NULL))
|
||||
return (ssh2_time_t)tv.tv_sec * 1000 + (ssh2_time_t)tv.tv_usec / 1000;
|
||||
#endif
|
||||
{
|
||||
ssh2_time_t ms = (ssh2_time_t)time(NULL) * 1000;
|
||||
return ms ? ms : 1;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
/*
|
||||
* Implementation according to:
|
||||
|
||||
12
src/packet.c
12
src/packet.c
@@ -1461,7 +1461,7 @@ int ssh2_packet_require(LIBSSH2_SESSION *session,
|
||||
match_len) == 0)
|
||||
return 0; /* A packet was available in the packet brigade */
|
||||
|
||||
state->start = time(NULL);
|
||||
state->start = ssh2_now();
|
||||
}
|
||||
|
||||
while(session->socket_state == SSH2_SOCKET_CONNECTED) {
|
||||
@@ -1485,8 +1485,8 @@ int ssh2_packet_require(LIBSSH2_SESSION *session,
|
||||
}
|
||||
else if(ret == 0) {
|
||||
/* nothing available, wait until data arrives or we time out */
|
||||
long left = session->packet_read_timeout - (long)(time(NULL) -
|
||||
state->start);
|
||||
ssh2_timediff_t left = session->packet_read_timeout -
|
||||
(ssh2_now() - state->start);
|
||||
|
||||
if(left <= 0) {
|
||||
state->start = 0;
|
||||
@@ -1575,7 +1575,7 @@ int ssh2_packet_requirev(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if(state->start == 0)
|
||||
state->start = time(NULL);
|
||||
state->start = ssh2_now();
|
||||
|
||||
while(session->socket_state != SSH2_SOCKET_DISCONNECTED) {
|
||||
int ret = ssh2_transport_read(session);
|
||||
@@ -1584,8 +1584,8 @@ int ssh2_packet_requirev(LIBSSH2_SESSION *session,
|
||||
return ret;
|
||||
}
|
||||
if(ret <= 0) {
|
||||
long left = session->packet_read_timeout -
|
||||
(long)(time(NULL) - state->start);
|
||||
ssh2_timediff_t left = session->packet_read_timeout -
|
||||
(ssh2_now() - state->start);
|
||||
|
||||
if(left <= 0) {
|
||||
state->start = 0;
|
||||
|
||||
101
src/session.c
101
src/session.c
@@ -412,11 +412,12 @@ LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC(*my_alloc),
|
||||
session->send = ssh2_send;
|
||||
session->recv = ssh2_recv;
|
||||
session->abstract = abstract;
|
||||
session->api_timeout = 0; /* timeout-free API by default */
|
||||
session->api_timeout_ms = 0; /* timeout-free API by default */
|
||||
session->api_block_mode = 1; /* blocking API by default */
|
||||
session->state = SSH2_STATE_INITIAL_KEX;
|
||||
session->fullpacket_required_type = 0;
|
||||
session->packet_read_timeout = SSH2_DEFAULT_READ_TIMEOUT;
|
||||
session->packet_read_timeout =
|
||||
ssh2_sec_to_timediff(SSH2_DEFAULT_READ_TIMEOUT);
|
||||
session->flag.quote_paths = 1; /* default behavior is to quote paths
|
||||
for the scp subsystem */
|
||||
session->kex = NULL;
|
||||
@@ -539,14 +540,15 @@ void *libssh2_session_callback_set(LIBSSH2_SESSION *session,
|
||||
* Utility function that waits for action on the socket. Returns 0 when ready
|
||||
* to run again or error on timeout.
|
||||
*/
|
||||
int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
||||
int ssh2_wait_socket(LIBSSH2_SESSION *session, ssh2_time_t start_time)
|
||||
{
|
||||
int rc;
|
||||
int seconds_to_next;
|
||||
int dir;
|
||||
int has_timeout;
|
||||
long ms_to_next = 0;
|
||||
long elapsed_ms;
|
||||
ssh2_timediff_t time_to_next = 0;
|
||||
ssh2_timediff_t elapsed_time;
|
||||
ssh2_timediff_t api_timeout = ssh2_ms_to_timediff(session->api_timeout_ms);
|
||||
|
||||
/* since libssh2 often sets EAGAIN internally before this function is
|
||||
called, we can decrease some amount of confusion in user programs by
|
||||
@@ -558,7 +560,7 @@ int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
ms_to_next = seconds_to_next * 1000;
|
||||
time_to_next = ssh2_sec_to_timediff(seconds_to_next);
|
||||
|
||||
/* figure out what to wait for */
|
||||
dir = libssh2_session_block_directions(session);
|
||||
@@ -568,27 +570,28 @@ int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
||||
/* To avoid that we hang below because there is nothing set to
|
||||
wait for, we timeout on 1 second to also avoid busy-looping
|
||||
during this condition */
|
||||
ms_to_next = 1000;
|
||||
time_to_next = ssh2_ms_to_timediff(1000);
|
||||
}
|
||||
|
||||
if(session->api_timeout > 0 &&
|
||||
(seconds_to_next == 0 || ms_to_next > session->api_timeout)) {
|
||||
time_t now = time(NULL);
|
||||
elapsed_ms = (long)(1000 * difftime(now, start_time));
|
||||
if(elapsed_ms > session->api_timeout)
|
||||
if(api_timeout > 0 &&
|
||||
(seconds_to_next == 0 || time_to_next > api_timeout)) {
|
||||
ssh2_time_t now = ssh2_now();
|
||||
elapsed_time = now > start_time ? (now - start_time) : 0;
|
||||
if(elapsed_time > api_timeout)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_TIMEOUT,
|
||||
"API timeout expired");
|
||||
|
||||
ms_to_next = session->api_timeout - elapsed_ms;
|
||||
time_to_next = api_timeout - elapsed_time;
|
||||
has_timeout = 1;
|
||||
}
|
||||
else if(ms_to_next > 0)
|
||||
else if(time_to_next > 0)
|
||||
has_timeout = 1;
|
||||
else
|
||||
has_timeout = 0;
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
{
|
||||
ssh2_timediff_t time_to_next_ms = ssh2_timediff_to_ms(time_to_next);
|
||||
struct pollfd sockets[1];
|
||||
|
||||
sockets[0].fd = session->socket_fd;
|
||||
@@ -601,7 +604,8 @@ int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
||||
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
||||
sockets[0].events |= POLLOUT;
|
||||
|
||||
rc = poll(sockets, 1, has_timeout ? (int)ms_to_next : -1);
|
||||
rc = poll(sockets, 1,
|
||||
has_timeout ? (int)SSH2_MIN(time_to_next_ms, INT_MAX) : -1);
|
||||
}
|
||||
#else
|
||||
{
|
||||
@@ -610,8 +614,9 @@ int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
||||
fd_set *writefd = NULL;
|
||||
fd_set *readfd = NULL;
|
||||
struct timeval tv;
|
||||
ssh2_timediff_t ms_to_next = ssh2_timediff_to_ms(time_to_next);
|
||||
|
||||
tv.tv_sec = ms_to_next / 1000;
|
||||
tv.tv_sec = (long)(ms_to_next / 1000);
|
||||
#ifdef libssh2_usec_t
|
||||
tv.tv_usec = (libssh2_usec_t)((ms_to_next - tv.tv_sec * 1000) * 1000);
|
||||
#else
|
||||
@@ -1337,12 +1342,12 @@ int libssh2_session_get_blocking(LIBSSH2_SESSION *session)
|
||||
* Set a session's timeout (in msec) for blocking mode,
|
||||
* or 0 to disable timeouts.
|
||||
*/
|
||||
void libssh2_session_set_timeout(LIBSSH2_SESSION *session, long timeout)
|
||||
void libssh2_session_set_timeout(LIBSSH2_SESSION *session, long timeout_ms)
|
||||
{
|
||||
if(!session)
|
||||
return;
|
||||
|
||||
session->api_timeout = timeout;
|
||||
session->api_timeout_ms = timeout_ms;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1353,22 +1358,22 @@ long libssh2_session_get_timeout(LIBSSH2_SESSION *session)
|
||||
if(!session)
|
||||
return 0;
|
||||
|
||||
return session->api_timeout;
|
||||
return session->api_timeout_ms;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a session's timeout (in sec) when reading packets,
|
||||
* or 0 to use default of 60 seconds.
|
||||
*/
|
||||
void libssh2_session_set_read_timeout(LIBSSH2_SESSION *session, long timeout)
|
||||
void libssh2_session_set_read_timeout(LIBSSH2_SESSION *session, long timeout_s)
|
||||
{
|
||||
if(!session)
|
||||
return;
|
||||
|
||||
if(timeout <= 0)
|
||||
timeout = SSH2_DEFAULT_READ_TIMEOUT;
|
||||
if(timeout_s <= 0)
|
||||
timeout_s = SSH2_DEFAULT_READ_TIMEOUT;
|
||||
|
||||
session->packet_read_timeout = timeout;
|
||||
session->packet_read_timeout = ssh2_sec_to_timediff(timeout_s);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1379,7 +1384,7 @@ long libssh2_session_get_read_timeout(LIBSSH2_SESSION *session)
|
||||
if(!session)
|
||||
return 0;
|
||||
|
||||
return session->packet_read_timeout;
|
||||
return (long)ssh2_timediff_to_sec(session->packet_read_timeout);
|
||||
}
|
||||
|
||||
#ifndef LIBSSH2_NO_DEPRECATED
|
||||
@@ -1446,9 +1451,9 @@ static SSH2_INLINE int session_poll_listener_queued(LIBSSH2_LISTENER *listener)
|
||||
*
|
||||
* Poll sockets, channels, and listeners for activity
|
||||
*/
|
||||
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout_ms)
|
||||
{
|
||||
long timeout_remaining;
|
||||
ssh2_timediff_t timeout_remaining;
|
||||
unsigned int i, active_fds;
|
||||
#ifdef HAVE_POLL
|
||||
LIBSSH2_SESSION *session = NULL;
|
||||
@@ -1503,7 +1508,6 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
LIBSSH2_SESSION *session = NULL;
|
||||
libssh2_socket_t maxfd = 0;
|
||||
fd_set rfds, wfds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
@@ -1575,10 +1579,10 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
}
|
||||
}
|
||||
#else /* !HAVE_POLL && !HAVE_SELECT */
|
||||
timeout = 0; /* no sockets structure to setup */
|
||||
timeout_ms = 0; /* no sockets structure to setup */
|
||||
#endif /* HAVE_POLL || HAVE_SELECT */
|
||||
|
||||
timeout_remaining = timeout;
|
||||
timeout_remaining = ssh2_ms_to_timediff(timeout_ms);
|
||||
do {
|
||||
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
|
||||
int sysret;
|
||||
@@ -1655,12 +1659,13 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
{
|
||||
struct timeval tv_begin, tv_end;
|
||||
ssh2_gettimeofday(&tv_begin, NULL);
|
||||
sysret = poll(sockets, nfds, (int)timeout_remaining);
|
||||
ssh2_gettimeofday(&tv_end, NULL);
|
||||
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
|
||||
timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
|
||||
ssh2_timediff_t timeout_remaining_ms =
|
||||
ssh2_timediff_to_ms(timeout_remaining);
|
||||
ssh2_time_t start_time = ssh2_now(), now;
|
||||
sysret = poll(sockets, nfds,
|
||||
(int)SSH2_MIN(timeout_remaining_ms, INT_MAX));
|
||||
now = ssh2_now();
|
||||
timeout_remaining -= now > start_time ? (now - start_time) : 0;
|
||||
}
|
||||
|
||||
if(sysret > 0) {
|
||||
@@ -1704,19 +1709,19 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
|
||||
#elif defined(HAVE_SELECT)
|
||||
|
||||
tv.tv_sec = timeout_remaining / 1000;
|
||||
#ifdef libssh2_usec_t
|
||||
tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000);
|
||||
#else
|
||||
tv.tv_usec = (timeout_remaining % 1000) * 1000;
|
||||
#endif
|
||||
{
|
||||
struct timeval tv_begin, tv_end;
|
||||
ssh2_gettimeofday(&tv_begin, NULL);
|
||||
ssh2_time_t start_time, now;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = (long)(timeout_remaining / 1000);
|
||||
#ifdef libssh2_usec_t
|
||||
tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000);
|
||||
#else
|
||||
tv.tv_usec = (timeout_remaining % 1000) * 1000;
|
||||
#endif
|
||||
start_time = ssh2_now();
|
||||
sysret = select((int)(maxfd + 1), &rfds, &wfds, NULL, &tv);
|
||||
ssh2_gettimeofday(&tv_end, NULL);
|
||||
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
|
||||
timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
|
||||
now = ssh2_now();
|
||||
timeout_remaining -= now > start_time ? (now - start_time) : 0;
|
||||
}
|
||||
|
||||
if(sysret > 0) {
|
||||
@@ -1758,8 +1763,8 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_POLL && !HAVE_SELECT -- timeout (and by extension
|
||||
* timeout_remaining) is equal to 0 */
|
||||
#endif /* !HAVE_POLL && !HAVE_SELECT -- timeout_ms (and by extension
|
||||
timeout_remaining) is equal to 0 */
|
||||
} while(timeout_remaining > 0 && !active_fds);
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
*/
|
||||
#define BLOCK_ADJUST(rc, session, x) \
|
||||
do { \
|
||||
time_t entry_time = time(NULL); \
|
||||
ssh2_time_t entry_time = ssh2_now(); \
|
||||
do { \
|
||||
(rc) = (x); \
|
||||
/* the order of the check below is important to properly \
|
||||
@@ -66,7 +66,7 @@
|
||||
*/
|
||||
#define BLOCK_ADJUST_ERRNO(ptr, session, x) \
|
||||
do { \
|
||||
time_t entry_time = time(NULL); \
|
||||
ssh2_time_t entry_time = ssh2_now(); \
|
||||
int rc; \
|
||||
do { \
|
||||
(ptr) = (x); \
|
||||
@@ -77,7 +77,7 @@
|
||||
} while(!(rc)); \
|
||||
} while(0)
|
||||
|
||||
int ssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time);
|
||||
int ssh2_wait_socket(LIBSSH2_SESSION *session, ssh2_time_t start_time);
|
||||
|
||||
/* this is the lib-internal set blocking function */
|
||||
int ssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking);
|
||||
|
||||
@@ -510,7 +510,7 @@ static int sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
|
||||
|
||||
/* If no timeout is active, start a new one */
|
||||
if(sftp->requirev_start == 0)
|
||||
sftp->requirev_start = time(NULL);
|
||||
sftp->requirev_start = ssh2_now();
|
||||
|
||||
while(sftp->channel->session->socket_state == SSH2_SOCKET_CONNECTED) {
|
||||
for(i = 0; i < num_valid_responses; i++) {
|
||||
@@ -536,9 +536,9 @@ static int sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
|
||||
}
|
||||
else if(rc <= 0) {
|
||||
/* prevent busy-looping */
|
||||
long left =
|
||||
ssh2_timediff_t left =
|
||||
sftp->channel->session->packet_read_timeout -
|
||||
(long)(time(NULL) - sftp->requirev_start);
|
||||
(ssh2_now() - sftp->requirev_start);
|
||||
|
||||
if(left <= 0) {
|
||||
sftp->requirev_start = 0;
|
||||
|
||||
@@ -143,7 +143,7 @@ struct _LIBSSH2_SFTP {
|
||||
size_t partial_received; /* Bytes received so far */
|
||||
|
||||
/* Time that sftp_packet_requirev() started reading */
|
||||
time_t requirev_start;
|
||||
ssh2_time_t requirev_start;
|
||||
|
||||
/* State variables used in libssh2_sftp_open_ex() */
|
||||
ssh2_NB_states open_state;
|
||||
|
||||
Reference in New Issue
Block a user