code wiki / _hdl_build / nx_synth_serve_gate.nx

nx_synth_serve_gate.nx source

↩ module page · 105 lines · 7532 B

1// nx_synth_serve_gate.nx -- prove the Synth Studio is LIVE over real loopback HTTP: forks the server, then acts 2// as the browser. T1 GET /synth -> the studio page · T2 GET /synth/api/move?id=1 -> a real APNG · T3 POST 3// /synth/api/text2motion "say hello with a wave" -> a real APNG (neural chain runs in the request) · T4 POST 4// /synth/api/variant?sp=1&tv=1 -> a real PNG · T5 GET /synth/health -> ok. All served by sv_serve_conn. 5// license_tier: ORIGINAL expect_exit: 0 6import "nx_synth_serve.nx" 7import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 8import "nx_syscalls.nx" 9 10func g(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func glen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 12func gcat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){d[o+i]=s[i]; i=i+1} return o+i } 13func gcatb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n {d[o+i]=s[i]; i=i+1} return o+n } 14func gitoa(d: *u8, o: 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 q: i64=k-1; while q>=0{d[o]=t[q];o=o+1;q=q-1} return o } 15func gfind(buf: *u8, n: i64, needle: *u8) -> i64 { 16 let nl: i64 = glen(needle); if nl==0 {return 0} 17 var i: i64=0 18 while i+nl<=n { var j: i64=0; var ok: i64=1; while j<nl { if (buf[i+j]&0xff)!=(needle[j]&0xff){ok=0;j=nl} else {j=j+1} } if ok==1{return i} i=i+1 } 19 return 0-1 20} 21// PNG signature 137 80 78 71 appears in the BODY (after the header) 22func gpng(buf: *u8, n: i64) -> i64 { 23 var i: i64=0 24 while i+4<=n { if (buf[i]&0xff)==137 { if (buf[i+1]&0xff)==80 { if (buf[i+2]&0xff)==78 { if (buf[i+3]&0xff)==71 { return i } } } } i=i+1 } 25 return 0-1 26} 27func glisten(port: i64) -> i64 { 28 let lfd: i64 = sys_socket(2,1,0); if lfd<0 {return 0-1} 29 let optv: *u8 = sys_mmap(4); optv[0]=1 as u8; sys_setsockopt(lfd,1,2,optv,4) 30 let addr: *u8 = sys_mmap(16) 31 addr[0]=2 as u8; addr[1]=0 as u8; addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8 32 addr[4]=127 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=1 as u8 33 var zi: i64=8; while zi<16 {addr[zi]=0 as u8; zi=zi+1} 34 if sys_bind(lfd, addr, 16) < 0 { return 0-1 } 35 if sys_listen(lfd, 16) < 0 { return 0-1 } 36 return lfd 37} 38func gconnect(port: i64) -> i64 { 39 let fd: i64 = sys_socket(2,1,0); if fd<0 {return 0-1} 40 sys_set_socket_timeout(fd, 120) 41 let a: *u8 = sys_mmap(16) 42 a[0]=2 as u8; a[1]=0 as u8; a[2]=((port>>8)&0xff) as u8; a[3]=(port&0xff) as u8 43 a[4]=127 as u8; a[5]=0 as u8; a[6]=0 as u8; a[7]=1 as u8 44 var zi: i64=8; while zi<16 {a[zi]=0 as u8; zi=zi+1} 45 if nx_connect_bounded(fd, a, 16, NX_CONN_DEFAULT_MS) != 0 { sys_close(fd); return 0-1 } 46 return fd 47} 48func gread(fd: i64, resp: *u8, cap: i64) -> i64 { var rn: i64=0; var go: i64=1; while go==1 { let r: i64=sys_read(fd,(resp as i64+rn) as *u8,cap-rn); if r<=0 {go=0} else {rn=rn+r; if rn>=cap {go=0}} } return rn } 49func greq_get(port: i64, path: *u8, resp: *u8, cap: i64) -> i64 { 50 let fd: i64 = gconnect(port); if fd<0 { return 0-1 } 51 let rq: *u8 = sys_mmap(2048); var o: i64 = gcat(rq, 0, "GET " as *u8); o = gcat(rq, o, path); o = gcat(rq, o, " HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n" as *u8) 52 sys_write(fd, rq, o); let rn: i64 = gread(fd, resp, cap); sys_close(fd); return rn 53} 54func greq_post(port: i64, path: *u8, body: *u8, resp: *u8, cap: i64) -> i64 { 55 let fd: i64 = gconnect(port); if fd<0 { return 0-1 } 56 let bl: i64 = glen(body) 57 let rq: *u8 = sys_mmap(2048); var o: i64 = gcat(rq, 0, "POST " as *u8); o = gcat(rq, o, path) 58 o = gcat(rq, o, " HTTP/1.1\r\nHost: x\r\nConnection: close\r\nContent-Length: " as *u8); o = gitoa(rq, o, bl); o = gcat(rq, o, "\r\n\r\n" as *u8); o = gcatb(rq, o, body, bl) 59 sys_write(fd, rq, o); let rn: i64 = gread(fd, resp, cap); sys_close(fd); return rn 60} 61 62func main() -> i64 { 63 g("=== nx_synth_serve_gate -- the Synth Studio LIVE over loopback ===\n" as *u8) 64 let PORT: i64 = 39351 65 let lfd: i64 = glisten(PORT); if lfd<0 { g("GATE FAIL: listen\n" as *u8); sys_exit(1); return 1 } 66 let pid: i64 = sys_fork() 67 if pid == 0 { 68 var i: i64 = 0 69 while i < 8 { let c: i64 = sys_accept(lfd); if c>=0 { sv_serve_conn(c); sys_close(c) } i=i+1 } 70 sys_exit(0) 71 } 72 sys_close(lfd) 73 let resp: *u8 = sys_mmap(12 * 1024 * 1024) 74 var fails: i64 = 0 75 76 let n1: i64 = greq_get(PORT, "/synth" as *u8, resp, 12*1024*1024) 77 if gfind(resp, n1, "200 OK" as *u8) >= 0 { if gfind(resp, n1, "Synth Studio" as *u8) >= 0 { g("T1 PASS GET /synth -> studio page\n" as *u8) } else { fails=fails+1; g("T1 FAIL no studio marker\n" as *u8) } } else { fails=fails+1; g("T1 FAIL not 200\n" as *u8) } 78 79 let n2: i64 = greq_get(PORT, "/synth/api/move?id=1" as *u8, resp, 12*1024*1024) 80 if gfind(resp, n2, "200 OK" as *u8) >= 0 { if gpng(resp, n2) >= 0 { g("T2 PASS /api/move?id=1 -> APNG (" as *u8); let nb: *u8=sys_mmap(16); let k: i64=gitoa(nb,0,n2); sys_write(1,nb,k); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T2 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T2 FAIL not 200\n" as *u8) } 81 82 let n3: i64 = greq_post(PORT, "/synth/api/text2motion" as *u8, "say hello with a wave" as *u8, resp, 12*1024*1024) 83 if gfind(resp, n3, "200 OK" as *u8) >= 0 { if gpng(resp, n3) >= 0 { g("T3 PASS POST /api/text2motion 'say hello with a wave' -> neural motion APNG (" as *u8); let nb2: *u8=sys_mmap(16); let k2: i64=gitoa(nb2,0,n3); sys_write(1,nb2,k2); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T3 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T3 FAIL not 200\n" as *u8) } 84 85 let n4: i64 = greq_post(PORT, "/synth/api/variant?sp=1&hv=0&ev=1&tv=1&build=110" as *u8, "" as *u8, resp, 12*1024*1024) 86 if gfind(resp, n4, "200 OK" as *u8) >= 0 { if gpng(resp, n4) >= 0 { g("T4 PASS POST /api/variant (wolf+tail) -> PNG (" as *u8); let nb3: *u8=sys_mmap(16); let k3: i64=gitoa(nb3,0,n4); sys_write(1,nb3,k3); g(" bytes)\n" as *u8) } else { fails=fails+1; g("T4 FAIL no PNG body\n" as *u8) } } else { fails=fails+1; g("T4 FAIL not 200\n" as *u8) } 87 88 let n5: i64 = greq_get(PORT, "/synth/health" as *u8, resp, 12*1024*1024) 89 if gfind(resp, n5, "\"ok\":1" as *u8) >= 0 { g("T5 PASS /synth/health ok\n" as *u8) } else { fails=fails+1; g("T5 FAIL health\n" as *u8) } 90 91 let n6: i64 = greq_get(PORT, "/synth/api/coach?err=0" as *u8, resp, 12*1024*1024) 92 if gfind(resp, n6, "\"form\":1000" as *u8) >= 0 { g("T6 PASS /api/coach?err=0 -> perfect form 1000/1000\n" as *u8) } else { fails=fails+1; g("T6 FAIL clean form not 1000\n" as *u8) } 93 94 let n7: i64 = greq_get(PORT, "/synth/api/coach?err=65" as *u8, resp, 12*1024*1024) 95 if gfind(resp, n7, "wrist" as *u8) >= 0 { g("T7 PASS /api/coach?err=65 -> coach flags the wrist (form scored down)\n" as *u8) } else { fails=fails+1; g("T7 FAIL coach did not flag wrist\n" as *u8) } 96 97 // let the server loop finish + reap 98 greq_get(PORT, "/synth/health" as *u8, resp, 4096) 99 let stx: *i64 = sys_mmap(16) as *i64 100 sys_wait4(pid, stx, 0) 101 102 if fails == 0 { g("SYNTH-STUDIO-GATE 7/7 GREEN -- studio page + text2motion + move + variant + COACH (form score + names the off-joint) all LIVE over HTTP\n" as *u8); sys_exit(0); return 0 } 103 g("SYNTH-STUDIO-GATE RED fails=" as *u8); let fb: *u8=sys_mmap(16); let kk: i64=gitoa(fb,0,fails); sys_write(1,fb,kk); g("\n" as *u8) 104 sys_exit(1); return 1 105}