hare

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

commit 455ed760ef4d743d5793d4d9d912577f334e308e
parent 84664ea8962ff2c71b274728c3ef8014c0af10d0
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 10 Feb 2023 10:25:47 +0100

net::dial: add dial_uri

Also updates net::uri to skip the scheme if unset.

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

Diffstat:
Mnet/dial/dial.ha | 33+++++++++++++++++++++++++++++++++
Mnet/uri/fmt.ha | 4+++-
2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/net/dial/dial.ha b/net/dial/dial.ha @@ -1,6 +1,10 @@ // License: MPL-2.0 // (c) 2021 Drew DeVault <sir@cmpwn.com> +use errors; +use fmt; use net; +use net::ip; +use net::uri; // Dials a remote address, establishing a connection and returning the resulting // [[net::socket]]. The proto parameter should be the transport protocol (e.g. @@ -49,3 +53,32 @@ export fn dial( }; return net::unknownproto: net::error; }; + +def HOST_MAX: size = 255; + +// Performs a [[dial]] operation for a given URI, taking the service name from +// the URI scheme and forming an address from the URI host and port. +export fn dial_uri(proto: str, uri: *uri::uri) (net::socket | error) = { + // XXX: Should the code to convert a URI to e.g. "[::1]:80" be + // generalized for end-user use? + if (uri.host is str && len(uri.host as str) > HOST_MAX) { + return invalid_address; + }; + static let addr: [HOST_MAX + len("[]:65535")]u8 = [0...]; + + const colon = if (uri.port != 0) ":" else ""; + const port: fmt::formattable = if (uri.port != 0) uri.port else ""; + + let addr = match (uri.host) { + case let host: str => + yield fmt::bsprintf(addr, "{}{}{}", host, colon, port); + case let ip: ip::addr4 => + const host = ip::string(ip); + yield fmt::bsprintf(addr, "{}{}{}", host, colon, port); + case let ip: ip::addr6 => + const host = ip::string(ip); + yield fmt::bsprintf(addr, "[{}]{}{}", host, colon, port); + }; + + return dial(proto, addr, uri.scheme); +}; diff --git a/net/uri/fmt.ha b/net/uri/fmt.ha @@ -27,7 +27,9 @@ def unres_path: str = "-._~!$&'()*+,;=:@/"; export fn fmt(out: io::handle, u: *const uri) (size | io::error) = { let n = 0z; let slashes_w = false; - n += fmt::fprintf(out, "{}:", u.scheme)?; + if (u.scheme != "") { + n += fmt::fprintf(out, "{}:", u.scheme)?; + }; if (len(u.userinfo) > 0) { assert(!(u.host is str) || len(u.host as str) > 0); n += fmt::fprintf(out, "//{}@", u.userinfo)?;