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:
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)?;