module netio import os #include #include fn C.socket(i32, i32, i32) i32 fn C.bind(i32, voidptr, i32) i32 fn C.connect(i32, voidptr, i32) i32 fn C.listen(i32, i32) i32 fn C.accept(i32, voidptr, voidptr) i32 fn C.shutdown(i32, i32) i32 fn C.close(i32) i32 fn C.setsockopt(i32, i32, i32, voidptr, i32) i32 fn C.getsockopt(i32, i32, i32, voidptr, i32) i32 struct C.sockaddr_storage {} pub struct Socket { pub: fd int = -1 } // Socket.new creates new socket. // See [socket(7)](https://www.man7.org/linux/man-pages/man7/socket.7.html) and // [socket(3)](https://man7.org/linux/man-pages/man3/socket.3p.html) for details. pub fn Socket.new(domain AddrFamily, typ SocketType, protocol Protocol) !Socket { fd := C.socket(i32(domain), i32(typ), i32(protocol)) if fd == -1 { return os.last_error() } return Socket{ fd: fd } } // typeof reports the actual socket type. pub fn (s Socket) typeof() !SocketType { return s.get_option_int(C.SOL_SOCKET, C.SO_TYPE)! } // Socket shutdown modes. See [shutdown(3p)](https://man7.org/linux/man-pages/man3/shutdown.3p.html) for details. pub enum Shutdown { read = C.SHUT_RD write = C.SHUT_WR read_and_write = C.SHUT_RDWR } // connect connects a socket. pub fn (s Socket) connect(addr SocketAddr) ! { if C.connect(s.fd, addr.ptr(), addr.size()) == -1 { return os.last_error() } } // bind binds a name to a socket. pub fn (s Socket) bind(addr SocketAddr) ! { if C.bind(s.fd, addr.ptr(), addr.size()) == -1 { return os.last_error() } } // listen starts listening for socket connections and limit the queue of incoming connections. pub fn (s Socket) listen(backlog int) ! { if C.listen(s.fd, backlog) == -1 { return os.last_error() } } // accept accepts a new connection on a socket. // The return values are the new socket connected to remote and the remote socket address. pub fn (s Socket) accept() !(Socket, SocketAddr) { mut sock_addr_storage := &C.sockaddr_storage{} mut sock_addr_len := sizeof(C.sockaddr_storage) fd := C.accept(s.fd, sock_addr_storage, &sock_addr_len) if fd == -1 { return os.last_error() } sock := Socket{ fd: fd } sock_addr := unsafe { SocketAddr.from_ptr(sock_addr_storage, sock_addr_len)! } return sock, sock_addr } // set_option sets the socket option. pub fn (s Socket) set_option(level SocketLevel, option SocketOption, value int) ! { if C.setsockopt(s.fd, i32(level), i32(option), i32(value), sizeof(value)) == -1 { return os.last_error() } } // get_option gets the socket option as int. pub fn (s Socket) get_option_int(level SocketLevel, option SocketOption) !int { mut result := 0 if C.getsockopt(s.fd, i32(level), i32(option), &result, sizeof(result)) == -1 { return os.last_error() } return result } // shutdown shut downs socket send and receive operations. pub fn (s Socket) shutdown(how Shutdown) ! { if C.shutdown(s.fd, i32(how)) == -1 { return os.last_error() } } // close closes the socket. pub fn (s Socket) close() ! { if C.close(s.fd) == -1 { return os.last_error() } }