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);