diff --git a/docs/libssh2_keepalive_config.md b/docs/libssh2_keepalive_config.md index 40cea3b7..f9925b75 100644 --- a/docs/libssh2_keepalive_config.md +++ b/docs/libssh2_keepalive_config.md @@ -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)**. diff --git a/docs/libssh2_poll.md b/docs/libssh2_poll.md index c4ab608c..de122572 100644 --- a/docs/libssh2_poll.md +++ b/docs/libssh2_poll.md @@ -17,7 +17,7 @@ libssh2_poll - poll for activity on a socket, channel or listener ~~~c #include -int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout); +int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout_ms); ~~~ # DESCRIPTION diff --git a/docs/libssh2_session_set_read_timeout.md b/docs/libssh2_session_set_read_timeout.md index 7af50dfa..0ba811f1 100644 --- a/docs/libssh2_session_set_read_timeout.md +++ b/docs/libssh2_session_set_read_timeout.md @@ -17,12 +17,13 @@ libssh2_session_set_read_timeout - set timeout for packet read functions ~~~c #include -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. diff --git a/docs/libssh2_session_set_timeout.md b/docs/libssh2_session_set_timeout.md index 17f058ad..bf5f111d 100644 --- a/docs/libssh2_session_set_timeout.md +++ b/docs/libssh2_session_set_timeout.md @@ -17,13 +17,13 @@ libssh2_session_set_timeout - set timeout for blocking functions ~~~c #include -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 diff --git a/include/libssh2.h b/include/libssh2.h index 5b690fd3..7b7fbd45 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -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() diff --git a/src/keepalive.c b/src/keepalive.c index 6746977d..061e1d91 100644 --- a/src/keepalive.c +++ b/src/keepalive.c @@ -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; } diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 2875e4fd..abf8ac61 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -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 diff --git a/src/misc.c b/src/misc.c index 91ab907d..0922e838 100644 --- a/src/misc.c +++ b/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: diff --git a/src/packet.c b/src/packet.c index d220ec31..ded8fbc6 100644 --- a/src/packet.c +++ b/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; diff --git a/src/session.c b/src/session.c index 612b8f2d..6afd4e34 100644 --- a/src/session.c +++ b/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 diff --git a/src/session.h b/src/session.h index fbfd7514..bb19e8db 100644 --- a/src/session.h +++ b/src/session.h @@ -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); diff --git a/src/sftp.c b/src/sftp.c index 07037cea..2c8aa8d9 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -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; diff --git a/src/sftp.h b/src/sftp.h index e6e3b04f..e9f06b74 100644 --- a/src/sftp.h +++ b/src/sftp.h @@ -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;