nx_page_get_test.nx source
↩ module page · 174 lines · 5417 B
1// nx_browser_loopback_test.nx -- fork-loopback fetch + render.
2//
3// Server: accepts ONE TCP connection on a high port, sends a canned
4// HTTP/1.1 response with a small HTML body, then exits.
5// Client: connects, reads the full response, parses it, renders to
6// plain text, writes to stdout.
7//
8// This proves the sovereign browser substrate composes over a real
9// kernel-mediated TCP socket -- only the TLS layer is omitted (the
10// already-passing nx_https_loopback_test proves that layer in
11// isolation). CAPABILITY_COMPLETENESS PARTIAL: combining
12// loopback + TLS into one binary is queued behind X.509 chain
13// validation arc.
14//
15// expect_exit: 0
16// license_tier: ORIGINAL
17
18import "nx_syscalls.nx"
19import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
20import "nx_http_response_parse.nx"
21import "nx_html_to_text.nx"
22
23const BLP_PORT: i64 = 17890
24
25// ===== LEAF: address + I/O =======================================
26
27func blp_addr(out: *u8, port: i64) -> i64 {
28 out[0] = 2; out[1] = 0
29 out[2] = (port >> 8) & 0xff
30 out[3] = port & 0xff
31 out[4] = 127; out[5] = 0; out[6] = 0; out[7] = 1
32 var i: i64 = 8
33 while i < 16 { out[i] = 0; i = i + 1 }
34 return 16
35}
36
37func blp_recv_all(fd: i64, buf: *u8, cap: i64) -> i64 {
38 var got: i64 = 0
39 while got < cap {
40 let r: i64 = sys_read(fd, buf + got, cap - got)
41 if r <= 0 { return got }
42 got = got + r
43 }
44 return got
45}
46
47// ===== Canned response builder ===================================
48
49func blp_write(out: *u8, off: i64, s: *u8, n: i64) -> i64 {
50 var i: i64 = 0
51 while i < n { out[off + i] = s[i]; i = i + 1 }
52 return off + n
53}
54
55func blp_status(out: *u8) -> i64 {
56 let l: *u8 = sys_mmap(32)
57 l[0]=0x48; l[1]=0x54; l[2]=0x54; l[3]=0x50
58 l[4]=0x2f; l[5]=0x31; l[6]=0x2e; l[7]=0x31
59 l[8]=0x20; l[9]=0x32; l[10]=0x30; l[11]=0x30
60 l[12]=0x20; l[13]=0x4f; l[14]=0x4b
61 l[15]=0x0d; l[16]=0x0a
62 return blp_write(out, 0, l, 17)
63}
64
65func blp_ct(out: *u8, off: i64) -> i64 {
66 let l: *u8 = sys_mmap(32)
67 l[0]=0x43; l[1]=0x6f; l[2]=0x6e; l[3]=0x74
68 l[4]=0x65; l[5]=0x6e; l[6]=0x74; l[7]=0x2d
69 l[8]=0x54; l[9]=0x79; l[10]=0x70; l[11]=0x65
70 l[12]=0x3a; l[13]=0x20
71 l[14]=0x74; l[15]=0x65; l[16]=0x78; l[17]=0x74
72 l[18]=0x2f; l[19]=0x68; l[20]=0x74; l[21]=0x6d; l[22]=0x6c
73 l[23]=0x0d; l[24]=0x0a
74 return blp_write(out, off, l, 25)
75}
76
77func blp_cl(out: *u8, off: i64) -> i64 {
78 // "Content-Length: 20\r\n\r\n" body = 20 bytes
79 let l: *u8 = sys_mmap(32)
80 l[0]=0x43; l[1]=0x6f; l[2]=0x6e; l[3]=0x74
81 l[4]=0x65; l[5]=0x6e; l[6]=0x74; l[7]=0x2d
82 l[8]=0x4c; l[9]=0x65; l[10]=0x6e; l[11]=0x67
83 l[12]=0x74; l[13]=0x68; l[14]=0x3a; l[15]=0x20
84 l[16]=0x32; l[17]=0x30
85 l[18]=0x0d; l[19]=0x0a
86 l[20]=0x0d; l[21]=0x0a
87 return blp_write(out, off, l, 22)
88}
89
90func blp_body(out: *u8, off: i64) -> i64 {
91 // "<p>hello world</p>X1" (20 bytes total exactly)
92 let b: *u8 = sys_mmap(32)
93 b[0]=0x3c; b[1]=0x70; b[2]=0x3e
94 b[3]=0x68; b[4]=0x65; b[5]=0x6c; b[6]=0x6c; b[7]=0x6f
95 b[8]=0x20
96 b[9]=0x77; b[10]=0x6f; b[11]=0x72; b[12]=0x6c; b[13]=0x64
97 b[14]=0x3c; b[15]=0x2f; b[16]=0x70; b[17]=0x3e
98 b[18]=0x58; b[19]=0x31
99 return blp_write(out, off, b, 20)
100}
101
102func blp_build(out: *u8) -> i64 {
103 var p: i64 = 0
104 p = blp_status(out)
105 p = blp_ct(out, p)
106 p = blp_cl(out, p)
107 p = blp_body(out, p)
108 return p
109}
110
111// ===== Render helper =============================================
112
113func blp_render(buf: *u8, n: i64, out: *u8, cap: i64) -> i64 {
114 let r: *i64 = nx_http_resp_alloc()
115 let v: i64 = nx_http_response_parse(buf, n, r)
116 if v != NX_HTTP_RESP_OK { return 0 - 200 - v }
117 if r[1] != 200 { return 0 - 300 - r[1] }
118 if r[7] <= 0 { return 0 - 400 - r[7] }
119 if r[6] < 0 { return 0 - 500 - r[6] }
120 return nx_html_to_text(buf + r[6], r[7], out, cap)
121}
122
123// ===== Endpoint runners ==========================================
124
125func blp_run_server(cfd: i64) -> i64 {
126 let buf: *u8 = sys_mmap(256)
127 let n: i64 = blp_build(buf)
128 sys_write(cfd, buf, n)
129 sys_close(cfd)
130 return 0
131}
132
133func blp_run_client(cfd: i64) -> i64 {
134 let buf: *u8 = sys_mmap(4096)
135 let n: i64 = blp_recv_all(cfd, buf, 4096)
136 if n <= 0 { return 10 }
137 if n > 250 { return 11 }
138 let rendered: *u8 = sys_mmap(512)
139 let m: i64 = blp_render(buf, n, rendered, 512)
140 if m < 0 { return 0 - m }
141 if m == 0 { return 99 }
142 sys_write(1, rendered, m)
143 if m != 14 { return 100 + m }
144 return 0
145}
146
147func main() -> i64 {
148 let addr: *u8 = sys_mmap(16)
149 blp_addr(addr, BLP_PORT)
150 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
151 if lfd < 0 { return 1 }
152 if sys_bind(lfd, addr, 16) < 0 { return 2 }
153 if sys_listen(lfd, 4) < 0 { return 3 }
154
155 let pid: i64 = sys_fork()
156 if pid < 0 { return 4 }
157 if pid == 0 {
158 var spin: i64 = 0
159 while spin < 200000 { spin = spin + 1 }
160 let ccfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
161 if ccfd < 0 { return 5 }
162 if nx_connect_bounded(ccfd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { return 6 }
163 return blp_run_client(ccfd)
164 }
165
166 let scfd: i64 = sys_accept(lfd)
167 if scfd < 0 { return 7 }
168 let sr: i64 = blp_run_server(scfd)
169 if sr != 0 { return sr }
170
171 let status: *i64 = sys_mmap(8) as *i64
172 sys_wait4(pid, status, 0)
173 return wait_exit_code(*status)
174}