// std.socket nonblocking surface (PLAN-HTTPZ S2): set_nonblocking via // the C-variadic fcntl, and the typed _nb wrappers' full result // algebra — bytes, WouldBlock, Closed — on a unix socketpair, plus // accept_nb on a nonblocking TCP listener (WouldBlock with an empty // backlog, a connection after a loopback connect). #import "modules/std.sx"; PORT :: 18931; main :: () -> i32 { // ── socketpair: read/write algebra ──────────────────────────────── pair : [2]i32 = ---; if socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0, @pair[0]) != 0 { print("socketpair failed\n"); return 1; } a := pair[0]; b := pair[1]; if !socket.set_nonblocking(a) or !socket.set_nonblocking(b) { print("set_nonblocking failed\n"); return 1; } buf : [16]u8 = ---; n, e := socket.read_nb(a, @buf[0], 16); if e != error.WouldBlock { print("empty pair read: expected WouldBlock\n"); return 1; } print("empty read: WouldBlock\n"); msg := "ping"; wn, we := socket.write_nb(b, msg.ptr, 4); if we { print("write_nb failed\n"); return 1; } if wn != 4 { print("short write: {}\n", wn); return 1; } rn, re := socket.read_nb(a, @buf[0], 16); if re { print("read_nb after write failed\n"); return 1; } if rn != 4 { print("short read: {}\n", rn); return 1; } print("pair round trip: {} bytes\n", rn); socket.close(b); cn, ce := socket.read_nb(a, @buf[0], 16); if ce != error.Closed { print("read after peer close: expected Closed\n"); return 1; } print("peer close: Closed\n"); socket.close(a); // ── nonblocking listener: accept_nb ─────────────────────────────── lfd := socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0); if lfd < 0 { print("listener socket failed\n"); return 1; } one : i32 = 1; socket.setsockopt(lfd, socket.SOL_SOCKET, socket.SO_REUSEADDR, @one, 4); addr : socket.SockAddr = .{ sin_len = 16, sin_family = xx socket.AF_INET, sin_port = socket.htons(PORT), sin_addr = 0x0100007F, // 127.0.0.1 }; if socket.bind(lfd, @addr, 16) != 0 { print("bind failed\n"); return 1; } if socket.listen(lfd, 4) != 0 { print("listen failed\n"); return 1; } if !socket.set_nonblocking(lfd) { print("listener set_nonblocking failed\n"); return 1; } afd, ae := socket.accept_nb(lfd); if ae != error.WouldBlock { print("empty backlog: expected WouldBlock\n"); return 1; } print("empty backlog: WouldBlock\n"); // A blocking loopback connect completes the handshake against the // listen queue without an accept having run yet. cfd := socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0); if cfd < 0 { print("client socket failed\n"); return 1; } if socket.connect(cfd, @addr, 16) != 0 { print("connect failed: errno {}\n", socket.errno()); return 1; } got := -1; tries := 0; while got < 0 and tries < 1000 { c2, ae2 := socket.accept_nb(lfd); if !ae2 { got = xx c2; } else if ae2 != error.WouldBlock { print("accept_nb fault\n"); return 1; } tries += 1; } if got < 0 { print("accept never produced the connection\n"); return 1; } print("accept after connect: ok\n"); socket.close(xx got); socket.close(cfd); socket.close(lfd); print("socket nonblocking ok\n"); return 0; }