include include include include include import "./core.zc" import "./result.zc" import "./string.zc" import "./mem.zc" def Z_AF_INET = 2; def Z_SOCK_STREAM = 1; // Direct externs for simple socket functions extern fn socket(domain: c_int, type: c_int, proto: c_int) -> c_int; extern fn close(fd: c_int) -> c_int; extern fn read(fd: c_int, buf: void*, count: usize) -> isize; // Minimal raw block: required for struct sockaddr_in usage // These functions encapsulate sockaddr_in setup because the struct layout // cannot be declared in Zen-C without type conflicts with C headers. // Also includes inet_pton, htons, bind, connect, listen, accept wrappers. raw { static int _z_net_bind(int fd, const 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, const 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_write(int fd, const char* buf, size_t n) { return write(fd, (const void*)buf, n); } } extern fn _z_net_bind(fd: c_int, host: const char*, port: c_int) -> c_int; extern fn _z_net_connect(fd: c_int, host: const char*, port: c_int) -> c_int; extern fn _z_net_accept(fd: c_int) -> c_int; extern fn _z_net_write(fd: c_int, buf: const char*, n: usize) -> isize; struct TcpStream { handle: c_int; } extern fn strerror(errnum: c_int) -> char*; impl TcpStream { fn read(self, buf: char*, len: usize) -> Result { let n = read(self.handle - 1, (void*)buf, len); let zero: c_int = 0; if (n < (isize)zero) return Result::Err(strerror(errno)); return Result::Ok((usize)n); } fn write(self, buf: u8*, len: usize) -> Result { let one: c_int = 1; let n: isize = _z_net_write(self.handle - one, buf, len); let zero: isize = 0; if (n < zero) return Result::Err("Write failed"); return Result::Ok((usize)n); } fn close(self) { let zero: c_int = 0; if (self.handle > zero) { let one: c_int = 1; close(self.handle - one); self.handle = zero; } } fn connect(host: char*, port: c_int) -> Result { let zero: c_int = 0; let fd = socket(Z_AF_INET, Z_SOCK_STREAM, zero); if (fd < zero) return Result::Err("Failed to create socket"); // C constants like -1 let neg_one: c_int = -1; let res = _z_net_connect(fd, host, port); if (res == neg_one) { close(fd); return Result::Err("Invalid address"); } // _z_net_connect might return -2? The original code had it. // Assuming -2 is also possible... check implementation or just assume logic was correct. // But wait, the original code had: // if (res == -1) ... if (res == -2) ... // I will keep it but cast strict. let neg_two: c_int = -2; if (res == neg_two) { close(fd); return Result::Err("Connection failed"); } let one: c_int = 1; return Result::Ok(TcpStream { handle: fd + one }); } } impl Drop for TcpStream { fn drop(self) { self.close(); } } struct TcpListener { handle: c_int; } impl TcpListener { fn bind(host: char*, port: c_int) -> Result { let zero: c_int = 0; let fd = socket(Z_AF_INET, Z_SOCK_STREAM, zero); if (fd < zero) return Result::Err("Failed to create socket"); let res = _z_net_bind(fd, host, port); let neg_one: c_int = -1; let neg_two: c_int = -2; let neg_three: c_int = -3; if (res == neg_one) { close(fd); return Result::Err("Invalid address"); } if (res == neg_two) { close(fd); return Result::Err("Bind failed"); } if (res == neg_three) { close(fd); return Result::Err("Listen failed"); } let one: c_int = 1; return Result::Ok(TcpListener { handle: fd + one }); } fn accept(self) -> Result { let one: c_int = 1; let client_fd = _z_net_accept(self.handle - one); let zero: c_int = 0; if (client_fd < zero) return Result::Err("Accept failed"); return Result::Ok(TcpStream { handle: client_fd + one }); } fn close(self) { let zero: c_int = 0; if (self.handle > zero) { let one: c_int = 1; close(self.handle - one); self.handle = zero; } } } impl Drop for TcpListener { fn drop(self) { self.close(); } }