code wiki / _hdl_build / nx_meet_serve_gate.nx
nx_meet_serve_gate.nx source
↩ module page · 118 lines · 6738 B
1// nx_meet_serve_gate.nx -- liar-kill gate for the P2-LIVE socket route. Binds a port, forks a child running the
2// REAL daemon path (meet_serve_one -> accept -> meet_http_handle), and drives it as a sovereign loopback HTTP
3// CLIENT. Asserts over a real socket: a clean apply POST -> 200 + "passed our checks" (SCREENED), a honeypot POST
4// -> 200 + "under review" (FLAGGED), a GET -> 405. Distinguishing teeth: screened != flagged response. expect_exit: 0
5import "nx_syscalls.nx"
6import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
7import "nx_meet_lib.nx"
8import "nx_meet_serve_lib.nx"
9import "nx_gate_verdict.nx"
10
11func sg_find(buf: *u8, n: i64, needle: *u8) -> i64 {
12 var nl: i64 = 0; while needle[nl] != (0 as u8) { nl = nl + 1 }
13 if nl == 0 { return 0 - 1 }
14 var i: i64 = 0
15 while i + nl <= n { var j: i64=0; var ok: i64=1; while j<nl { if buf[i+j]!=needle[j]{ok=0;j=nl} else {j=j+1} } if ok==1 {return i} i=i+1 }
16 return 0 - 1
17}
18func sg_has(buf: *u8, n: i64, needle: *u8) -> i64 { if sg_find(buf, n, needle) >= 0 { return 1 } return 0 }
19func sg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i];o=o+1;i=i+1} return o }
20func sg_itoa(dst: *u8, off: i64, v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var o: i64=off; var q: i64=k-1; while q>=0{dst[o]=t[q];o=o+1;q=q-1} return o }
21func sg_nap(ms: i64) -> i64 { let ts: *i64 = sys_mmap(16) as *i64; ts[0]=0; ts[1]=ms*1000000; __syscall(35, ts as i64, 0, 0, 0, 0, 0); return 0 }
22
23func build_post(path: *u8, body: *u8, out: *u8) -> i64 {
24 var bl: i64 = 0; while body[bl] != (0 as u8) { bl = bl + 1 }
25 var o: i64 = 0
26 o = sg_cat(out, o, "POST " as *u8); o = sg_cat(out, o, path)
27 o = sg_cat(out, o, " HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: " as *u8)
28 o = sg_itoa(out, o, bl)
29 o = sg_cat(out, o, "\r\nConnection: close\r\n\r\n" as *u8)
30 o = sg_cat(out, o, body)
31 return o
32}
33// connect 127.0.0.1:port (retry until bound), send raw, read response. returns bytes read or -1.
34func cg_send(port: i64, raw: *u8, rawlen: i64, resp: *u8, cap: i64) -> i64 {
35 var tries: i64 = 0
36 while tries < 120 {
37 let fd: i64 = sys_socket(2, 1, 0)
38 if fd >= 0 {
39 let tv: *u8 = sys_mmap(16); tv[0]=3 as u8; var tz: i64=1; while tz<16 { tv[tz]=0 as u8; tz=tz+1 }
40 sys_setsockopt(fd, 1, 20, tv, 16)
41 let addr: *u8 = sys_mmap(16)
42 addr[0]=2 as u8; addr[1]=0 as u8; addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8
43 addr[4]=127 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=1 as u8
44 var z: i64=8; while z<16 { addr[z]=0 as u8; z=z+1 }
45 if nx_connect_bounded(fd, addr, 16, NX_CONN_DEFAULT_MS) == 0 {
46 sys_write(fd, raw, rawlen)
47 let n: i64 = sys_read(fd, resp, cap)
48 sys_close(fd)
49 return n
50 }
51 sys_close(fd)
52 }
53 sg_nap(15)
54 tries = tries + 1
55 }
56 return 0 - 1
57}
58
59func main() -> i64 {
60 mputs("=== nx_meet_serve_gate: live socket route over loopback (real HTTP POST -> handler -> response) ===\n" as *u8)
61 let port: i64 = 18099
62
63 // bind+listen in the PARENT, then fork the server child (inherits the listening socket)
64 let addr: *u8 = sys_mmap(16)
65 addr[0]=2 as u8; addr[1]=0 as u8; addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8
66 var zi: i64=4; while zi<16 { addr[zi]=0 as u8; zi=zi+1 }
67 let lfd: i64 = sys_socket(2, 1, 0)
68 let optv: *u8 = sys_mmap(4); optv[0]=1 as u8
69 sys_setsockopt(lfd, 1, 2, optv, 4)
70 if sys_bind(lfd, addr, 16) < 0 { mputs("BIND-FAIL\n" as *u8); sys_exit(1); return 1 }
71 if sys_listen(lfd, 16) < 0 { mputs("LISTEN-FAIL\n" as *u8); sys_exit(1); return 1 }
72
73 let pid: i64 = sys_fork()
74 if pid == 0 {
75 meet_serve_one(lfd, 1)
76 meet_serve_one(lfd, 2)
77 meet_serve_one(lfd, 3)
78 sys_close(lfd); sys_exit(0)
79 }
80 sys_close(lfd)
81
82 let raw: *u8 = sys_mmap(4096)
83 let resp: *u8 = sys_mmap(131072)
84 var pass: i64 = 0; var fail: i64 = 0
85
86 // 1) clean apply
87 var rl: i64 = build_post("/apply" as *u8, "name=Jane+Doe&email=jane%40example.com&resume=Built+12000+jane%40example.com+github&website=" as *u8, raw)
88 let n1: i64 = cg_send(port, raw, rl, resp, 131072)
89 if sg_has(resp, n1, "200 OK" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-no-200\n" as *u8) }
90 if sg_has(resp, n1, "passed our checks" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-not-screened\n" as *u8) }
91 if sg_has(resp, n1, "under review" as *u8) == 0 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL clean-shows-review\n" as *u8) }
92
93 // 2) honeypot bot -> flagged
94 rl = build_post("/apply" as *u8, "name=Bot&email=b%40x.com&resume=Built+12000+github&website=spam" as *u8, raw)
95 let n2: i64 = cg_send(port, raw, rl, resp, 131072)
96 if sg_has(resp, n2, "under review" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL bot-not-flagged\n" as *u8) }
97 if sg_has(resp, n2, "passed our checks" as *u8) == 0 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL bot-shows-screened\n" as *u8) }
98
99 // 3) GET -> 405
100 rl = sg_cat(raw, 0, "GET /apply HTTP/1.0\r\nConnection: close\r\n\r\n" as *u8)
101 let n3: i64 = cg_send(port, raw, rl, resp, 131072)
102 if sg_has(resp, n3, "405" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; mputs(" FAIL get-no-405\n" as *u8) }
103
104 __syscall(129, pid, 9, 0, 0, 0, 0) // rv64 kill=129; raw x86 62 is an RV64 KEY translated to lseek(8) -- the kill never happened (debt idx 2277)
105 let st: *i64 = sys_mmap(8) as *i64; var rr: i64 = 0; while rr < 20 { sys_wait4(0 - 1, st, 1); rr = rr + 1 }
106
107 mputs(" port=" as *u8); mnum(port); mputs(" bytes: clean=" as *u8); mnum(n1); mputs(" bot=" as *u8); mnum(n2); mputs(" get=" as *u8); mnum(n3); mputs("\n" as *u8)
108 mputs("MEET-SERVE-GATE pass=" as *u8); mnum(pass); mputs(" fail=" as *u8); mnum(fail)
109 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
110 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
111 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
112 let ctr__dry: *i64 = gv_ctr()
113 ctr__dry[0] = pass
114 ctr__dry[1] = pass + fail
115 let rc__dry: i64 = gv_verdict("MEET-SERVE-GATE" as *u8, ctr__dry, "live socket route: real HTTP POST over loopback -> screen -> respond; screened != flagged)" as *u8)
116 sys_exit(rc__dry)
117 return rc__dry
118}