summaryrefslogtreecommitdiff
path: root/std/net.zc
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
commitba5ee94871e670fbe1ea091dd5731e593df0b29f (patch)
tree3b706a9ab11effa4acb094482f3d657c986ef501 /std/net.zc
parentaba9191ab3ef0699b0f9507ee3d03161f9ee7771 (diff)
Some std for you
Diffstat (limited to 'std/net.zc')
-rw-r--r--std/net.zc128
1 files changed, 128 insertions, 0 deletions
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 <sys/socket.h>;
+include <netinet/in.h>;
+include <arpa/inet.h>;
+include <unistd.h>;
+include <errno.h>;
+
+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<usize> {
+ var n = _z_net_read(self.fd, buf, len);
+ if (n < 0) return Result<usize>::Err("Read failed");
+ return Result<usize>::Ok((usize)n);
+ }
+
+ fn write(self, buf: char*, len: usize) -> Result<usize> {
+ var n = _z_net_write(self.fd, buf, len);
+ if (n < 0) return Result<usize>::Err("Write failed");
+ return Result<usize>::Ok((usize)n);
+ }
+
+ fn close(self) {
+ if (self.fd >= 0) {
+ close(self.fd);
+ self.fd = -1;
+ }
+ }
+
+ fn connect(host: char*, port: int) -> Result<TcpStream> {
+ var fd = socket(Z_AF_INET, Z_SOCK_STREAM, 0);
+ if (fd < 0) return Result<TcpStream>::Err("Failed to create socket");
+
+ var res = _z_net_connect(fd, host, port);
+ if (res == -1) { close(fd); return Result<TcpStream>::Err("Invalid address"); }
+ if (res == -2) { close(fd); return Result<TcpStream>::Err("Connection failed"); }
+
+ return Result<TcpStream>::Ok(TcpStream { fd: fd });
+ }
+}
+
+struct TcpListener {
+ fd: int;
+}
+
+impl TcpListener {
+ fn bind(host: char*, port: int) -> Result<TcpListener> {
+ var fd = socket(Z_AF_INET, Z_SOCK_STREAM, 0);
+ if (fd < 0) return Result<TcpListener>::Err("Failed to create socket");
+
+ var res = _z_net_bind(fd, host, port);
+ if (res == -1) { close(fd); return Result<TcpListener>::Err("Invalid address"); }
+ if (res == -2) { close(fd); return Result<TcpListener>::Err("Bind failed"); }
+ if (res == -3) { close(fd); return Result<TcpListener>::Err("Listen failed"); }
+
+ return Result<TcpListener>::Ok(TcpListener { fd: fd });
+ }
+
+ fn accept(self) -> Result<TcpStream> {
+ var client_fd = _z_net_accept(self.fd);
+ if (client_fd < 0) return Result<TcpStream>::Err("Accept failed");
+ return Result<TcpStream>::Ok(TcpStream { fd: client_fd });
+ }
+
+ fn close(self) {
+ if (self.fd >= 0) {
+ close(self.fd);
+ self.fd = -1;
+ }
+ }
+}