session CHANGE timeout mechanism completely rewritten
Now is accurate, it was not at all before.
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index c4f2465..2cc924f 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -1185,7 +1185,8 @@
static int
nc_open_netconf_channel(struct nc_session *session, int timeout)
{
- int elapsed_usec = 0, ret;
+ int ret;
+ struct timespec ts_timeout, ts_cur;
/* message callback is executed twice to give chance for the channel to be
* created if timeout == 0 (it takes 2 messages, channel-open, subsystem-request) */
@@ -1231,6 +1232,10 @@
return 1;
}
+ if (timeout > -1) {
+ nc_gettimespec(&ts_timeout);
+ nc_addtimespec(&ts_timeout, timeout);
+ }
while (1) {
if (!nc_session_is_connected(session)) {
ERR("Communication socket unexpectedly closed (libssh).");
@@ -1256,14 +1261,15 @@
return 1;
}
- if ((timeout != -1) && (elapsed_usec / 1000 >= timeout)) {
- /* timeout */
- ERR("Failed to start \"netconf\" SSH subsystem for too long, disconnecting.");
- break;
- }
-
usleep(NC_TIMEOUT_STEP);
- elapsed_usec += NC_TIMEOUT_STEP;
+ if (timeout > -1) {
+ nc_gettimespec(&ts_cur);
+ if (nc_difftimespec(&ts_cur, &ts_timeout) < 1) {
+ /* timeout */
+ ERR("Failed to start \"netconf\" SSH subsystem for too long, disconnecting.");
+ break;
+ }
+ }
}
return 0;
@@ -1320,7 +1326,8 @@
{
ssh_bind sbind;
struct nc_server_ssh_opts *opts;
- int libssh_auth_methods = 0, elapsed_usec = 0, ret;
+ int libssh_auth_methods = 0, ret;
+ struct timespec ts_timeout, ts_cur;
opts = session->data;
@@ -1374,12 +1381,18 @@
ssh_set_blocking(session->ti.libssh.session, 0);
+ if (timeout > -1) {
+ nc_gettimespec(&ts_timeout);
+ nc_addtimespec(&ts_timeout, timeout);
+ }
while ((ret = ssh_handle_key_exchange(session->ti.libssh.session)) == SSH_AGAIN) {
/* this tends to take longer */
usleep(NC_TIMEOUT_STEP * 20);
- elapsed_usec += NC_TIMEOUT_STEP * 20;
- if ((timeout > -1) && (elapsed_usec / 1000 >= timeout)) {
- break;
+ if (timeout > -1) {
+ nc_gettimespec(&ts_cur);
+ if (nc_difftimespec(&ts_cur, &ts_timeout) < 1) {
+ break;
+ }
}
}
if (ret == SSH_AGAIN) {
@@ -1391,8 +1404,11 @@
}
/* authenticate */
- elapsed_usec = 0;
- do {
+ if (opts->auth_timeout) {
+ nc_gettimespec(&ts_timeout);
+ nc_addtimespec(&ts_timeout, opts->auth_timeout * 1000);
+ }
+ while (1) {
if (!nc_session_is_connected(session)) {
ERR("Communication SSH socket unexpectedly closed.");
return -1;
@@ -1404,18 +1420,24 @@
return -1;
}
+ if (session->flags & NC_SESSION_SSH_AUTHENTICATED) {
+ break;
+ }
+
if (session->opts.server.ssh_auth_attempts >= opts->auth_attempts) {
ERR("Too many failed authentication attempts of user \"%s\".", session->username);
return -1;
}
- if (session->flags & NC_SESSION_SSH_AUTHENTICATED) {
- break;
- }
-
usleep(NC_TIMEOUT_STEP);
- elapsed_usec += NC_TIMEOUT_STEP;
- } while (!opts->auth_timeout || (elapsed_usec / 1000000 < opts->auth_timeout));
+ if (opts->auth_timeout) {
+ nc_gettimespec(&ts_cur);
+ if (nc_difftimespec(&ts_cur, &ts_timeout) < 1) {
+ /* timeout */
+ break;
+ }
+ }
+ }
if (!(session->flags & NC_SESSION_SSH_AUTHENTICATED)) {
/* timeout */
@@ -1428,7 +1450,7 @@
}
/* open channel */
- ret = nc_open_netconf_channel(session, opts->auth_timeout ? (opts->auth_timeout * 1000 - elapsed_usec / 1000) : -1);
+ ret = nc_open_netconf_channel(session, timeout);
if (ret < 1) {
return ret;
}