// net — minimal TCP. Sketched against the Linux syscall numbers // 41 (socket), 42 (connect), 43 (accept), 49 (bind), 50 (listen). // Real applications will want addrinfo + DNS; we leave that to // higher layers. package net; @symbol("rt_syscall") fn syscall0(num: i64) i64; @symbol("rt_syscall") fn syscall3(num: i64, a: i64, b: i64, c: i64) i64; def AF_INET: i32 = 2; def SOCK_STREAM:i32 = 1; def IPPROTO_TCP:i32 = 6; def SYS_SOCKET: i64 = 41; def SYS_CONNECT: i64 = 42; def SYS_ACCEPT: i64 = 43; def SYS_BIND: i64 = 49; def SYS_LISTEN: i64 = 50; // sockaddrin is laid out by the kernel: family u16, port u16 (BE), // addr u32 (BE), padding 8B = 16B total. Caller fills it. type sockaddrin = struct { family: u16, port: u16, addr: u32, pad0: u64, }; export fn socket() i32 = { return syscall3(SYS_SOCKET, AF_INET: i64, SOCK_STREAM: i64, IPPROTO_TCP: i64): i32; }; export fn connect(fd: i32, sa: *sockaddrin) i32 = { return syscall3(SYS_CONNECT, fd: i64, sa: i64, 16): i32; }; export fn bind(fd: i32, sa: *sockaddrin) i32 = { return syscall3(SYS_BIND, fd: i64, sa: i64, 16): i32; }; export fn listen(fd: i32, backlog: i32) i32 = { return syscall3(SYS_LISTEN, fd: i64, backlog: i64, 0): i32; }; // Byte-order conversions live in lib/endian (Hare's endian::htonu16 // is the canonical name). Use `endian.htonu16` to put a port into // network order.