summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-10-25 02:27:05 -0400
committerJune McEnroe <june@causal.agency>2019-10-25 02:27:05 -0400
commit3f243081d85ca02188ccdd61ae3476ed9df933e1 (patch)
treee3adbde6da2c302255ee31d9db1f4fbe5ae45a37
parentImplement ringDiff and ringRead (diff)
downloadpounce-3f243081d85ca02188ccdd61ae3476ed9df933e1.tar.gz
pounce-3f243081d85ca02188ccdd61ae3476ed9df933e1.zip
Implement client reading from ring buffer
It's still messy but it works!!
-rw-r--r--bounce.c31
-rw-r--r--bounce.h12
-rw-r--r--client.c21
3 files changed, 50 insertions, 14 deletions
diff --git a/bounce.c b/bounce.c
index 6de5e5d..c771bbe 100644
--- a/bounce.c
+++ b/bounce.c
@@ -140,17 +140,30 @@ int main(int argc, char *argv[]) {
 				struct tls *tls;
 				int fd = listenAccept(&tls, event.fds[i].fd);
 				eventAdd(fd, clientAlloc(tls));
-			} else if (!event.clients[i]) {
+				continue;
+			}
+			if (!event.clients[i]) {
 				serverRecv();
+				continue;
+			}
+			short revents = event.fds[i].revents;
+			struct Client *client = event.clients[i];
+			if (revents & POLLIN) clientRecv(client);
+			if (revents & POLLOUT) clientRead(client);
+			if (clientError(client) || revents & (POLLHUP | POLLERR)) {
+				clientFree(client);
+				close(event.fds[i].fd);
+				eventRemove(i);
+				break;
+			}
+		}
+
+		for (size_t i = 0; i < event.len; ++i) {
+			if (!event.clients[i]) continue;
+			if (clientDiff(event.clients[i])) {
+				event.fds[i].events |= POLLOUT;
 			} else {
-				struct Client *client = event.clients[i];
-				if (event.fds[i].revents & POLLIN) clientRecv(client);
-				if (event.fds[i].revents & ~POLLIN || clientError(client)) {
-					clientFree(client);
-					close(event.fds[i].fd);
-					eventRemove(i);
-					break;
-				}
+				event.fds[i].events &= ~POLLOUT;
 			}
 		}
 	}
diff --git a/bounce.h b/bounce.h
index d81acf9..d4ec916 100644
--- a/bounce.h
+++ b/bounce.h
@@ -53,6 +53,11 @@ static inline struct Message parse(char *line) {
 	return msg;
 }
 
+void ringWrite(const char *line);
+size_t ringReader(const char *name);
+size_t ringDiff(size_t reader);
+const char *ringRead(time_t *time, size_t reader);
+
 void listenConfig(const char *cert, const char *priv);
 size_t listenBind(int fds[], size_t cap, const char *host, const char *port);
 int listenAccept(struct tls **client, int fd);
@@ -76,12 +81,9 @@ void clientRecv(struct Client *client);
 void clientSend(struct Client *client, const char *ptr, size_t len);
 void clientFormat(struct Client *client, const char *format, ...)
 	__attribute__((format(printf, 2, 3)));
+size_t clientDiff(const struct Client *client);
+void clientRead(struct Client *client);
 
 bool stateReady(void);
 void stateParse(char *line);
 void stateSync(struct Client *client);
-
-void ringWrite(const char *line);
-size_t ringReader(const char *name);
-size_t ringDiff(size_t reader);
-const char *ringRead(time_t *time, size_t reader);
diff --git a/client.c b/client.c
index 4bb1f54..cdf0009 100644
--- a/client.c
+++ b/client.c
@@ -119,6 +119,7 @@ static void handleUser(struct Client *client, struct Message msg) {
 }
 
 static void handlePass(struct Client *client, struct Message msg) {
+	if (!clientPass) return;
 	if (!msg.params[0] || strcmp(clientPass, msg.params[0])) {
 		passRequired(client);
 	} else {
@@ -227,3 +228,23 @@ void clientRecv(struct Client *client) {
 	client->len -= line - client->buf;
 	memmove(client->buf, line, client->len);
 }
+
+size_t clientDiff(const struct Client *client) {
+	if (client->need) return 0;
+	return ringDiff(client->reader);
+}
+
+// TODO: Read several lines based on LOWAT for POLLOUT?
+void clientRead(struct Client *client) {
+	time_t time;
+	const char *line = ringRead(&time, client->reader);
+	if (!line) return;
+	if (client->serverTime) {
+		char ts[sizeof("YYYY-MM-DDThh:mm:ss.sssZ")];
+		struct tm *tm = gmtime(&time);
+		strftime(ts, sizeof(ts), "%FT%T.000Z", tm);
+		clientFormat(client, "@time=%s %s\r\n", ts, line);
+	} else {
+		clientFormat(client, "%s\r\n", line);
+	}
+}
igKonstantin Ryabitsev