code wiki / _hdl_build / nx_mp_daemon_gate.nx

nx_mp_daemon_gate.nx source

↩ module page · 97 lines · 4842 B

1// nx_mp_daemon_gate.nx -- proves the sovereign multiplayer daemon request-handler (nx_mp_daemon) over a relay. 2// NO sockets, NO js, NO curl: crafts real HTTP request bytes and drives mpd_pstate / mpd_roster directly. 3// 1) routing: /pstate->1, /roster->2, a file path->0 ; query ints parsed 4// 2) POST /pstate puts the body snapshot into the room (two players) 5// 3) GET /roster returns an HTTP response whose body = the OTHER players' [len][frame] records (byte-exact) 6// 4) room isolation (neg): /roster for a different room returns an empty body 7// Built nx_cc_sovereign -> nxasm_x86 (no gcc, no .sh). license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_gate_emit_lib.nx" 10import "nx_mp_daemon.nx" // brings nx_mp_relay + nx_room_relay transitively 11 12func mk_post(req: *u8, rm: i64, pr: i64, frame: *u8, fl: i64) -> i64 { 13 var o: i64 = mpd_wstr(req, 0, "POST /pstate?r=" as *u8) 14 o = mpd_wn(req, o, rm) 15 o = mpd_wstr(req, o, "&p=" as *u8) 16 o = mpd_wn(req, o, pr) 17 o = mpd_wstr(req, o, " HTTP/1.1\r\nContent-Length: " as *u8) 18 o = mpd_wn(req, o, fl) 19 o = mpd_wstr(req, o, "\r\n\r\n" as *u8) 20 var k: i64 = 0 21 while k < fl { req[o + k] = frame[k]; k = k + 1 } 22 return o + fl 23} 24func rec_eq(body: *u8, o: i64, expect: *u8, n: i64) -> i64 { 25 if (body[o] as i64) != n { return 0 } 26 var k: i64 = 0 27 while k < n { if body[o + 1 + k] != expect[k] { return 0 } k = k + 1 } 28 return 1 29} 30 31func main() -> i64 { 32 g_puts("nx_mp_daemon gate (sovereign /pstate + /roster handler, NO sockets/js/curl)\n" as *u8) 33 var pass: i64 = 0; var total: i64 = 0 34 35 let N: i64 = 8 36 let SB: i64 = 64 37 let st: *i64 = sys_mmap((2 + 5*N) * 8) as *i64 38 let arena: *u8 = sys_mmap(N * SB) 39 rr_init(st, N, SB) 40 let path: *u8 = sys_mmap(1024) 41 let out: *u8 = sys_mmap(8192) 42 let req: *u8 = sys_mmap(8192) 43 let RM: i64 = 32368 44 let NOW: i64 = 1000 45 46 // 1) routing + query int parse 47 var r1: i64 = 1 48 mpd_path("POST /pstate?r=32368&p=100 HTTP/1.1\r\n\r\n" as *u8, 40, path) 49 if mpd_route(path) != 1 { r1 = 0 } 50 if mpd_qint(path, "r=" as *u8) != 32368 { r1 = 0 } 51 if mpd_qint(path, "p=" as *u8) != 100 { r1 = 0 } 52 mpd_path("GET /roster?r=5&p=9 HTTP/1.1\r\n\r\n" as *u8, 33, path) 53 if mpd_route(path) != 2 { r1 = 0 } 54 mpd_path("GET /pets3d.wasm HTTP/1.1\r\n\r\n" as *u8, 29, path) 55 if mpd_route(path) != 0 { r1 = 0 } 56 pass = pass + g_check("routing + query-int parse" as *u8, r1); total=total+1 57 58 // 2) POST /pstate for two players 59 let fa: *u8 = sys_mmap(64); var i: i64=0; while i<11 { fa[i]=(100+i) as u8; i=i+1 } 60 let fb: *u8 = sys_mmap(64); i=0; while i<11 { fb[i]=(40+i) as u8; i=i+1 } 61 let na: i64 = mk_post(req, RM, 100, fa, 11) 62 mpd_path(req, na, path); mpd_pstate(req, na, path, st, arena, SB, NOW, out) 63 let nb: i64 = mk_post(req, RM, 101, fb, 11) 64 mpd_path(req, nb, path); mpd_pstate(req, nb, path, st, arena, SB, NOW, out) 65 var r2: i64 = 1 66 if rr_live(st, RM, 100, NOW, 8000) < 0 { r2 = 0 } 67 if rr_live(st, RM, 101, NOW, 8000) < 0 { r2 = 0 } 68 pass = pass + g_check("POST /pstate stored both players in the room" as *u8, r2); total=total+1 69 70 // 3) GET /roster -> HTTP response whose body = the other players' records 71 var go: i64 = mpd_wstr(req, 0, "GET /roster?r=" as *u8) 72 go = mpd_wn(req, go, RM); go = mpd_wstr(req, go, "&p=999 HTTP/1.1\r\n\r\n" as *u8) 73 mpd_path(req, go, path) 74 let rlen: i64 = mpd_roster(path, st, arena, SB, NOW, 8000, out) 75 let bo: i64 = mpd_body_off(out, rlen) // skip the HTTP header 76 var r3: i64 = 1 77 if bo < 0 { r3 = 0 } else { 78 let body: *u8 = (out + bo) as *u8 79 let blen: i64 = rlen - bo 80 if mp_roster_count(body, blen) != 2 { r3 = 0 } 81 if rec_eq(body, 0, fa, 11) != 1 { r3 = 0 } 82 if rec_eq(body, 1 + 11, fb, 11) != 1 { r3 = 0 } 83 g_puts(" [measure] /roster response = " as *u8); g_pn(rlen); g_puts(" bytes (header + " as *u8); g_pn(blen); g_puts("-byte body, 2 records)\n" as *u8) 84 } 85 pass = pass + g_check("GET /roster body = other players' [len][frame] records, byte-exact" as *u8, r3); total=total+1 86 87 // 4) room isolation (neg): /roster for a different room -> empty body 88 var gx: i64 = mpd_wstr(req, 0, "GET /roster?r=11111&p=1 HTTP/1.1\r\n\r\n" as *u8) 89 mpd_path(req, gx, path) 90 let rl2: i64 = mpd_roster(path, st, arena, SB, NOW, 8000, out) 91 let bo2: i64 = mpd_body_off(out, rl2) 92 pass = pass + g_check("room isolation: empty roster body for another room (neg)" as *u8, (rl2 - bo2) == 0); total=total+1 93 94 g_puts("---- mp-daemon gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 95 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 96 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 97}