nx_udp_loopback.nx source
↩ module page · 82 lines · 3831 B
1// nx_udp_loopback.nx -- proves SOVEREIGN UDP sockets on the nx_syscalls (rv64->x86_64) layer,
2// the foundation the tracker announce round-trip (X-TORRENT-LIVE-001 R2b) needs. The existing UDP
3// organs ride OTHER syscall layers (nx_udp.nx -> nx_syscalls_x86_64, net.nx -> syscalls.nx); the
4// tracker build/parse (nx_udp_tracker) is on nx_syscalls.nx, so this proves the round-trip plumbing
5// on THAT layer to avoid a mixed-layer conflict. Pattern (the proven H2 fork-server+client loopback):
6// bind the server socket BEFORE fork (eliminates the bind/send race) + SO_RCV/SNDTIMEO (no-hang law:
7// every recvfrom is bounded). Child = echo server (inherits the bound fd); parent = client; assert
8// the echo round-trips byte-exact over 127.0.0.1. Self-gating. license_tier: ORIGINAL
9//
10// module: nishi-core.torrent.udp_loopback
11// depends: nishi-core.sys.syscalls
12// capability: SOVEREIGN_UDP_ROUNDTRIP
13import "nx_syscalls.nx"
14import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
15const K_MAGIC_53117: i64 = 53117
16
17func ul_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
18// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
19// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
20// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
21// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
22func ul_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
23
24// fill a 16-byte sockaddr_in: AF_INET + port(BE) + addr(network order) + 8 pad.
25func ul_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 {
26 sa[0] = 2 as u8; sa[1] = 0 as u8
27 sa[2] = ((port >> 8) & 0xff) as u8; sa[3] = (port & 0xff) as u8
28 sa[4] = i0 as u8; sa[5] = i1 as u8; sa[6] = i2 as u8; sa[7] = i3 as u8
29 var k: i64 = 8
30 while k < 16 { sa[k] = 0 as u8; k = k + 1 }
31 return 0
32}
33
34func main() -> i64 {
35 let PORT: i64 = K_MAGIC_53117
36 let sa: *u8 = sys_mmap(16)
37 ul_sockaddr(sa, PORT, 127, 0, 0, 1)
38 let sfd: i64 = sys_socket(AF_INET, SOCK_DGRAM, 0)
39 var bound: i64 = 0
40 if sfd >= 0 {
41 sys_set_socket_timeout(sfd, 2)
42 if sys_bind(sfd, sa, 16) >= 0 { bound = 1 }
43 }
44 if bound == 0 {
45 ul_w(1, "UDPLOOP-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1
46 }
47 let pid: i64 = sys_fork()
48 if pid == 0 {
49 // CHILD = echo server on the inherited, already-bound sfd.
50 let rbuf: *u8 = sys_mmap(512)
51 let src: *u8 = sys_mmap(16)
52 let slen: *i64 = sys_mmap(16) as *i64; slen[0] = 16
53 let n: i64 = sys_recvfrom(sfd, rbuf, 512, 0, src, slen)
54 if n > 0 { sys_sendto(sfd, rbuf, n, 0, src, slen[0]) }
55 sys_close(sfd)
56 sys_exit(0)
57 }
58 // PARENT = client.
59 let cfd: i64 = sys_socket(AF_INET, SOCK_DGRAM, 0)
60 sys_set_socket_timeout(cfd, 2)
61 let dest: *u8 = sys_mmap(16)
62 ul_sockaddr(dest, PORT, 127, 0, 0, 1)
63 let msg: *u8 = "NX-UDP-ECHO-PROBE" as *u8
64 let mlen: i64 = 17
65 sys_sendto(cfd, msg, mlen, 0, dest, 16)
66 let rbuf2: *u8 = sys_mmap(512)
67 let n2: i64 = sys_recvfrom(cfd, rbuf2, 512, 0, 0 as *u8, 0 as *i64)
68 var matched: i64 = 0
69 if n2 == mlen {
70 var i: i64 = 0; var ok: i64 = 1
71 while i < mlen { if rbuf2[i] != msg[i] { ok = 0; i = mlen } else { i = i + 1 } }
72 matched = ok
73 }
74 let st: *i64 = sys_mmap(16) as *i64
75 sys_wait4(pid, st, 0)
76 sys_close(cfd)
77 ul_w(1, "UDPLOOP-GATE authored=organ bound=1 echo_len=" as *u8); ul_wn(1, n2)
78 ul_w(1, " echo_match=" as *u8); ul_wn(1, matched)
79 if matched == 1 { ul_w(1, " verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
80 ul_w(1, " verdict=RED\n" as *u8); sys_exit(1)
81 return 1
82}