Lindenii Project Forge
Login

hare-ev

Temporary fork of hare-ev for... reasons
Commit info
ID
904324e7f5d938fbf7f6507b49c82772a0e6cc77
Author
Willow Barraco <contact@willowbarraco.fr>
Author date
Sat, 29 Jul 2023 14:15:32 +0200
Committer
Drew DeVault <sir@cmpwn.com>
Committer date
Mon, 07 Aug 2023 11:23:46 +0200
Actions
Set state.src: ip::addr4 initial value

Signed-off-by: Willow Barraco <contact@willowbarraco.fr>
use errors;
use ev;
use log;
use net;
use net::ip;
use os;

type state = struct {
	loop: *ev::loop,
	src: ip::addr,
	port: u16,
	buf: [os::BUFSIZ]u8,
	wbuf: []u8,
};

export fn main() void = {
	const loop = ev::newloop()!;
	defer ev::finish(&loop);

	const sock = match (ev::listen_udp(&loop, ip::LOCAL_V4, 12345)) {
	case let err: net::error =>
		log::fatalf("Error: listen: {}", net::strerror(err));
	case let err: errors::error =>
		log::fatalf("Error: listen: {}", errors::strerror(err));
	case let sock: *ev::file =>
		yield sock;
	};
	defer ev::close(sock);

	let state = state {
		loop = &loop,
		src = [0: u8, 0: u8, 0: u8, 0: u8],
		...
	};
	ev::setuser(sock, &state);
	ev::recvfrom(sock, &recv, state.buf);

	log::println("Listening on 127.0.0.1:12345");
	for (ev::dispatch(&loop, -1)!) void;
};

fn recv(sock: *ev::file, r: ((size, ip::addr, u16) | net::error)) void = {
	const state = ev::getuser(sock): *state;
	const (n, src, port) = match (r) {
	case let err: net::error =>
		log::println("Error: recv:", net::strerror(err));
		ev::stop(state.loop);
		return;
	case let packet: (size, ip::addr, u16) =>
		yield packet;
	};

	// TODO: Make ev send/write all data and drop these fields and the need
	// to manually manage a write buffer and re-call sendto in &send
	state.src = src;
	state.port = port;

	log::printfln("{} bytes from {}:{}", n, ip::string(src), port);
	state.wbuf = state.buf[..n];
	ev::sendto(sock, &send, state.wbuf, src, port);
};

fn send(sock: *ev::file, r: (size | net::error)) void = {
	const state = ev::getuser(sock): *state;
	const n = match (r) {
	case let err: net::error =>
		log::println("Error: send:", net::strerror(err));
		ev::stop(state.loop);
		return;
	case let n: size =>
		yield n;
	};

	static delete(state.wbuf[..n]);

	if (len(state.wbuf) != 0) {
		ev::sendto(sock, &send, state.wbuf, state.src, state.port);
	} else {
		ev::recvfrom(sock, &recv, state.buf);
	};
};