summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2021-10-03 16:06:51 -0400
committerJune McEnroe <june@causal.agency>2021-10-03 16:06:51 -0400
commitd2a4c96a7993fea9c765644bfc2341d5b9209030 (patch)
tree42ff006bc80aac05d936c75085c74df8b668eb90
parentTrack client idle time (diff)
downloadpounce-d2a4c96a7993fea9c765644bfc2341d5b9209030.tar.gz
pounce-d2a4c96a7993fea9c765644bfc2341d5b9209030.zip
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.
-rw-r--r--bounce.c22
1 files 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);