From 9d2c11ebf759e16e6becaf1d4ba440875c600b70 Mon Sep 17 00:00:00 2001
From: Armin Preiml <apreiml@strohwolke.at>
Date: Thu, 23 Jan 2025 15:54:31 +0100
Subject: [PATCH] ev::dial: nomen changes

Signed-off-by: Armin Preiml <apreiml@strohwolke.at>

---
 ev/dial/ip.ha       | 30 ++++++++++++++++++++----------
 ev/dial/registry.ha | 10 +++++-----
 ev/dial/resolve.ha  | 59 ++++++++++++++++++++++++++++++++++++++++++-----------

diff --git a/ev/dial/ip.ha b/ev/dial/ip.ha
index 0819889dc44822759600d18517a63d603f65d4df..a0ea529978c7845f811bffb175d8d2fc26f301ed 100644
--- a/ev/dial/ip.ha
+++ b/ev/dial/ip.ha
@@ -35,12 +35,17 @@ 		loop = loop,
 		cb = cb,
 		user = user,
 		...
-	});
+	})?;
 
-	const req = resolve(loop, "tcp", addr,
-		service, &dial_tcp_resolvecb, state)?;
-	state.req = req;
-	return ev::mkreq(&dial_tcp_cancel, state);
+	match (resolve(loop, "tcp", addr,
+		service, &dial_tcp_resolvecb, state)) {
+	case let req: ev::req =>
+		state.req = req;
+		return ev::mkreq(&dial_tcp_cancel, state);
+	case let e: error =>
+		free(state);
+		return e;
+	};
 };
 
 fn dial_tcp_resolvecb(
@@ -135,12 +140,17 @@ 		loop = loop,
 		cb = cb,
 		user = user,
 		...
-	});
+	})?;
 
-	const req = resolve(loop, "udp", addr,
-		service, &dial_udp_resolvecb, state)?;
-	state.req = req;
-	return ev::mkreq(&dial_udp_cancel, state);
+	match (resolve(loop, "udp", addr,
+		service, &dial_udp_resolvecb, state)) {
+	case let req: ev::req =>
+		state.req = req;
+		return ev::mkreq(&dial_udp_cancel, state);
+	case let e: error =>
+		free(state);
+		return e;
+	};
 };
 
 fn dial_udp_resolvecb(
diff --git a/ev/dial/registry.ha b/ev/dial/registry.ha
index 982a878ffb8f9a6f6d66e1a6a2fcbd34bba755e4..ee9266cf87e99ad38858d571f826765784588ba7 100644
--- a/ev/dial/registry.ha
+++ b/ev/dial/registry.ha
@@ -16,7 +16,7 @@ // system.
 export type unknown_service = !void;
 
 // Errors which can occur from dial.
-export type error = !(invalid_address | unknown_service
+export type error = !(nomem | invalid_address | unknown_service
 	| net::error | dns::error | hosts::error | errors::error);
 
 // Converts an [[error]] to a human-readable string.
@@ -86,11 +86,11 @@ };
 
 // Registers a new transport-level protocol (e.g. TCP) with the dialer. The name
 // should be statically allocated.
-export fn registerproto(name: str, dial: *dialer) void = {
+export fn registerproto(name: str, dial: *dialer) (void | nomem) = {
 	append(protocols, protocol {
 		name = name,
 		dial = dial,
-	});
+	})?;
 };
 
 // Registers a new application-level service (e.g. SSH) with the dialer. Note
@@ -102,13 +102,13 @@ 	proto: str,
 	name: str,
 	alias: []str,
 	port: u16,
-) void = {
+) (void | nomem) = {
 	append(services, service {
 		proto = proto,
 		name = name,
 		alias = alias,
 		port = port,
-	});
+	})?;
 };
 
 fn lookup_service(proto: str, service: str) (u16 | void) = {
diff --git a/ev/dial/resolve.ha b/ev/dial/resolve.ha
index 3be0d59d188cc79d03306be630f90178f58a33ec..d828724def216cdb655f844f7fb2a149496e2bad 100644
--- a/ev/dial/resolve.ha
+++ b/ev/dial/resolve.ha
@@ -43,7 +43,7 @@ 	let state = alloc(resolve_state {
 		cb = cb,
 		user = user,
 		...
-	});
+	})?;
 
 	const (addr, port) = match (dial::splitaddr(addr, service)) {
 	case let svc: (str, u16) =>
@@ -77,13 +77,25 @@ 	};
 
 	match (ip::parse(addr)) {
 	case let addr: ip::addr =>
-		const addrs = alloc([addr]);
-		resolve_finish(state, (addrs, port));
-		return ev::req { ... };
+		let addrs: []ip::addr = [];
+		match (append(addrs, addr)) {
+		case void =>
+			resolve_finish(state, (addrs, port));
+			return ev::req { ... };
+		case nomem =>
+			resolve_finish(state, nomem);
+			return nomem;
+		};
 	case ip::invalid => yield;
 	};
 
-	const addrs = hosts::lookup(addr)?;
+	const addrs = match (hosts::lookup(addr)) {
+	case let addrs: []ip::addr =>
+		yield addrs;
+	case let e: hosts::error =>
+		resolve_finish(state, nomem);
+		return e;
+	};
 	if (len(addrs) != 0) {
 		resolve_finish(state, (addrs, port));
 		return ev::req { ... };
@@ -148,8 +160,11 @@ 		],
 		...
 	};
 
+	let ok = false;
 	state.r6 = edns::query(loop, &query6, &query_cb_v6, state)?;
+	defer if(!ok) ev::cancel(&state.r6);
 	state.r4 = edns::query(loop, &query4, &query_cb_v4, state)?;
+	ok = true;
 	return ev::mkreq(&resolve_cancel, state);
 };
 
@@ -171,7 +186,7 @@ 	free(state.ip);
 	free(state);
 };
 
-fn query_cb_v4(user: nullable *opaque, r: (*dns::message | dns::error)) void = {
+fn query_cb_v4(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) void = {
 	let state = user: *resolve_state;
 	state.r4 = ev::req { ... };
 
@@ -180,8 +195,18 @@ 	case let err: dns::error =>
 		ev::cancel(&state.r6);
 		resolve_finish(state, err);
 		return;
+	case nomem =>
+		ev::cancel(&state.r6);
+		resolve_finish(state, nomem);
+		return;
 	case let msg: *dns::message =>
-		collect_answers(&state.ip, &msg.answers);
+		match (collect_answers(&state.ip, &msg.answers)) {
+		case void => void;
+		case nomem =>
+			ev::cancel(&state.r6);
+			resolve_finish(state, nomem);
+			return;
+		};
 		state.nq += 1;
 	};
 
@@ -191,7 +216,7 @@ 	};
 	resolve_finish(state, (state.ip, state.port));
 };
 
-fn query_cb_v6(user: nullable *opaque, r: (*dns::message | dns::error)) void = {
+fn query_cb_v6(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) void = {
 	let state = user: *resolve_state;
 	state.r6 = ev::req { ... };
 
@@ -199,9 +224,19 @@ 	match (r) {
 	case let err: dns::error =>
 		ev::cancel(&state.r4);
 		resolve_finish(state, err);
+		return;
+	case nomem =>
+		ev::cancel(&state.r4);
+		resolve_finish(state, nomem);
 		return;
 	case let msg: *dns::message =>
-		collect_answers(&state.ip, &msg.answers);
+		match (collect_answers(&state.ip, &msg.answers)) {
+		case void => void;
+		case nomem =>
+			ev::cancel(&state.r4);
+			resolve_finish(state, nomem);
+			return;
+		};
 		state.nq += 1;
 	};
 
@@ -211,13 +246,13 @@ 	};
 	resolve_finish(state, (state.ip, state.port));
 };
 
-fn collect_answers(addrs: *[]ip::addr, answers: *[]dns::rrecord) void = {
+fn collect_answers(addrs: *[]ip::addr, answers: *[]dns::rrecord) (void | nomem) = {
 	for (let answer &.. answers) {
 		match (answer.rdata) {
 		case let addr: dns::aaaa =>
-			append(addrs, addr: ip::addr);
+			append(addrs, addr: ip::addr)?;
 		case let addr: dns::a =>
-			append(addrs, addr: ip::addr);
+			append(addrs, addr: ip::addr)?;
 		case => void;
 		};
 	};

-- 
2.48.1