From ba5ee94871e670fbe1ea091dd5731e593df0b29f Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Sun, 11 Jan 2026 17:47:30 +0000 Subject: Some std for you --- std/net.zc | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 std/net.zc (limited to 'std/net.zc') diff --git a/std/net.zc b/std/net.zc new file mode 100644 index 0000000..996ddeb --- /dev/null +++ b/std/net.zc @@ -0,0 +1,128 @@ + +include ; +include ; +include ; +include ; +include ; + +import "./core.zc" +import "./result.zc" +import "./string.zc" + +const Z_AF_INET = 2; +const Z_SOCK_STREAM = 1; + +raw { + static int _z_net_bind(int fd, char *host, int port) { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) return -1; // Invalid addr + + int opt = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) return -2; // Bind fail + if (listen(fd, 10) < 0) return -3; // Listen fail + return 0; + } + + static int _z_net_connect(int fd, char *host, int port) { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) return -1; + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) return -2; + return 0; + } + + static int _z_net_accept(int fd) { + return accept(fd, NULL, NULL); + } + + static ssize_t _z_net_read(int fd, char* buf, size_t n) { + return read(fd, (void*)buf, n); + } + + static ssize_t _z_net_write(int fd, char* buf, size_t n) { + return write(fd, (const void*)buf, n); + } +} + +extern fn socket(domain: int, type: int, proto: int) -> int; +extern fn close(fd: int) -> int; + +extern fn _z_net_bind(fd: int, host: char*, port: int) -> int; +extern fn _z_net_connect(fd: int, host: char*, port: int) -> int; +extern fn _z_net_accept(fd: int) -> int; +extern fn _z_net_read(fd: int, buf: char*, n: usize) -> isize; +extern fn _z_net_write(fd: int, buf: char*, n: usize) -> isize; + + +struct TcpStream { + fd: int; +} + +impl TcpStream { + fn read(self, buf: char*, len: usize) -> Result { + var n = _z_net_read(self.fd, buf, len); + if (n < 0) return Result::Err("Read failed"); + return Result::Ok((usize)n); + } + + fn write(self, buf: char*, len: usize) -> Result { + var n = _z_net_write(self.fd, buf, len); + if (n < 0) return Result::Err("Write failed"); + return Result::Ok((usize)n); + } + + fn close(self) { + if (self.fd >= 0) { + close(self.fd); + self.fd = -1; + } + } + + fn connect(host: char*, port: int) -> Result { + var fd = socket(Z_AF_INET, Z_SOCK_STREAM, 0); + if (fd < 0) return Result::Err("Failed to create socket"); + + var res = _z_net_connect(fd, host, port); + if (res == -1) { close(fd); return Result::Err("Invalid address"); } + if (res == -2) { close(fd); return Result::Err("Connection failed"); } + + return Result::Ok(TcpStream { fd: fd }); + } +} + +struct TcpListener { + fd: int; +} + +impl TcpListener { + fn bind(host: char*, port: int) -> Result { + var fd = socket(Z_AF_INET, Z_SOCK_STREAM, 0); + if (fd < 0) return Result::Err("Failed to create socket"); + + var res = _z_net_bind(fd, host, port); + if (res == -1) { close(fd); return Result::Err("Invalid address"); } + if (res == -2) { close(fd); return Result::Err("Bind failed"); } + if (res == -3) { close(fd); return Result::Err("Listen failed"); } + + return Result::Ok(TcpListener { fd: fd }); + } + + fn accept(self) -> Result { + var client_fd = _z_net_accept(self.fd); + if (client_fd < 0) return Result::Err("Accept failed"); + return Result::Ok(TcpStream { fd: client_fd }); + } + + fn close(self) { + if (self.fd >= 0) { + close(self.fd); + self.fd = -1; + } + } +} -- cgit v1.2.3