hare

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

+linux.ha (2814B)


      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 = 0) (socket | error) = {
     23 	flags ^= rt::SOCK_CLOEXEC: sockflag; // invert CLOEXEC
     24 	const fd = match (rt::accept4(sock, null, null, flags)) {
     25 	case let err: rt::errno =>
     26 		return errors::errno(err);
     27 	case let fd: int =>
     28 		yield fd;
     29 	};
     30 	return io::fdopen(fd);
     31 };
     32 
     33 fn msg_to_native(msg: *msghdr) *rt::msghdr = {
     34 	let native = &msg.native;
     35 	if (len(msg.vectors) != 0) {
     36 		native.msg_iov = msg.vectors: *[*]rt::iovec;
     37 		native.msg_iovlen = len(msg.vectors);
     38 	};
     39 	if (len(msg.control) != 0) {
     40 		native.msg_control = msg.control: *[*]u8;
     41 		native.msg_controllen = len(msg.control);
     42 	};
     43 	return native;
     44 };
     45 
     46 // Sends a message to a socket. See [[newmsg]] for details.
     47 export fn sendmsg(sock: socket, msg: *msghdr) (size | error) = {
     48 	// TODO: Flags
     49 	match (rt::sendmsg(sock, msg_to_native(msg), 0)) {
     50 	case let n: int =>
     51 		return n: size;
     52 	case let err: rt::errno =>
     53 		return errors::errno(err);
     54 	};
     55 };
     56 
     57 // Receives a message from a socket. See [[newmsg]] for details.
     58 export fn recvmsg(sock: socket, msg: *msghdr) (size | error) = {
     59 	// TODO: Flags
     60 	match (rt::recvmsg(sock, msg_to_native(msg), 0)) {
     61 	case let n: int =>
     62 		return n: size;
     63 	case let err: rt::errno =>
     64 		return errors::errno(err);
     65 	};
     66 };
     67 
     68 // Closes a [[socket]]. No further operations against this socket are permitted
     69 // after calling this function. Closing a socket can fail only under certain
     70 // conditions (for example, closing a socket twice, or an interrupted syscall).
     71 // However, the user should not attempt to close the file again on failure - at
     72 // best the user should print a diagnostic message and move on. See close(2) for
     73 // details.
     74 //
     75 // On Linux, this function is an alias for [[io::close]].
     76 export fn close(sock: socket) (void | error) = match (io::close(sock)) {
     77 case void => void;
     78 case io::underread => abort();
     79 case let err: errors::error =>
     80 	yield err;
     81 };
     82 
     83 // Shuts down part of a full-duplex connection.
     84 export fn shutdown(sock: socket, how: shut) (void | error) = {
     85 	match (rt::shutdown(sock, how)) {
     86 	case void => void;
     87 	case let err: rt::errno =>
     88 		return errors::errno(err);
     89 	};
     90 };