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}