mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
b4202c917a
A compiler warning drew my attention to the fact that 'next' in pinger_schedule() was an int, not the unsigned long it should have been. And looking at the code that handles it, it was also taking no care with integer wraparound when checking whether an existing scheduled ping should be moved forward. So now I do something a bit more robust, by remembering what time it _was_ when we set pinger->next, and checking if the new time value falls in the interval between those two times.
75 lines
1.7 KiB
C
75 lines
1.7 KiB
C
/*
|
|
* pinger.c: centralised module that deals with sending TS_PING
|
|
* keepalives, to avoid replicating this code in multiple backends.
|
|
*/
|
|
|
|
#include "putty.h"
|
|
|
|
struct pinger_tag {
|
|
int interval;
|
|
int pending;
|
|
unsigned long when_set, next;
|
|
Backend *back;
|
|
void *backhandle;
|
|
};
|
|
|
|
static void pinger_schedule(Pinger pinger);
|
|
|
|
static void pinger_timer(void *ctx, unsigned long now)
|
|
{
|
|
Pinger pinger = (Pinger)ctx;
|
|
|
|
if (pinger->pending && now == pinger->next) {
|
|
pinger->back->special(pinger->backhandle, TS_PING);
|
|
pinger->pending = FALSE;
|
|
pinger_schedule(pinger);
|
|
}
|
|
}
|
|
|
|
static void pinger_schedule(Pinger pinger)
|
|
{
|
|
unsigned long next;
|
|
|
|
if (!pinger->interval) {
|
|
pinger->pending = FALSE; /* cancel any pending ping */
|
|
return;
|
|
}
|
|
|
|
next = schedule_timer(pinger->interval * TICKSPERSEC,
|
|
pinger_timer, pinger);
|
|
if (!pinger->pending ||
|
|
(next - pinger->when_set) < (pinger->next - pinger->when_set)) {
|
|
pinger->next = next;
|
|
pinger->when_set = timing_last_clock();
|
|
pinger->pending = TRUE;
|
|
}
|
|
}
|
|
|
|
Pinger pinger_new(Conf *conf, Backend *back, void *backhandle)
|
|
{
|
|
Pinger pinger = snew(struct pinger_tag);
|
|
|
|
pinger->interval = conf_get_int(conf, CONF_ping_interval);
|
|
pinger->pending = FALSE;
|
|
pinger->back = back;
|
|
pinger->backhandle = backhandle;
|
|
pinger_schedule(pinger);
|
|
|
|
return pinger;
|
|
}
|
|
|
|
void pinger_reconfig(Pinger pinger, Conf *oldconf, Conf *newconf)
|
|
{
|
|
int newinterval = conf_get_int(newconf, CONF_ping_interval);
|
|
if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) {
|
|
pinger->interval = newinterval;
|
|
pinger_schedule(pinger);
|
|
}
|
|
}
|
|
|
|
void pinger_free(Pinger pinger)
|
|
{
|
|
expire_timer_context(pinger);
|
|
sfree(pinger);
|
|
}
|