udp sockets

This commit is contained in:
2026-03-12 16:57:28 +01:00
parent c67abf5a8e
commit f21abaafff
2 changed files with 83 additions and 23 deletions

View File

@@ -148,7 +148,7 @@ func mem.realloc[x: ptr, new_size: i64] : ptr
if !new_ptr if !new_ptr
return 0 return 0
mem.copy(x, new_ptr, blk->size) mem.copy(x, new_ptr, math.min(blk->size, new_size))
mem.free(x) mem.free(x)
return new_ptr return new_ptr
@@ -236,11 +236,7 @@ func io.read_line[]: str
return buffer return buffer
func io.file_exists[path: str] : bool func io.file_exists[path: str] : bool
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0) return _builtin_syscall(SYS_faccessat, -100, path, 0, 0) == 0
if fd >= 0
_builtin_syscall(SYS_close, fd)
return true
return false
func io.read_file[path: str] : str func io.read_file[path: str] : str
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0) let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
@@ -275,7 +271,7 @@ func io.read_binary_file[path: str] : io.Buffer
return buffer return buffer
func io.write_file[path: str, content: str] : void func io.write_file[path: str, content: str] : void
let fd: ptr = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644) let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
if fd < 0 if fd < 0
panic("failed to open file") // TODO panic("failed to open file") // TODO
@@ -283,7 +279,7 @@ func io.write_file[path: str, content: str] : void
_builtin_syscall(SYS_close, fd) _builtin_syscall(SYS_close, fd)
func io.write_binary_file[path: str, content: ptr, size: i64] : void func io.write_binary_file[path: str, content: ptr, size: i64] : void
let fd: ptr = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644) let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644)
if fd < 0 if fd < 0
panic("failed to open file") // TODO panic("failed to open file") // TODO
@@ -296,7 +292,7 @@ func str.len[s: str] : i64
i = i + 1 i = i + 1
return i return i
func str.copy[s: str] : str func str.make_copy[s: str] : str
let size: i64 = str.len(s) + 1 let size: i64 = str.len(s) + 1
let dup: str = mem.alloc(size) let dup: str = mem.alloc(size)
mem.copy(s, dup, size) mem.copy(s, dup, size)
@@ -429,7 +425,10 @@ func str.reverse[s: str] : str
// not sure this covers all the wacky edge cases // not sure this covers all the wacky edge cases
func str.from_i64[n: i64] : str func str.from_i64[n: i64] : str
if n == 0 if n == 0
return str.copy("0") let out: str = mem.alloc(2)
out[0] = '0'
out[1] = 0
return out
let neg: bool = n < 0 let neg: bool = n < 0
if neg if neg
@@ -717,9 +716,12 @@ func os.getpid[] : i64
return _builtin_syscall(SYS_getpid) return _builtin_syscall(SYS_getpid)
func os.sleep[ms: i64] : void func os.sleep[ms: i64] : void
if ms < 0
panic("negative time passed to os.sleep")
// TODO: we really shouldnt need a heap allocation to sleep // TODO: we really shouldnt need a heap allocation to sleep
let req: os.Timeval = new os.Timeval let req: os.Timeval = new os.Timeval
req->tv_sec = ms / 1000 req->tv_sec = ms / 1000
// yes, we should have a os.Timespec with tv_nsec but this works for now
req->tv_usec = (ms % 1000) * 1000000 req->tv_usec = (ms % 1000) * 1000000
_builtin_syscall(SYS_nanosleep, req, 0) _builtin_syscall(SYS_nanosleep, req, 0)
mem.free(req) mem.free(req)
@@ -750,7 +752,7 @@ func os.time[] : i64
return out return out
// voodoo magic // voodoo magic
func os.shell[command: str] : i64 func os.run_shell_command[command: str] : i64
let pid: i64 = _builtin_syscall(SYS_fork) let pid: i64 = _builtin_syscall(SYS_fork)
if pid == 0 if pid == 0
let argv: Array = ["sh", "-c", command, 0] // gets freed after child process exits let argv: Array = ["sh", "-c", command, 0] // gets freed after child process exits
@@ -768,7 +770,7 @@ func os.shell[command: str] : i64
else else
return -(st & 0x7f) return -(st & 0x7f)
func os.listdir[path: str] : Array func os.list_directory[path: str] : Array
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0) let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
if fd < 0 if fd < 0
return [] return []
@@ -794,21 +796,26 @@ func os.listdir[path: str] : Array
if name[2] == 0 if name[2] == 0
skip = true skip = true
if !skip if !skip
array.push(files, str.copy(name)) array.push(files, str.make_copy(name))
pos = pos + len pos = pos + len
mem.free(buf) mem.free(buf)
_builtin_syscall(SYS_close, fd) _builtin_syscall(SYS_close, fd)
return files return files
const AF_INET = 2
const SOCK_STREAM = 1
const SOCK_DGRAM = 2
const SOL_SOCKET = 1
const SO_REUSEADDR = 4
func net.listen[packed_host: i64, port: i64] : i64 func net.listen[packed_host: i64, port: i64] : i64
let s: i64 = _builtin_syscall(SYS_socket, 2, 1, 0) let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
if s < 0 if s < 0
return -1 return -1
// setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
let optval = 1 let optval = 1
if _builtin_syscall(SYS_setsockopt, s, 1, 2, ^optval, 8) < 0 if _builtin_syscall(SYS_setsockopt, s, SOL_SOCKET, SO_REUSEADDR, ^optval, 8) < 0
_builtin_syscall(SYS_close, s) _builtin_syscall(SYS_close, s)
return -1 return -1
@@ -837,13 +844,13 @@ func net.listen[packed_host: i64, port: i64] : i64
// TODO: resolve DNS // TODO: resolve DNS
func net.connect[packed_host: i64, port: i64] : i64 func net.connect[packed_host: i64, port: i64] : i64
let s: i64 = _builtin_syscall(SYS_socket, 2, 1, 0) let s: i64 = _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
if s < 0 if s < 0
return -1 return -1
let sa: ptr = mem.alloc(16) let sa: ptr = mem.alloc(16)
mem.zero(sa, 16) mem.zero(sa, 16)
sa[0] = 2 sa[0] = AF_INET
sa[1] = 0 sa[1] = 0
sa[2] = (port >> 8) & 255 sa[2] = (port >> 8) & 255
sa[3] = port & 255 sa[3] = port & 255
@@ -863,7 +870,7 @@ func net.connect[packed_host: i64, port: i64] : i64
func net.accept[s: i64] : i64 func net.accept[s: i64] : i64
return _builtin_syscall(SYS_accept, s, 0, 0) return _builtin_syscall(SYS_accept, s, 0, 0)
func net.send[s: i64, data: str, size: i64] : void func net.send[s: i64, data: ptr, size: i64] : void
_builtin_syscall(SYS_sendto, s, data, size, 0, 0, 0) _builtin_syscall(SYS_sendto, s, data, size, 0, 0, 0)
func net.read[s: i64, buffer: ptr, size: i64] : i64 func net.read[s: i64, buffer: ptr, size: i64] : i64
@@ -874,3 +881,56 @@ func net.close[s: i64] : void
func net.pack_addr[a: i64, b: i64, c: i64, d: i64] : i64 func net.pack_addr[a: i64, b: i64, c: i64, d: i64] : i64
return (a << 24) | (b << 16) | (c << 8) | d return (a << 24) | (b << 16) | (c << 8) | d
struct net.UDPSocket
fd: i64
addr: ptr
struct net.UDPPacket
buffer: ptr
source_addr: ptr
size: i64
func net.create_udp_socket[packed_host: i64, port: i64] : net.UDPSocket
let s: net.UDPSocket = new net.UDPSocket
s->fd = _builtin_syscall(SYS_socket, AF_INET, SOCK_DGRAM, 0)
if s->fd < 0
mem.free(s)
return 0
s->addr = mem.alloc(16)
mem.zero(s->addr, 16)
s->addr[0] = AF_INET
s->addr[1] = 0
s->addr[2] = (port >> 8) & 255
s->addr[3] = port & 255
s->addr[4] = (packed_host >> 24) & 255
s->addr[5] = (packed_host >> 16) & 255
s->addr[6] = (packed_host >> 8) & 255
s->addr[7] = packed_host & 255
return s
func net.udp_send[s: net.UDPSocket, data: ptr, size: i64] : void
_builtin_syscall(SYS_sendto, s->fd, data, size, 0, s->addr, 16)
func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
let pkt: net.UDPPacket = new net.UDPPacket
pkt->buffer = mem.alloc(size)
pkt->size = size
pkt->source_addr = mem.alloc(16)
mem.zero(pkt->source_addr, 16)
let addrlen: i64 = 16
_builtin_syscall(SYS_recvfrom, s->fd, pkt->buffer, size, 0, pkt->source_addr, ^addrlen)
return pkt
func net.udp_close_and_free[s: net.UDPSocket] : void
_builtin_syscall(SYS_close, s->fd)
mem.free(s->addr)
mem.free(s)
func net.udp_free_packet[pkt: net.UDPPacket] : void
mem.free(pkt->buffer)
mem.free(pkt->source_addr)
mem.free(pkt)

View File

@@ -14,7 +14,7 @@ func run_test[x: str] : void
io.print("... ") io.print("... ")
let build_start_time: i64 = os.time() let build_start_time: i64 = os.time()
if os.shell(str.concat("./target/release/zern ", x)) != 0 if os.run_shell_command(str.concat("./target/release/zern ", x)) != 0
os.exit(1) os.exit(1)
let build_end_time: i64 = os.time() let build_end_time: i64 = os.time()
@@ -39,7 +39,7 @@ func run_test[x: str] : void
run_cmd = str.concat(run_cmd, " test.zr") run_cmd = str.concat(run_cmd, " test.zr")
let run_start_time: i64 = os.time() let run_start_time: i64 = os.time()
if os.shell(run_cmd) != 0 if os.run_shell_command(run_cmd) != 0
os.exit(1) os.exit(1)
let run_end_time: i64 = os.time() let run_end_time: i64 = os.time()
@@ -50,14 +50,14 @@ func run_test[x: str] : void
io.println("ms") io.println("ms")
func run_directory[dir: str] : void func run_directory[dir: str] : void
let files: Array = os.listdir(dir) let files: Array = os.list_directory(dir)
for i in 0..files->size for i in 0..files->size
run_test(str.concat(dir, array.nth(files, i))) run_test(str.concat(dir, array.nth(files, i)))
array.free(files) array.free(files)
func main[] : i64 func main[] : i64
os.shell("cargo build --release") os.run_shell_command("cargo build --release")
run_directory("examples/") run_directory("examples/")
run_directory("examples/puzzles/") run_directory("examples/puzzles/")