summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2022-03-29 17:26:40 -0400
committerJune McEnroe <june@causal.agency>2022-03-29 17:26:40 -0400
commit37ba5072f3058f94e6b809ff01101b2681c62fb2 (patch)
treea10f3ed3578ace1db8f21a16b8a0b38d0d5e7ecf
parentDocument using -S to connect over IPv4 or IPv6 (diff)
downloadpounce-37ba5072f3058f94e6b809ff01101b2681c62fb2.tar.gz
pounce-37ba5072f3058f94e6b809ff01101b2681c62fb2.zip
Handle CAP REQ causal.agency/passive after registration
If we supported disabling caps, there would need to be a corresponding
check and activeIncr().
-rw-r--r--client.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/client.c b/client.c
index 10b28f8..6d6268d 100644
--- a/client.c
+++ b/client.c
@@ -46,8 +46,6 @@ enum Cap clientCaps = CapServerTime | CapConsumer | CapPassive | CapSTS;
 char *clientPass;
 char *clientAway;
 
-static size_t active;
-
 struct Client *clientAlloc(int sock, struct tls *tls) {
 	struct Client *client = calloc(1, sizeof(*client));
 	if (!client) err(EX_OSERR, "calloc");
@@ -75,12 +73,26 @@ static void clientHandshake(struct Client *client) {
 	}
 }
 
-void clientFree(struct Client *client) {
-	if (!client->need) {
-		if (!(client->caps & CapPassive) && !--active && !stateAway) {
-			serverEnqueue("AWAY :%s\r\n", clientAway);
-		}
+static size_t active;
+
+static void activeIncr(const struct Client *client) {
+	if (client->need) return;
+	if (client->caps & CapPassive) return;
+	if (!active++) {
+		serverEnqueue("AWAY\r\n");
 	}
+}
+
+static void activeDecr(const struct Client *client) {
+	if (client->need) return;
+	if (client->caps & CapPassive) return;
+	if (!--active && !stateAway) {
+		serverEnqueue("AWAY :%s\r\n", clientAway);
+	}
+}
+
+void clientFree(struct Client *client) {
+	activeDecr(client);
 	tls_close(client->tls);
 	tls_free(client->tls);
 	free(client);
@@ -129,9 +141,7 @@ static void maybeSync(struct Client *client) {
 	if (!client->need) {
 		stateSync(client);
 		if (client->setPos) ringSet(client->consumer, client->setPos);
-		if (!(client->caps & CapPassive) && !active++) {
-			serverEnqueue("AWAY\r\n");
-		}
+		activeIncr(client);
 	}
 }
 
@@ -213,10 +223,13 @@ static void handleCap(struct Client *client, struct Message *msg) {
 		if (client->need) client->need |= NeedCapEnd;
 		enum Cap caps = capParse(msg->params[1], values);
 		if (caps == (avail & caps)) {
-			client->caps |= caps;
 			if (caps & CapConsumer && values[CapConsumerBit]) {
 				client->setPos = strtoull(values[CapConsumerBit], NULL, 10);
 			}
+			if (caps & CapPassive && !(client->caps & CapPassive)) {
+				activeDecr(client);
+			}
+			client->caps |= caps;
 			clientFormat(client, ":%s CAP * ACK :%s\r\n", ORIGIN, msg->params[1]);
 		} else {
 			clientFormat(client, ":%s CAP * NAK :%s\r\n", ORIGIN, msg->params[1]);