hare

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

+freebsd.ha (2924B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use errors;
      5 use io;
      6 use rt;
      7 
      8 // A network socket.
      9 export type socket = io::file;
     10 
     11 // Optional flags to [[accept]] to be set on the returned [[socket]].
     12 // See the O_CLOEXEC and O_NONBLOCK sections of open(2) for details.
     13 // Note that CLOEXEC is on by default, and NOCLOEXEC flag disables it.
     14 export type sockflag = enum int {
     15 	NOCLOEXEC = rt::SOCK_CLOEXEC,
     16 	NONBLOCK = rt::SOCK_NONBLOCK
     17 };
     18 
     19 // Accepts the next connection from a socket. Blocks until a new connection is
     20 // available. Optionally accepts NOCLOEXEC and NONBLOCK flags. If flags are
     21 // supplied, the [[io::file]] returned will have the supplied flags set.
     22 export fn accept(sock: socket, flags: sockflag...) (socket | error) = {
     23 	// Apply any supplied flags
     24 	let f = 0i;
     25 	for (let i = 0z; i < len(flags); i += 1) {
     26 		f |= flags[i];
     27 	};
     28 	f ^= rt::SOCK_CLOEXEC; // invert CLOEXEC
     29 	const fd = match (rt::accept4(sock, null, null, f)) {
     30 	case let err: rt::errno =>
     31 		return errors::errno(err);
     32 	case let fd: int =>
     33 		yield fd;
     34 	};
     35 	return io::fdopen(fd);
     36 };
     37 
     38 fn msg_to_native(msg: *msghdr) *rt::msghdr = {
     39 	let native = &msg.native;
     40 	if (len(msg.vectors) != 0) {
     41 		native.msg_iov = msg.vectors: *[*]rt::iovec;
     42 		native.msg_iovlen = len(msg.vectors): int;
     43 	};
     44 	if (len(msg.control) != 0) {
     45 		native.msg_control = msg.control: *[*]u8;
     46 		native.msg_controllen = len(msg.control): rt::socklen_t;
     47 	};
     48 	return native;
     49 };
     50 
     51 // Sends a message to a socket. See [[newmsg]] for details.
     52 export fn sendmsg(sock: socket, msg: *msghdr) (size | error) = {
     53 	// TODO: Flags
     54 	match (rt::sendmsg(sock, msg_to_native(msg), 0)) {
     55 	case let n: int =>
     56 		return n: size;
     57 	case let err: rt::errno =>
     58 		return errors::errno(err);
     59 	};
     60 };
     61 
     62 // Receives a message from a socket. See [[newmsg]] for details.
     63 export fn recvmsg(sock: socket, msg: *msghdr) (size | error) = {
     64 	// TODO: Flags
     65 	match (rt::recvmsg(sock, msg_to_native(msg), 0)) {
     66 	case let n: int =>
     67 		return n: size;
     68 	case let err: rt::errno =>
     69 		return errors::errno(err);
     70 	};
     71 };
     72 
     73 // Closes a [[socket]]. No further operations against this socket are permitted
     74 // after calling this function. Closing a socket can fail only under certain
     75 // conditions (for example, closing a socket twice, or an interrupted syscall).
     76 // However, the user should not attempt to close the file again on failure - at
     77 // best the user should print a diagnostic message and move on. See close(2) for
     78 // details.
     79 //
     80 // On FreeBSD, this function is an alias for [[io::close]].
     81 export fn close(sock: socket) (void | error) = match (io::close(sock)) {
     82 case void => void;
     83 case io::underread => abort();
     84 case let err: errors::error =>
     85 	yield err;
     86 };
     87 
     88 // Shuts down part of a full-duplex connection.
     89 export fn shutdown(sock: socket, how: shut) (void | error) = {
     90 	match (rt::shutdown(sock, how)) {
     91 	case void => void;
     92 	case let err: rt::errno =>
     93 		return errors::errno(err);
     94 	};
     95 };