From d2a4c96a7993fea9c765644bfc2341d5b9209030 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sun, 3 Oct 2021 16:06:51 -0400 Subject: Send PING to idle clients after 15 minutes This is to keep TCP connections to clients from being idle for more than 15 minutes, since regular PINGs from the server are answered by pounce and not relayed to clients. Note that there is still no timeout on poll(2) unless there are need clients. We assume that we are receiving (and swallowing) regular PINGs from the server at an interval shorter than 15 minutes, so a poll(2) timeout would be pointless. --- bounce.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/bounce.c b/bounce.c index ef256bc..ae75dc6 100644 --- a/bounce.c +++ b/bounce.c @@ -475,19 +475,24 @@ int main(int argc, char *argv[]) { eventAdd(server, NULL); size_t clientIndex = event.len; + enum { + NeedTime = 10, + IdleTime = 15 * 60, + }; for (;;) { enum Need needs = 0; + time_t now = time(NULL); for (size_t i = clientIndex; i < event.len; ++i) { struct Client *client = event.clients[i]; event.fds[i].events = POLLIN; - if (!client->need && ringDiff(client->consumer)) { + needs |= client->need; + if (client->need) continue; + if (ringDiff(client->consumer) || now - client->idle >= IdleTime) { event.fds[i].events |= POLLOUT; } - needs |= client->need; } - int timeout = 10000; - int ready = poll(event.fds, event.len, (needs ? timeout : -1)); + int ready = poll(event.fds, event.len, (needs ? NeedTime * 1000 : -1)); if (ready < 0 && errno != EINTR) err(EX_IOERR, "poll"); if (needs) { @@ -495,7 +500,7 @@ int main(int argc, char *argv[]) { for (size_t i = event.len - 1; i >= clientIndex; --i) { struct Client *client = event.clients[i]; if (!client->need) continue; - if (now - client->time < timeout / 1000) continue; + if (now - client->time < NeedTime) continue; clientFree(client); eventRemove(i); } @@ -507,7 +512,12 @@ int main(int argc, char *argv[]) { struct Client *client = event.clients[i]; if (client) { - if (revents & POLLOUT) clientConsume(client); + if (revents & POLLOUT) { + clientConsume(client); + if (now - client->idle >= IdleTime) { + clientFormat(client, "PING :%s\r\n", ORIGIN); + } + } if (revents & POLLIN) clientRecv(client); if (client->error || revents & (POLLHUP | POLLERR)) { clientFree(client); -- cgit 1.4.1