hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 5d7ebf141050eb1b41536c8d006042a441b43c69
parent 2f357d551b3e8b40587b8eabb98de3cfb8fa7192
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 28 Sep 2023 13:08:19 +0200

net::dial: refactor out and export splitaddr

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mnet/dial/resolve.ha | 78+++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mnet/dns/query.ha | 1-
2 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/net/dial/resolve.ha b/net/dial/resolve.ha @@ -8,52 +8,64 @@ use strconv; use strings; use unix::hosts; -// Performs DNS resolution on a given address string for a given service, -// including /etc/hosts lookup and SRV resolution, and returns a list of -// candidate IP addresses and the appropriate port, or an error. -// -// The caller must free the [[net::ip::addr]] slice. -export fn resolve( - proto: str, - addr: str, - service: str, -) (([]ip::addr, u16) | error) = { - let port = if (strings::hasprefix(addr, '[')) { - // [::1]:80 - yield match (strings::index(addr, "]:")) { +// Splits an address:port/service string into separate address and port +// components. The return value is borrowed from the input. +export fn splitaddr(addr: str, service: str) ((str, u16) | invalid_address) = { + let port = 0u16; + if (strings::hasprefix(addr, '[')) { + // [::1]:80 (IPv6) + match (strings::index(addr, "]:")) { case let i: size => const sub = strings::sub(addr, i + 2, strings::end); addr = strings::sub(addr, 1, i); - yield match (strconv::stou16(sub)) { + match (strconv::stou16(sub)) { case let u: u16 => - yield u; + port = u; case => return invalid_address; }; case void => - return invalid_address; - }; - } else { - yield match (strings::index(addr, ':')) { - case void => - yield match (strconv::stou16(service)) { + match (strconv::stou16(service)) { case let u: u16 => - yield u; - case => - yield 0u16; - }; - case let i: size => - const sub = strings::sub(addr, i + 1, strings::end); - addr = strings::sub(addr, 0, i); - yield match (strconv::stou16(sub)) { - case let u: u16 => - yield u; - case => - return invalid_address; + port = u; + case => yield; }; }; + return (addr, port); }; + // 1.1.1.1:80 (IPv4) + match (strings::index(addr, ':')) { + case void => + match (strconv::stou16(service)) { + case let u: u16 => + port = u; + case => yield; + }; + case let i: size => + const sub = strings::sub(addr, i + 1, strings::end); + addr = strings::sub(addr, 0, i); + match (strconv::stou16(sub)) { + case let u: u16 => + port = u; + case => + return invalid_address; + }; + }; + return (addr, port); +}; + +// Performs DNS resolution on a given address string for a given service, +// including /etc/hosts lookup and SRV resolution, and returns a list of +// candidate IP addresses and the appropriate port, or an error. +// +// The caller must free the [[net::ip::addr]] slice. +export fn resolve( + proto: str, + addr: str, + service: str, +) (([]ip::addr, u16) | error) = { + const (addr, port) = splitaddr(addr, service)?; if (service == "unknown" && port == 0) { return unknown_service; }; diff --git a/net/dns/query.ha b/net/dns/query.ha @@ -20,7 +20,6 @@ def timeout: time::duration = 3 * time::SECOND; // // If no DNS servers are provided, the system default servers (if any) are used. export fn query(query: *message, servers: ip::addr...) (*message | error) = { - // TODO: Use TCP for messages >512 bytes if (len(servers) == 0) { servers = resolvconf::load(); };