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