summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bounce.h3
-rw-r--r--client.c14
-rw-r--r--ring.c5
3 files changed, 19 insertions, 3 deletions
diff --git a/bounce.h b/bounce.h
index 1eb5ce9..d5f4170 100644
--- a/bounce.h
+++ b/bounce.h
@@ -70,6 +70,7 @@ static inline struct Message parse(char *line) {
 	X("away-notify", CapAwayNotify) \
 	X("batch", CapBatch) \
 	X("cap-notify", CapCapNotify) \
+	X("causal.agency/consumer", CapConsumer) \
 	X("causal.agency/passive", CapPassive) \
 	X("chghost", CapChghost) \
 	X("extended-join", CapExtendedJoin) \
@@ -91,6 +92,7 @@ enum Cap {
 	TagCaps = 0
 		| CapAccountTag
 		| CapBatch
+		| CapConsumer
 		| CapLabeledResponse
 		| CapMessageTags
 		| CapServerTime,
@@ -142,6 +144,7 @@ extern bool verbose;
 void ringAlloc(size_t len);
 void ringProduce(const char *line);
 size_t ringConsumer(const char *name);
+size_t ringPos(size_t consumer);
 size_t ringDiff(size_t consumer);
 const char *ringPeek(struct timeval *time, size_t consumer);
 const char *ringConsume(struct timeval *time, size_t consumer);
diff --git a/client.c b/client.c
index 3a1d9d6..74fa38a 100644
--- a/client.c
+++ b/client.c
@@ -165,9 +165,9 @@ static void handlePass(struct Client *client, struct Message *msg) {
 static void handleCap(struct Client *client, struct Message *msg) {
 	if (!msg->params[0]) msg->params[0] = "";
 
-	enum Cap avail = CapServerTime | CapPassive | (stateCaps & ~CapSASL);
+	enum Cap avail = (stateCaps & ~CapSASL)
+		| CapServerTime | CapConsumer | CapPassive | (clientCA ? CapSASL : 0);
 	const char *values[CapBits] = { [CapSASLBit] = "EXTERNAL" };
-	if (clientCA) avail |= CapSASL;
 
 	if (!strcmp(msg->params[0], "END")) {
 		if (!client->need) return;
@@ -553,8 +553,16 @@ void clientConsume(struct Client *client) {
 		struct tm *tm = gmtime(&time.tv_sec);
 		strftime(ts, sizeof(ts), "%FT%T", tm);
 		clientFormat(
-			client, "@time=%s.%03dZ%c%s\r\n",
+			client, "@time=%s.%03dZ;causal.agency/id=%zu%c%s\r\n",
 			ts, (int)(time.tv_usec / 1000),
+			ringPos(client->consumer),
+			(line[0] == '@' ? ';' : ' '),
+			(line[0] == '@' ? &line[1] : line)
+		);
+	} else if (client->caps & CapConsumer) {
+		clientFormat(
+			client, "@causal.agency/id=%zu%c%s\r\n",
+			ringPos(client->consumer),
 			(line[0] == '@' ? ';' : ' '),
 			(line[0] == '@' ? &line[1] : line)
 		);
diff --git a/ring.c b/ring.c
index 2d41666..90e6f2a 100644
--- a/ring.c
+++ b/ring.c
@@ -81,6 +81,11 @@ size_t ringConsumer(const char *name) {
 	return consumers.len++;
 }
 
+size_t ringPos(size_t consumer) {
+	assert(consumer < consumers.len);
+	return consumers.ptr[consumer].pos;
+}
+
 size_t ringDiff(size_t consumer) {
 	assert(consumer < consumers.len);
 	return producer - consumers.ptr[consumer].pos;