hare

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

+linux.ha (2840B)


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