Browse Source

add Hare tick server with bug

master
Alexander Avery 9 months ago
parent
commit
6907f75fb2
  1. 143
      main.ha

143
main.ha

@ -0,0 +1,143 @@
use bufio;
use io;
use log;
use net;
use net::ip;
use net::tcp;
use strings;
use time;
use unix::poll;
// our message to send to clients as a constant
def tick: [5]u8 = ['t', 'i', 'c', 'k', '\n'];
// tryconn attempts to add a client to a pollfd slice.
fn tryconn(fds: []poll::pollfd) void = {
let socket = fds[0];
if (socket.revents & poll::event::POLLIN > 0) {
// try to accept the connection.
let conn = match(net::accept(socket.fd)) {
case let err: net::error =>
log::println("failed to accept connection");
return;
case let sock: net::socket =>
yield sock;
};
// the events we want to listen for
let events = (poll::event::POLLIN | poll::event::POLLPRI);
for (let i = 1z; i < len(fds); i += 1) {
// empty slot is indicated by a
// file descriptor equal to 0
if (fds[i].fd == 0) {
fds[i].fd = conn;
fds[i].events = events;
return;
};
};
// close the connection if there is no room
io::close(conn)!;
};
};
// tryread will attempt to read from all connected clients.
fn tryread(fds: []poll::pollfd) void = {
for (let i = 1z; i < len(fds); i += 1) {
let revents = fds[i].revents;
// just close the file descriptor
// on error or hangup events
if (revents & poll::event::POLLERR
& poll::event::POLLHUP > 0) {
closefd(&fds[i]);
continue;
};
// if there is data to read...
if (revents & poll::event::POLLIN > 0) {
let scanner = bufio::newscanner(fds[i].fd, 1024z);
defer bufio::finish(&scanner);
match(bufio::scan_line(&scanner)) {
case let msg: const str =>
log::printfln("client said: {}", msg);
case =>
// io::EOF, io::error, or utf8::invalid
closefd(&fds[i]);
};
};
};
};
// write sends a 'tick' message to all connected clients.
fn write(fds: []poll::pollfd) void = {
for (let i = 1z; i < len(fds); i += 1) {
if (fds[i].fd > 0) {
io::writeall(fds[i].fd, tick)!;
};
};
};
// closefd closes a provided file descriptor
// and resets all fields to 0.
fn closefd(fd: *poll::pollfd) void = {
match(io::close(fd.fd)) {
case void =>
void;
case io::error =>
log::println("failed to close socket");
};
fd.fd = 0;
fd.events = 0;
fd.revents = 0;
};
export fn main() void = {
let socket = tcp::listen(ip::LOCAL_V4, 8080)!;
// initialize all pollfds with zero values
let fds: [15]poll::pollfd = [
poll::pollfd {
fd = 0,
events = 0,
revents = 0,
}
...
];
// overwrite the first pollfd with our socket
fds[0] = poll::pollfd {
fd = socket,
events = (poll::event::POLLIN | poll::event::POLLPRI),
revents = 0
};
for (true) {
match(poll::poll(fds, time::SECOND)) {
case let n: uint =>
if (n > 0) {
tryconn(fds);
tryread(fds);
} else {
write(fds);
};
case let err: poll::error =>
log::fatal("poll failed");
};
};
};
Loading…
Cancel
Save