+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 };