# HG changeset patch # User Matt Johnston # Date 1438614343 -28800 # Node ID f6d3a16ecc719ee1a95f36473d638083ae2956fe # Parent 43a8ea69b24cf42d7f5a6deb7d2d425bbc714333 set timeouts to time remaining rather than timeout duration diff -r 43a8ea69b24c -r f6d3a16ecc71 common-session.c --- a/common-session.c Mon Aug 03 21:59:40 2015 +0800 +++ b/common-session.c Mon Aug 03 23:05:43 2015 +0800 @@ -532,20 +532,39 @@ } } +static void update_timeout(long limit, long now, long last_event, long * timeout) { + TRACE(("update_timeout limit %ld, now %ld, last %ld, timeout %ld", + limit, now, last_event, *timeout)) + if (last_event > 0 && limit > 0) { + *timeout = MIN(*timeout, last_event+limit-now); + TRACE(("update to %ld", *timeout)) + } +} + static long select_timeout() { /* determine the minimum timeout that might be required, so as to avoid waking when unneccessary */ - long ret = LONG_MAX; - if (KEX_REKEY_TIMEOUT > 0) - ret = MIN(KEX_REKEY_TIMEOUT, ret); - /* AUTH_TIMEOUT is only relevant before authdone */ - if (ses.authstate.authdone != 1 && AUTH_TIMEOUT > 0) - ret = MIN(AUTH_TIMEOUT, ret); - if (opts.keepalive_secs > 0) - ret = MIN(opts.keepalive_secs, ret); - if (opts.idle_timeout_secs > 0) - ret = MIN(opts.idle_timeout_secs, ret); - return ret; + long timeout = LONG_MAX; + long now = monotonic_now(); + + update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout); + + if (ses.authstate.authdone != 1 && IS_DROPBEAR_SERVER) { + /* AUTH_TIMEOUT is only relevant before authdone */ + update_timeout(AUTH_TIMEOUT, now, ses.connect_time, &timeout); + } + + update_timeout(opts.keepalive_secs, now, + MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent), + &timeout); + + update_timeout(opts.idle_timeout_secs, now, ses.last_packet_time_idle, + &timeout); + + TRACE(("timeout %ld", timeout)) + + /* clamp negative timeouts to zero - event has already triggered */ + return MAX(timeout, 0); } const char* get_user_shell() {