beterraba

commit 400614750fec88f2c14ee46e41c0e883a28fa6f4

Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>

server: disconnect clients

Also added a write & read buffer to clients

 cmd/beterrabad/socket2.ha | 45 ++++++++++++++++++++++++++++++++++++----


diff --git a/cmd/beterrabad/socket2.ha b/cmd/beterrabad/socket2.ha
index a3ae8bda17696242bdb8c9ded295531d79762d67..b4103a249fe406ce9c104be0bbe42cacf5770029 100644
--- a/cmd/beterrabad/socket2.ha
+++ b/cmd/beterrabad/socket2.ha
@@ -25,7 +25,9 @@
 type client2 = struct {
 	server: *server2,
 	sock: io::file,
-	pollfd: *poll::pollfd
+	pollfd: *poll::pollfd,
+	wbuf: []u8,
+	rbuf: []u8
 };
 
 fn bind2(fd: io::file) server2 = {
@@ -81,6 +83,12 @@ 		};
 
 		for (let i = 2z; i < len(s.pollfd); i += 1) {
 			dispatch_client2(s, &s.clients[i - 2]);
+
+			if (s.disconnected) {
+				// Restart loop on client disconnect
+				s.disconnected = false;
+				i = 2z;
+			};
 		};
 	};
 	case let err: errors::error =>
@@ -93,6 +101,16 @@
 fn dispatch_client2(s: *server2, client: *client2) void = {
 	let cpollfd = client.pollfd;
 
+	if (cpollfd.revents & event::POLLERR != 0) {
+		disconnect_client(client);
+		return;
+	};
+
+	if (cpollfd.revents & event::POLLHUP != 0) {
+		disconnect_client(client);
+		return;
+	};
+
 	if (cpollfd.revents & event::POLLIN != 0) {
 		read_client(s, client);
 	};
@@ -107,11 +125,9 @@ 	let bufline = match (bufio::scanline(client.sock)) {
 	case let l: []u8 =>
 		yield l;
 	case io::EOF =>
-		// disconnect
-		log::println("EOF");
+		disconnect_client(client);
 	case io::error =>
-		// disconnect
-		log::fatalf("io error");
+		disconnect_client(client);
 	};
 
 	let line = match (strings::try_fromutf8(bufline as []u8)) {
@@ -149,10 +165,29 @@ 		...
 	});
 };
 
+// Immediately disconnects a client, without sending them an error message.
+fn disconnect_client(c: *client2) void = {
+	io::close(c.sock)!;
+	free(c.rbuf);
+	free(c.wbuf);
+
+	let serv = c.server;
+	let i = (c: uintptr - serv.clients: *[*]client: uintptr): size / size(client);
+	delete(serv.clients[i]);
+	delete(serv.pollfd[i + 2z]);
+	for (i < len(serv.clients); i += 1) {
+		serv.clients[i].pollfd = &serv.pollfd[i + 2z];
+	};
+
+	serv.disconnected = true;
+};
+
 // TODO: Walk over every connected client and disconnect them & free the clients
 fn shutdown2(s: *server2) void = {
 	for (let i = 0z; i < len(s.clients); i += 1) {
 		net::close(s.clients[i].sock)!;
+		free(s.clients[i].wbuf);
+		free(s.clients[i].rbuf);
 	};
 
 	free(s.clients);