commit ee80f4f705a90dd2fe32381f070c7ab225589412
parent a4241309ff1f31a4af7bb9ddfb80ece41e13fabc
Author: Lorenz (xha) <me@xha.li>
Date: Sat, 25 Nov 2023 15:18:25 +0100
OpenBSD: add net::unix
Signed-off-by: Lorenz (xha) <me@xha.li>
Diffstat:
2 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/net/unix/+openbsd.ha b/net/unix/+openbsd.ha
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use errors;
+use fmt;
+use io;
+use net;
+use os;
+use rt;
+use strings;
+use types;
+
+// Opens a UNIX socket connection to the path. Blocks until the connection is
+// established.
+export fn connect(
+ addr: addr,
+ options: connect_option...
+) (net::socket | net::error) = {
+ let sockaddr = match (to_native(addr)) {
+ case let a: rt::sockaddr =>
+ yield a;
+ case invalid =>
+ return errors::unsupported; // path too long
+ };
+ let flags = 0i;
+ for (let i = 0z; i < len(options); i += 1) {
+ // Only sockflag for now
+ flags |= options[i];
+ };
+ flags ^= rt::SOCK_CLOEXEC; // invert CLOEXEC
+ const sockfd = match (rt::socket(rt::AF_UNIX: int, rt::SOCK_STREAM | flags, 0)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let fd: int =>
+ yield fd;
+ };
+
+ const sz = size(rt::sockaddr_un): u32;
+ match (rt::connect(sockfd, &sockaddr, sz)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case int => void;
+ };
+ return io::fdopen(sockfd);
+};
+
+// Binds a UNIX socket to the given path.
+export fn listen(
+ addr: addr,
+ options: listen_option...
+) (net::socket | net::error) = {
+ let sockaddr = match (to_native(addr)) {
+ case let a: rt::sockaddr =>
+ yield a;
+ case invalid =>
+ return errors::unsupported; // path too long
+ };
+ let f = 0i;
+ for (let i = 0z; i < len(options); i += 1) {
+ match (options[i]) {
+ case let fl: net::sockflag =>
+ f |= fl;
+ case => void;
+ };
+ };
+ f ^= rt::SOCK_CLOEXEC; // invert CLOEXEC
+ const sockfd = match (rt::socket(rt::AF_UNIX: int, rt::SOCK_STREAM | f, 0)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case let fd: int =>
+ yield fd;
+ };
+
+ let bk: u32 = 10;
+ for (let i = 0z; i < len(options); i += 1) {
+ match (options[i]) {
+ case let b: backlog =>
+ bk = b;
+ case => void;
+ };
+ };
+
+ match (rt::bind(sockfd, &sockaddr, size(rt::sockaddr_un): u32)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case int => void;
+ };
+ match (rt::listen(sockfd, bk)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case int => void;
+ };
+
+ return sockfd;
+};
+
+// Converts a UNIX socket address to a native sockaddr.
+fn to_native(addr: addr) (rt::sockaddr | invalid) = {
+ // sun_path should be NUL-terminated and fit into rt::UNIX_PATH_MAX
+ if (len(addr) > rt::UNIX_PATH_MAX - 1) {
+ return invalid;
+ };
+ let ret = rt::sockaddr {
+ un = rt::sockaddr_un {
+ sun_len = size(rt::sockaddr_un): u8,
+ sun_family = rt::AF_UNIX,
+ ...
+ }
+ };
+ match ((&addr: *types::string).data) {
+ case null => void;
+ case let data: *[*]u8 =>
+ ret.un.sun_path[..len(addr)] = data[..len(addr)];
+ };
+ ret.un.sun_path[len(addr)] = 0;
+ return ret;
+};
diff --git a/net/unix/socketpair.ha b/net/unix/socketpair.ha
@@ -16,7 +16,7 @@ export fn socketpair(flags: net::sockflag...) ((net::socket, net::socket) | net:
f |= flags[i];
};
f ^= rt::SOCK_CLOEXEC; // invert CLOEXEC
- match (rt::socketpair(rt::AF_UNIX : int, (rt::SOCK_STREAM | f) : int, 0, &sv)) {
+ match (rt::socketpair(rt::AF_UNIX: int, (rt::SOCK_STREAM | f): int, 0, &sv)) {
case let err: rt::errno =>
return errors::errno(err);
case =>