hare

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

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:
Anet/unix/+openbsd.ha | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnet/unix/socketpair.ha | 2+-
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 =>