nx_browser_image_demo_test.nx source
↩ module page · 117 lines · 4707 B
1// nx_browser_image_demo_test.nx -- THE end-to-end image milestone.
2//
3// The Nishi browser fetches a REAL public JPEG over the live network
4// using its own bits-up stack -- DNS resolver, BSD sockets, HTTP/1.1
5// request builder, response parser -- then decodes the JPEG bits-up
6// (baseline Huffman + IDCT + level shift) and paints it as ASCII art
7// in the terminal. No libc, no libjpeg, no curl, no Chrome. Every
8// byte between the socket and the pixel is NishiLang.
9//
10// Target: http://httpbin.org/image/jpeg -- a 35 KB SOF0 (baseline)
11// JPEG, the format our decoder handles. Fetched over plain HTTP so
12// this milestone isolates the image pipeline; arbitrary-host HTTPS
13// handshake interop is its own hardening track (see task: TLS
14// RECV_SH_FAIL). Sovereign TLS 1.3 already fetches example.com.
15//
16// PASS = HTTP 200 + JPEG decode OK + ASCII raster emitted. The art
17// is written to stdout so the result is visible, not just asserted.
18//
19// expect_exit: 0
20// license_tier: ORIGINAL
21
22import "nx_syscalls.nx"
23import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
24import "nx_dns_resolve_a_record.nx"
25import "nx_https_url_connect.nx"
26import "nx_http_client.nx"
27import "nx_http_response_parse.nx"
28import "nx_jpeg_ascii.nx"
29
30func dump_dec(label0: i64, label1: i64, v: i64) -> i64 {
31 let lab: *u8 = sys_mmap(8)
32 lab[0] = label0 as u8; lab[1] = label1 as u8; lab[2] = 0x3D
33 sys_write(2, lab, 3)
34 var av: i64 = v
35 if av < 0 { let neg: *u8 = sys_mmap(8); neg[0]=0x2D; sys_write(2, neg, 1); av = 0 - av }
36 if av == 0 { let z: *u8 = sys_mmap(8); z[0]=0x30; sys_write(2, z, 1) }
37 else {
38 let dbuf: *u8 = sys_mmap(16)
39 var pos: i64 = 0
40 var x: i64 = av
41 while x > 0 { dbuf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 }
42 let out: *u8 = sys_mmap(16)
43 var oi: i64 = 0
44 while oi < pos { out[oi] = dbuf[pos - 1 - oi]; oi = oi + 1 }
45 sys_write(2, out, pos)
46 }
47 let nl: *u8 = sys_mmap(8); nl[0]=0x0A; sys_write(2, nl, 1)
48 return 0
49}
50
51func main() -> i64 {
52 let host: *u8 = "httpbin.org\x00"
53 let host_len: i64 = 11
54 let path: *u8 = "/image/jpeg\x00"
55 let path_len: i64 = 11
56
57 // ---- DNS resolve ----
58 let dns: *DnsResolveResult = nx_dns_resolve_default(host, host_len, 1779284141)
59 if dns.verdict != NX_DNS_R_OK { dump_dec(0x44, 0x4E, dns.verdict); return 30 } // DN=
60 if dns.ipv4_packed == 0 { return 31 }
61
62 // ---- TCP connect on port 80 ----
63 let fd: i64 = sys_socket(NX_HTTPS_AF_INET, NX_HTTPS_SOCK_STREAM, 0)
64 if fd < 0 { return 32 }
65 let sa: *u8 = sys_mmap(16)
66 nx_https_build_sockaddr(sa, dns.ipv4_packed, 80)
67 if nx_connect_bounded(fd, sa, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 33 }
68
69 // ---- Send HTTP/1.1 GET ----
70 let req: *u8 = sys_mmap(256)
71 let req_len: i64 = nx_http_client_build_request(path, path_len, host, host_len, req)
72 if sys_write(fd, req, req_len) < 0 { sys_close(fd); return 34 }
73
74 // ---- Receive the full response (Connection: close -> read to EOF) ----
75 let cap: i64 = 262144
76 let buf: *u8 = sys_mmap(cap)
77 var total: i64 = 0
78 var budget: i64 = 100000 // bounded loop (KNOWN_LESSONS ยง12)
79 var reading: i64 = 1
80 while reading == 1 {
81 if total >= cap { reading = 0 }
82 if budget <= 0 { reading = 0 }
83 if reading == 1 {
84 let got: i64 = sys_read(fd, buf + total, cap - total)
85 if got <= 0 { reading = 0 }
86 if got > 0 { total = total + got }
87 budget = budget - 1
88 }
89 }
90 sys_close(fd)
91 dump_dec(0x47, 0x43, total) // GC= total bytes received
92 if total < 4 { return 35 }
93
94 // ---- Parse HTTP response; locate the JPEG body ----
95 let resp: *i64 = sys_mmap(128) as *i64
96 let pv: i64 = nx_http_response_parse(buf, total, resp)
97 dump_dec(0x50, 0x56, pv) // PV=
98 if pv != 0 { return 50 }
99 let status: i64 = resp[1]
100 dump_dec(0x53, 0x54, status) // ST=
101 if status != 200 { return 51 }
102 let body_off: i64 = resp[6]
103 let jpeg_len: i64 = total - body_off
104 dump_dec(0x42, 0x4F, body_off) // BO=
105 dump_dec(0x4A, 0x4C, jpeg_len) // JL=
106 if jpeg_len < 4 { return 52 }
107
108 // ---- Bits-up JPEG decode + ASCII raster to stdout ----
109 let banner: *u8 = "\n--- httpbin.org/image/jpeg : fetched + decoded + rendered bits-up by NishiLang ---\n\x00"
110 sys_write(1, banner, 84)
111
112 let rrc: i64 = nx_jpeg_render_ascii_fit(buf + body_off, jpeg_len, 72)
113 dump_dec(0x52, 0x52, rrc) // RR=
114 if rrc != NX_JPEG_ASCII_OK { return 60 + rrc }
115
116 return 0
117}