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:
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();
};