code wiki / _hdl_build / nx_mp_live_gate.nx

nx_mp_live_gate.nx source

↩ module page · 114 lines · 5716 B

1// nx_mp_live_gate.nx -- SOVEREIGN end-to-end LIVE proof of the running multiplayer daemon (no curl, no node): 2// a pure-syscall HTTP client POSTs two players' snapshots to the LIVE nx_mp_serve on 127.0.0.1:7702, then GETs 3// the roster and confirms the response body carries BOTH players' [len][frame] records. Proves the live relay 4// works (shared-mmap rr_post across forked handlers), not just that a page serves. 5// Run AFTER `nx_mp_up`: ./_offc/nx_sov_build_run.elf nx_mp_live_gate 6// license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 9import "nx_gate_emit_lib.nx" 10 11func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 12// connect a fresh TCP socket to 127.0.0.1:port; returns fd or -1 13func conn(port: i64) -> i64 { 14 let addr: *u8 = sys_mmap(16) 15 addr[0]=2 as u8; addr[1]=0 as u8 16 addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8 17 addr[4]=127 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=1 as u8 18 var z: i64=8; while z<16 { addr[z]=0 as u8; z=z+1 } 19 let fd: i64 = sys_socket(2,1,0) 20 if fd<0 { return 0-1 } 21 if nx_connect_bounded(fd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0-1 } 22 return fd 23} 24// POST a `flen`-byte snapshot to /pstate?r=<rm>&p=<pr> 25func post_pstate(port: i64, rm: i64, pr: i64, frame: *u8, flen: i64) -> i64 { 26 let fd: i64 = conn(port) 27 if fd < 0 { return 0-1 } 28 let req: *u8 = sys_mmap(256) 29 var o: i64 = 0 30 let h1: *u8 = "POST /pstate?r=" as *u8; var i: i64=0; while h1[i]!=(0 as u8){req[o]=h1[i];o=o+1;i=i+1} 31 var m: i64=rm; let t: *u8 = sys_mmap(16); var k: i64=0 32 if m==0 {t[0]=48 as u8;k=1} else { while m>0 {t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} } 33 var j: i64=k-1; while j>=0 {req[o]=t[j];o=o+1;j=j-1} 34 let h2: *u8 = "&p=" as *u8; i=0; while h2[i]!=(0 as u8){req[o]=h2[i];o=o+1;i=i+1} 35 m=pr;k=0; if m==0 {t[0]=48 as u8;k=1} else { while m>0 {t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} } 36 j=k-1; while j>=0 {req[o]=t[j];o=o+1;j=j-1} 37 let h3: *u8 = " HTTP/1.0\r\nContent-Length: 11\r\n\r\n" as *u8; i=0; while h3[i]!=(0 as u8){req[o]=h3[i];o=o+1;i=i+1} 38 var b: i64=0; while b<flen {req[o]=frame[b];o=o+1;b=b+1} 39 sys_write(fd, req, o) 40 let rb: *u8 = sys_mmap(256); sys_read(fd, rb, 255) // drain ack 41 sys_close(fd) 42 return 0 43} 44// GET /roster?r=<rm>&p=<self> into out; returns bytes read 45func get_roster(port: i64, rm: i64, self_pr: i64, out: *u8) -> i64 { 46 let fd: i64 = conn(port) 47 if fd < 0 { return 0-1 } 48 let req: *u8 = sys_mmap(256) 49 var o: i64 = 0 50 let h1: *u8 = "GET /roster?r=" as *u8; var i: i64=0; while h1[i]!=(0 as u8){req[o]=h1[i];o=o+1;i=i+1} 51 var m: i64=rm; let t: *u8 = sys_mmap(16); var k: i64=0 52 if m==0 {t[0]=48 as u8;k=1} else { while m>0 {t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} } 53 var j: i64=k-1; while j>=0 {req[o]=t[j];o=o+1;j=j-1} 54 let h2: *u8 = "&p=" as *u8; i=0; while h2[i]!=(0 as u8){req[o]=h2[i];o=o+1;i=i+1} 55 m=self_pr;k=0; if m==0 {t[0]=48 as u8;k=1} else { while m>0 {t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} } 56 j=k-1; while j>=0 {req[o]=t[j];o=o+1;j=j-1} 57 let h3: *u8 = " HTTP/1.0\r\nHost: x\r\n\r\n" as *u8; i=0; while h3[i]!=(0 as u8){req[o]=h3[i];o=o+1;i=i+1} 58 sys_write(fd, req, o) 59 let n: i64 = sys_read(fd, out, 4095) 60 sys_close(fd) 61 return n 62} 63// offset of the body (past "\r\n\r\n") in a response of length n 64func body_off(buf: *u8, n: i64) -> i64 { 65 var i: i64=0 66 while i+3 < n { if buf[i]==(13 as u8){if buf[i+1]==(10 as u8){if buf[i+2]==(13 as u8){if buf[i+3]==(10 as u8){return i+4}}}} i=i+1 } 67 return 0-1 68} 69// count [len][frame] records in a body 70func rec_count(body: *u8, total: i64) -> i64 { 71 var o: i64=0; var c: i64=0; var go: i64=1 72 while go==1 { if o>=total {go=0} else { let fl: i64=body[o] as i64; o=o+1+fl; c=c+1 } } 73 return c 74} 75 76func main() -> i64 { 77 g_puts("nx_mp_live gate (sovereign HTTP client vs the LIVE daemon on :7702, NO curl/node)\n" as *u8) 78 var pass: i64 = 0; var total: i64 = 0 79 let PORT: i64 = 7702 80 let RM: i64 = 99 81 82 // reachability 83 let probe: i64 = conn(PORT) 84 if probe < 0 { g_puts(" FAIL daemon not reachable on :7702 -- run nx_mp_up first\n" as *u8); g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 } 85 sys_close(probe) 86 87 let fa: *u8 = sys_mmap(16); var i: i64=0; while i<11 { fa[i]=(100+i) as u8; i=i+1 } 88 let fb: *u8 = sys_mmap(16); i=0; while i<11 { fb[i]=(40+i) as u8; i=i+1 } 89 post_pstate(PORT, RM, 1, fa, 11) 90 post_pstate(PORT, RM, 2, fb, 11) 91 92 let out: *u8 = sys_mmap(4096) 93 let n: i64 = get_roster(PORT, RM, 9, out) 94 let bo: i64 = body_off(out, n) 95 var r1: i64 = 1 96 var nrec: i64 = 0 97 if bo < 0 { r1 = 0 } else { 98 let body: *u8 = (out + bo) as *u8 99 let blen: i64 = n - bo 100 nrec = rec_count(body, blen) 101 if nrec != 2 { r1 = 0 } 102 g_puts(" [measure] LIVE /roster body = " as *u8); g_pn(blen); g_puts(" bytes, " as *u8); g_pn(nrec); g_puts(" player records\n" as *u8) 103 } 104 pass = pass + g_check("LIVE relay: 2 players POSTed -> roster returns both (shared-mmap across forks)" as *u8, r1); total=total+1 105 106 // isolation: an empty room returns 0 records 107 let n2: i64 = get_roster(PORT, 12345, 9, out) 108 let bo2: i64 = body_off(out, n2) 109 pass = pass + g_check("LIVE room isolation: empty room -> 0 records (neg)" as *u8, (n2 - bo2) == 0); total=total+1 110 111 g_puts("---- mp-live gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 112 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 113 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 114}