code wiki / (root) / nx_browser_image_demo_test.nx

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}