code wiki / _hdl_build / nx_host_router.nx

nx_host_router.nx source

↩ module page · 764 lines · 40120 B

1// nx_host_router.nx -- S-class sovereign multi-site host router (pure Nishi, no TLS, no crypto). 2// Config-driven vhost table + PER-REQUEST file serving = HOT CONTENT LOADING: push a file, it is 3// live on the next request, NO recompile. Path-traversal-safe. This is L5 (content) of the sovereign 4// hosting design (knowledge/research/2026-06-05-sovereign-web-hosting.md). Composed into the TLS 5// daemon, which supplies L3/L4. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7const HR_MAGIC_1024: i64 = 1024 8const HR_MAGIC_4096: i64 = 4096 9const HR_MAGIC_5120: i64 = 5120 10const HR_MAGIC_2048: i64 = 2048 11const HR_MAGIC_4095: i64 = 4095 12 13func hr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 14 15func hr_copy(dst: *u8, src: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { dst[i] = src[i]; i = i + 1 } return n } 16 17func hr_eq(a: *u8, b: *u8, n: i64) -> i64 { 18 var i: i64 = 0 19 while i < n { if a[i] != b[i] { return 0 } i = i + 1 } 20 return 1 21} 22 23func hr_lower(c: u8) -> u8 { 24 if c >= (65 as u8) { if c <= (90 as u8) { return (c + (32 as u8)) } } 25 return c 26} 27 28func hr_ieq(a: *u8, b: *u8, n: i64) -> i64 { 29 var i: i64 = 0 30 while i < n { if hr_lower(a[i]) != hr_lower(b[i]) { return 0 } i = i + 1 } 31 return 1 32} 33 34// Decimal-render v into out; return digit count (no modulo operator dependency). 35func hr_putdec(out: *u8, v: i64) -> i64 { 36 if v == 0 { out[0] = (48 as u8); return 1 } 37 let tmp: *u8 = sys_mmap(32) 38 var n: i64 = 0 39 var x: i64 = v 40 while x > 0 { 41 let q: i64 = x / 10 42 let r: i64 = x - q * 10 43 tmp[n] = ((48 + r) as u8) 44 n = n + 1 45 x = q 46 } 47 var i: i64 = 0 48 while i < n { out[i] = tmp[n - 1 - i]; i = i + 1 } 49 return n 50} 51 52// Extract the request path ("GET <path> HTTP/1.1") into out (NUL-terminated); drop any ?query. 53func hr_req_path(req: *u8, reqn: i64, out: *u8, cap: i64) -> i64 { 54 var i: i64 = 0 55 while i < reqn { if req[i] == (32 as u8) { break } i = i + 1 } 56 i = i + 1 57 var j: i64 = 0 58 while i < reqn { 59 let c: u8 = req[i] 60 if c == (32 as u8) { break } 61 if c == (63 as u8) { break } 62 if j < cap - 1 { out[j] = c; j = j + 1 } 63 i = i + 1 64 } 65 out[j] = (0 as u8) 66 return j 67} 68 69// Extract the ?query of the request line INCLUDING the leading '?' (empty -> 0). seq365: the canonical 70// 301 used to rebuild Location from the PATH alone, silently dropping ?room=&k=... from parameterized 71// links (family invites, probe URLs). Redirects must CARRY the query; this is its one extractor. 72func hr_req_query(req: *u8, reqn: i64, out: *u8, cap: i64) -> i64 { 73 var i: i64 = 0 74 while i < reqn { if req[i] == (32 as u8) { break } i = i + 1 } 75 i = i + 1 76 var q: i64 = 0 - 1 77 while i < reqn { 78 let c: u8 = req[i] 79 if c == (32 as u8) { break } 80 if c == (63 as u8) { q = i; break } 81 i = i + 1 82 } 83 if q < 0 { out[0] = (0 as u8); return 0 } 84 var j: i64 = 0 85 while q < reqn { 86 let c2: u8 = req[q] 87 if c2 == (32 as u8) { break } 88 if c2 == (13 as u8) { break } 89 if c2 == (10 as u8) { break } 90 if j < cap - 1 { out[j] = c2; j = j + 1 } 91 q = q + 1 92 } 93 out[j] = (0 as u8) 94 return j 95} 96 97// Extract the Host header (lowercased, port stripped) into out (NUL-terminated). 98func hr_req_host(req: *u8, reqn: i64, out: *u8, cap: i64) -> i64 { 99 var i: i64 = 0 100 var found: i64 = 0 - 1 101 while i + 5 <= reqn { 102 if hr_ieq(((req as i64 + i) as *u8), "host:" as *u8, 5) == 1 { found = i + 5; break } 103 i = i + 1 104 } 105 if found < 0 { out[0] = (0 as u8); return 0 } 106 var k: i64 = found 107 while k < reqn { if req[k] == (32 as u8) { k = k + 1 } else { break } } 108 var j: i64 = 0 109 while k < reqn { 110 let c: u8 = req[k] 111 if c == (13 as u8) { break } 112 if c == (10 as u8) { break } 113 if c == (58 as u8) { break } 114 if c == (32 as u8) { break } 115 if j < cap - 1 { out[j] = hr_lower(c); j = j + 1 } 116 k = k + 1 117 } 118 out[j] = (0 as u8) 119 return j 120} 121 122// Find the doc root for host in the config (lines "<host> <root>"; '#' comment; '*' wildcard default). 123// Exact host wins over wildcard regardless of line order. Returns root length (0 = no match). 124func hr_lookup_root(cfg: *u8, cfgn: i64, host: *u8, hostn: i64, out: *u8, cap: i64) -> i64 { 125 var i: i64 = 0 126 var wild: i64 = 0 - 1 127 var wildlen: i64 = 0 128 while i < cfgn { 129 while i < cfgn { let c: u8 = cfg[i]; if c == (32 as u8) { i = i + 1 } else { if c == (9 as u8) { i = i + 1 } else { break } } } 130 if i < cfgn { 131 if cfg[i] == (35 as u8) { 132 while i < cfgn { if cfg[i] == (10 as u8) { break } i = i + 1 } 133 i = i + 1 134 continue 135 } 136 } 137 let htok: i64 = i 138 while i < cfgn { let c: u8 = cfg[i]; if c == (32 as u8) { break } if c == (9 as u8) { break } if c == (10 as u8) { break } if c == (13 as u8) { break } i = i + 1 } 139 let htoklen: i64 = i - htok 140 while i < cfgn { let c: u8 = cfg[i]; if c == (32 as u8) { i = i + 1 } else { if c == (9 as u8) { i = i + 1 } else { break } } } 141 let rtok: i64 = i 142 while i < cfgn { let c: u8 = cfg[i]; if c == (32 as u8) { break } if c == (9 as u8) { break } if c == (10 as u8) { break } if c == (13 as u8) { break } i = i + 1 } 143 let rtoklen: i64 = i - rtok 144 while i < cfgn { if cfg[i] == (10 as u8) { break } i = i + 1 } 145 i = i + 1 146 if htoklen == hostn { 147 if hr_eq(((cfg as i64 + htok) as *u8), host, hostn) == 1 { 148 if rtoklen > 0 { hr_copy(out, ((cfg as i64 + rtok) as *u8), rtoklen); out[rtoklen] = (0 as u8); return rtoklen } 149 } 150 } 151 if htoklen == 1 { if cfg[htok] == (42 as u8) { if rtoklen > 0 { wild = rtok; wildlen = rtoklen } } } 152 } 153 if wild >= 0 { if wildlen > 0 { hr_copy(out, ((cfg as i64 + wild) as *u8), wildlen); out[wildlen] = (0 as u8); return wildlen } } 154 return 0 155} 156 157// Reject path traversal / NUL / non-absolute. Conservative: any ".." anywhere fails. 158func hr_path_safe(path: *u8, pathn: i64) -> i64 { 159 if pathn == 0 { return 0 } 160 if path[0] != (47 as u8) { return 0 } 161 var i: i64 = 0 162 while i < pathn { 163 if path[i] == (0 as u8) { return 0 } 164 if path[i] == (46 as u8) { if i + 1 < pathn { if path[i + 1] == (46 as u8) { return 0 } } } 165 i = i + 1 166 } 167 return 1 168} 169 170// Join root + path into out; append index.html when the path ends in '/'. 171func hr_resolve(root: *u8, rootn: i64, path: *u8, pathn: i64, out: *u8, cap: i64) -> i64 { 172 var j: i64 = 0 173 var i: i64 = 0 174 while i < rootn { if j < cap - 1 { out[j] = root[i]; j = j + 1 } i = i + 1 } 175 if j > 0 { if out[j - 1] == (47 as u8) { j = j - 1 } } 176 i = 0 177 while i < pathn { if j < cap - 1 { out[j] = path[i]; j = j + 1 } i = i + 1 } 178 if pathn > 0 { 179 if path[pathn - 1] == (47 as u8) { 180 // path ends in '/': append index.html 181 let idx: *u8 = "index.html" as *u8 182 var k: i64 = 0 183 while idx[k] != (0 as u8) { if j < cap - 1 { out[j] = idx[k]; j = j + 1 } k = k + 1 } 184 } else { 185 // bare path: if the last segment has no '.', it is a directory -> 186 // append /index.html so a CLEAN URL (e.g. /econsim) serves the page 187 // instead of reading the dir as a 0-byte octet-stream download. 188 var seg_has_dot: i64 = 0 189 var s: i64 = pathn - 1 190 while s >= 0 { 191 if path[s] == (47 as u8) { break } 192 if path[s] == (46 as u8) { seg_has_dot = 1; break } 193 s = s - 1 194 } 195 if seg_has_dot == 0 { 196 let idx2: *u8 = "/index.html" as *u8 197 var k2: i64 = 0 198 while idx2[k2] != (0 as u8) { if j < cap - 1 { out[j] = idx2[k2]; j = j + 1 } k2 = k2 + 1 } 199 } 200 } 201 } 202 out[j] = (0 as u8) 203 return j 204} 205 206// MIME by extension. 207func hr_ctype(file: *u8, filen: i64) -> *u8 { 208 var dot: i64 = 0 - 1 209 var i: i64 = 0 210 while i < filen { if file[i] == (46 as u8) { dot = i } i = i + 1 } 211 if dot < 0 { return "application/octet-stream" as *u8 } 212 let ext: *u8 = (file as i64 + dot) as *u8 213 if hr_ieq(ext, ".html" as *u8, 5) == 1 { return "text/html; charset=utf-8" as *u8 } 214 if hr_ieq(ext, ".htm" as *u8, 4) == 1 { return "text/html; charset=utf-8" as *u8 } 215 if hr_ieq(ext, ".css" as *u8, 4) == 1 { return "text/css; charset=utf-8" as *u8 } 216 if hr_ieq(ext, ".json" as *u8, 5) == 1 { return "application/json" as *u8 } 217 // .xml (2026-07-30): sitemap.xml was being served as application/octet-stream because the map had no 218 // XML row -- the one file on the site whose entire purpose is to be parsed by a machine was the one 219 // told it was an opaque blob. RFC 7303 media type; sitemaps.org expects an XML content type. 220 if hr_ieq(ext, ".xml" as *u8, 4) == 1 { return "application/xml; charset=utf-8" as *u8 } 221 if hr_ieq(ext, ".js" as *u8, 3) == 1 { return "application/javascript" as *u8 } 222 if hr_ieq(ext, ".png" as *u8, 4) == 1 { return "image/png" as *u8 } 223 if hr_ieq(ext, ".jpg" as *u8, 4) == 1 { return "image/jpeg" as *u8 } 224 if hr_ieq(ext, ".jpeg" as *u8, 5) == 1 { return "image/jpeg" as *u8 } 225 if hr_ieq(ext, ".svg" as *u8, 4) == 1 { return "image/svg+xml" as *u8 } 226 if hr_ieq(ext, ".gif" as *u8, 4) == 1 { return "image/gif" as *u8 } 227 if hr_ieq(ext, ".txt" as *u8, 4) == 1 { return "text/plain; charset=utf-8" as *u8 } 228 if hr_ieq(ext, ".ico" as *u8, 4) == 1 { return "image/x-icon" as *u8 } 229 if hr_ieq(ext, ".pdf" as *u8, 4) == 1 { return "application/pdf" as *u8 } 230 if hr_ieq(ext, ".webmanifest" as *u8, 12) == 1 { return "application/manifest+json" as *u8 } 231 if hr_ieq(ext, ".wasm" as *u8, 5) == 1 { return "application/wasm" as *u8 } 232 if hr_ieq(ext, ".mp4" as *u8, 4) == 1 { return "video/mp4" as *u8 } 233 if hr_ieq(ext, ".webm" as *u8, 5) == 1 { return "video/webm" as *u8 } 234 if hr_ieq(ext, ".woff2" as *u8, 6) == 1 { return "font/woff2" as *u8 } 235 // interop artifacts (the office/coordination second-half): calendar subscribe + office docs 236 if hr_ieq(ext, ".ics" as *u8, 4) == 1 { return "text/calendar; charset=utf-8" as *u8 } 237 if hr_ieq(ext, ".docx" as *u8, 5) == 1 { return "application/vnd.openxmlformats-officedocument.wordprocessingml.document" as *u8 } 238 if hr_ieq(ext, ".xlsx" as *u8, 5) == 1 { return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" as *u8 } 239 if hr_ieq(ext, ".pptx" as *u8, 5) == 1 { return "application/vnd.openxmlformats-officedocument.presentationml.presentation" as *u8 } 240 if hr_ieq(ext, ".odt" as *u8, 4) == 1 { return "application/vnd.oasis.opendocument.text" as *u8 } 241 if hr_ieq(ext, ".eml" as *u8, 4) == 1 { return "message/rfc822" as *u8 } 242 return "application/octet-stream" as *u8 243} 244 245// Emit a full HTTP/1.1 response (status line + Content-Type + Content-Length + body) into out. 246func hr_emit(out: *u8, statusline: *u8, ctype: *u8, body: *u8, bodyn: i64) -> i64 { 247 var j: i64 = 0 248 var k: i64 = 0 249 while statusline[k] != (0 as u8) { out[j] = statusline[k]; j = j + 1; k = k + 1 } 250 let h1: *u8 = "\r\nContent-Type: " as *u8 251 k = 0; while h1[k] != (0 as u8) { out[j] = h1[k]; j = j + 1; k = k + 1 } 252 k = 0; while ctype[k] != (0 as u8) { out[j] = ctype[k]; j = j + 1; k = k + 1 } 253 let h2: *u8 = "\r\nContent-Length: " as *u8 254 k = 0; while h2[k] != (0 as u8) { out[j] = h2[k]; j = j + 1; k = k + 1 } 255 j = j + hr_putdec(((out as i64 + j) as *u8), bodyn) 256 let h3: *u8 = "\r\nConnection: close\r\nX-Served-By: nishi-host\r\n\r\n" as *u8 257 k = 0; while h3[k] != (0 as u8) { out[j] = h3[k]; j = j + 1; k = k + 1 } 258 var b: i64 = 0 259 while b < bodyn { out[j] = body[b]; j = j + 1; b = b + 1 } 260 return j 261} 262 263// Does the request's Host match a configured site? Lets the daemon route ONLY config hosts 264// through the file server and fall back to its legacy routing (e.g. the wiki) for the rest. 265func hr_known_host(cfg: *u8, cfgn: i64, req: *u8, reqn: i64) -> i64 { 266 if cfgn <= 0 { return 0 } 267 let host: *u8 = sys_mmap(256) 268 let root: *u8 = sys_mmap(HR_MAGIC_1024) 269 let hn: i64 = hr_req_host(req, reqn, host, 256) 270 if hr_lookup_root(cfg, cfgn, host, hn, root, HR_MAGIC_1024) > 0 { return 1 } 271 return 0 272} 273 274// Full pipeline: request bytes + config -> HTTP response bytes in out. Reads the file PER REQUEST 275// (hot content). outcap must hold headers + file. Returns response length. 276func hr_serve(cfg: *u8, cfgn: i64, req: *u8, reqn: i64, out: *u8, outcap: i64) -> i64 { 277 let host: *u8 = sys_mmap(256) 278 let path: *u8 = sys_mmap(HR_MAGIC_4096) 279 let root: *u8 = sys_mmap(HR_MAGIC_1024) 280 let file: *u8 = sys_mmap(HR_MAGIC_5120) 281 let hn: i64 = hr_req_host(req, reqn, host, 256) 282 let pn: i64 = hr_req_path(req, reqn, path, HR_MAGIC_4096) 283 let rn: i64 = hr_lookup_root(cfg, cfgn, host, hn, root, HR_MAGIC_1024) 284 if rn == 0 { 285 let b0: *u8 = "<!doctype html><meta charset=utf-8><title>404</title><h1>404 &mdash; unknown host</h1>" as *u8 286 return hr_emit(out, "HTTP/1.1 404 Not Found" as *u8, "text/html; charset=utf-8" as *u8, b0, hr_slen(b0)) 287 } 288 if hr_path_safe(path, pn) == 0 { 289 let b1: *u8 = "<!doctype html><meta charset=utf-8><title>400</title><h1>400 &mdash; bad path</h1>" as *u8 290 return hr_emit(out, "HTTP/1.1 400 Bad Request" as *u8, "text/html; charset=utf-8" as *u8, b1, hr_slen(b1)) 291 } 292 let fnlen: i64 = hr_resolve(root, rn, path, pn, file, HR_MAGIC_5120) 293 let lenbox: *i64 = (sys_mmap(8)) as *i64 294 lenbox[0] = 0 295 let data: *u8 = sys_read_file(file, lenbox) 296 if (data as i64) == 0 { 297 let b2: *u8 = "<!doctype html><meta charset=utf-8><title>404</title><h1>404 &mdash; not found</h1>" as *u8 298 return hr_emit(out, "HTTP/1.1 404 Not Found" as *u8, "text/html; charset=utf-8" as *u8, b2, hr_slen(b2)) 299 } 300 let dn: i64 = lenbox[0] 301 let ct: *u8 = hr_ctype(file, fnlen) 302 return hr_emit(out, "HTTP/1.1 200 OK" as *u8, ct, data, dn) 303} 304 305// ===== v2: bounds-checked, keep-alive, fallthrough-aware serving ===== 306// (ADDITIVE -- hr_serve/hr_emit above are unchanged; the deployed daemon's 307// behaviour is bit-identical until it opts into hr_serve2.) 308 309// Bounds-checked emit. Writes status + Content-Type + Content-Length + 310// keep-alive headers + body into out; returns total length, or -1 if it 311// would not fit in outcap (caller turns that into a 500). Keep-alive (not 312// close) so one TLS handshake serves the whole page's assets. 313// Asset cache window. HTML is NEVER cached (the slot rotates on a 60s window and the served-impression 314// counter rides the HTML, so a cached page would freeze both rotation and billing); an asset is a 315// different fact. Bounded rather than immutable because house creatives sit at STABLE urls -- anything 316// uploaded through nx_adnet_creative is content-addressed and could safely take far longer. 317// DECLARED ABOVE ITS READER ON PURPOSE: nx_parse refuses a forward const read rather than silently 318// letting it evaluate to 0, which would have emitted "max-age=0" and looked like it worked. 319const HR_ASSET_MAXAGE: i64 = 3600 320 321func hr_emit_b(out: *u8, outcap: i64, statusline: *u8, ctype: *u8, body: *u8, bodyn: i64) -> i64 { 322 // headers are < 800 bytes for any status/ctype string (CORS + long office ctypes + the SOTA security header set: CSP/HSTS/nosniff/X-Frame-Options/Referrer-Policy) 323 // ROOT FIX (2026-07-31, debt 1785513321). This was a BLANKET RESERVE: `bodyn + HR_MAGIC_1024 > outcap`, 324 // which for outcap=1024 is true for ANY non-empty body -- so hr_serve2's TOOBIG branch could never emit 325 // its own 500 and an oversize file became a SILENT CONNECTION DROP instead of an error. A guard that 326 // cannot be satisfied produces a bypass, not safety. nx_host_router2_test asserted the 500 and had been 327 // RED on that tooth, uncompiled and unnoticed. 328 // Now bounded PRECISELY: refuse an outcap too small to hold the header block at all, then check the 329 // ACTUAL accumulated header length against the body before writing a single body byte. 330 if outcap < HR_MAGIC_1024 { return 0 - 1 } 331 var j: i64 = 0 332 var k: i64 = 0 333 while statusline[k] != (0 as u8) { out[j] = statusline[k]; j = j + 1; k = k + 1 } 334 let h1: *u8 = "\r\nContent-Type: " as *u8 335 k = 0; while h1[k] != (0 as u8) { out[j] = h1[k]; j = j + 1; k = k + 1 } 336 k = 0; while ctype[k] != (0 as u8) { out[j] = ctype[k]; j = j + 1; k = k + 1 } 337 let h2: *u8 = "\r\nContent-Length: " as *u8 338 k = 0; while h2[k] != (0 as u8) { out[j] = h2[k]; j = j + 1; k = k + 1 } 339 j = j + hr_putdec(((out as i64 + j) as *u8), bodyn) 340 // F1120 CROSS-ORIGIN ISOLATION (2026-07-28; /video/capprobe MEASURED crossOriginIsolated=false as 341 // the R1 blocker): COOP same-origin + COEP require-corp are what let a page use SharedArrayBuffer = 342 // wasm THREADS = tile-parallel sovereign encode (the 60fps+/4K multiplier). BLAST RADIUS NEAR-ZERO 343 // BY CONSTRUCTION: the CSP here is already default-src 'self', so every subresource is same-origin 344 // and CORP: same-origin covers them. A HEADER CHANGE KILLED THIS PRODUCT FOR 5 DAYS (seq1073) -- 345 // the video_canary tooth asserts these tokens too: a regression fails the same 300s pass it ships in. 346 // CACHEABILITY BY CONTENT TYPE (2026-07-31). This emitter hardcoded no-cache for EVERY response, 347 // images included, so a creative shipped on every served page was re-downloaded every single time. 348 // HTML MUST STAY no-cache: the slot rotates on a 60s window and the served-impression counter rides 349 // the HTML, so caching a page would freeze both rotation and billing. An asset is a different fact. 350 let hA: *u8 = "\r\nConnection: keep-alive\r\nKeep-Alive: timeout=65\r\nCache-Control: " as *u8 351 k = 0; while hA[k] != (0 as u8) { out[j] = hA[k]; j = j + 1; k = k + 1 } 352 var hr_is_html: i64 = 1 353 let hr_hm: *u8 = "text/html" as *u8 354 var hq: i64 = 0 355 while hq < 9 { if ctype[hq] != hr_hm[hq] { hr_is_html = 0; break } hq = hq + 1 } 356 if hr_is_html == 1 { 357 let hc1: *u8 = "no-cache" as *u8 358 k = 0; while hc1[k] != (0 as u8) { out[j] = hc1[k]; j = j + 1; k = k + 1 } 359 } else { 360 let hc2: *u8 = "public, max-age=" as *u8 361 k = 0; while hc2[k] != (0 as u8) { out[j] = hc2[k]; j = j + 1; k = k + 1 } 362 j = j + hr_putdec(((out as i64 + j) as *u8), HR_ASSET_MAXAGE) 363 } 364 let h3: *u8 = "\r\nAccess-Control-Allow-Origin: *\r\nX-Content-Type-Options: nosniff\r\nX-Frame-Options: SAMEORIGIN\r\nReferrer-Policy: strict-origin-when-cross-origin\r\nStrict-Transport-Security: max-age=63072000; includeSubDomains\r\nCross-Origin-Opener-Policy: same-origin\r\nCross-Origin-Embedder-Policy: require-corp\r\nCross-Origin-Resource-Policy: same-origin\r\nContent-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' blob:; worker-src 'self' blob:; font-src 'self' data:; connect-src 'self' http://127.0.0.1:7862; media-src 'self' blob:; frame-ancestors 'self'; base-uri 'none'; object-src 'none'\r\nX-Served-By: nishi-substrate-v2\r\n\r\n" as *u8 365 k = 0; while h3[k] != (0 as u8) { out[j] = h3[k]; j = j + 1; k = k + 1 } 366 // MEASURED bound: j is the ACTUAL header length just emitted, not a guessed reserve. Checked before a 367 // single body byte is written, so the refusal is exact and the TOOBIG path can emit its own 500. 368 if j + bodyn > outcap { return 0 - 1 } 369 var b: i64 = 0 370 while b < bodyn { out[j] = body[b]; j = j + 1; b = b + 1 } 371 return j 372} 373 374// Serve verdicts for hr_serve2 (sealed enum). 375const HR_S2_MISS: i64 = 0 // host known but file absent -> caller falls through to legacy routing 376const HR_S2_OK: i64 = 1 // 200 written 377const HR_S2_BAD: i64 = 2 // 400 written (traversal/malformed) 378const HR_S2_TOOBIG: i64 = 3 // 500 written (file exceeds outcap) 379 380// v2 pipeline: like hr_serve but (a) bounds-checked emit, (b) keep-alive, 381// (c) MISS verdict instead of a baked 404 when the file is absent -- the 382// daemon decides per host whether to fall through to its legacy routing 383// (nishifamily wiki) or emit a real 404 (andelinwest). Response length is 384// written to *out_n; the verdict is the return value. 385func hr_serve2(cfg: *u8, cfgn: i64, req: *u8, reqn: i64, out: *u8, outcap: i64, out_n: *i64) -> i64 { 386 out_n[0] = 0 387 let host: *u8 = sys_mmap(256) 388 let path: *u8 = sys_mmap(HR_MAGIC_4096) 389 let root: *u8 = sys_mmap(HR_MAGIC_1024) 390 let file: *u8 = sys_mmap(HR_MAGIC_5120) 391 let hn: i64 = hr_req_host(req, reqn, host, 256) 392 let pn: i64 = hr_req_path(req, reqn, path, HR_MAGIC_4096) 393 let rn: i64 = hr_lookup_root(cfg, cfgn, host, hn, root, HR_MAGIC_1024) 394 if rn == 0 { return HR_S2_MISS } 395 if hr_path_safe(path, pn) == 0 { 396 let b1: *u8 = "<!doctype html><meta charset=utf-8><title>400</title><h1>400 &mdash; bad path</h1>" as *u8 397 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 400 Bad Request" as *u8, "text/html; charset=utf-8" as *u8, b1, hr_slen(b1)) 398 return HR_S2_BAD 399 } 400 let fnlen: i64 = hr_resolve(root, rn, path, pn, file, HR_MAGIC_5120) 401 let lenbox: *i64 = (sys_mmap(8)) as *i64 402 lenbox[0] = 0 403 let data: *u8 = sys_read_file(file, lenbox) 404 if (data as i64) == 0 { return HR_S2_MISS } 405 let dn: i64 = lenbox[0] 406 let ct: *u8 = hr_ctype(file, fnlen) 407 let w: i64 = hr_emit_b(out, outcap, "HTTP/1.1 200 OK" as *u8, ct, data, dn) 408 if w < 0 { 409 let b3: *u8 = "<!doctype html><meta charset=utf-8><title>500</title><h1>500 &mdash; file exceeds serve buffer</h1>" as *u8 410 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 500 Internal Server Error" as *u8, "text/html; charset=utf-8" as *u8, b3, hr_slen(b3)) 411 return HR_S2_TOOBIG 412 } 413 out_n[0] = w 414 return HR_S2_OK 415} 416 417// Real 404 for hosts that do NOT fall through (e.g. andelinwest.com). 418func hr_emit_404(out: *u8, outcap: i64) -> i64 { 419 let b2: *u8 = "<!doctype html><meta charset=utf-8><title>404</title><h1>404 &mdash; not found</h1>" as *u8 420 return hr_emit_b(out, outcap, "HTTP/1.1 404 Not Found" as *u8, "text/html; charset=utf-8" as *u8, b2, hr_slen(b2)) 421} 422 423// ===== v3: S-CLASS ROUTING -- clean URLs + canonical 301s, ONE resolver for every path ===== 424// (ADDITIVE: hr_serve/hr_serve2 above are byte-identical and untouched.) This mirrors the gated pure 425// engine nx_route.nx (nx_route_gate 5/5) against the LIVE filesystem so routing is a property of the 426// HOST, not per-page redirect stubs: 427// * CLEAN extensionless URLs serve, for BOTH layouts: /foo -> foo/index.html (dir) OR foo.html (flat). 428// * ONE CANONICAL url via REAL 301s: /foo.html, /foo/, /foo/index.html, /index.html all collapse to 429// the clean canonical -- BUT only when that clean target actually resolves to a file, so a legacy 430// .html route (served by fallthrough, not a docroot file) is never 301'd into a 404. 431// * dir-index keeps PRECEDENCE over .html (so an existing /games hub is never shadowed by a stale flat). 432// * traversal -> 400 ; nothing resolves -> MISS (caller falls through to legacy, unchanged). 433const HR_S2_REDIR: i64 = 4 // 301 written to out (out_n set); caller must NOT fall through 434const HR_S2_STREAM: i64 = 5 // headers written to out; BODY handed via hr_stream_body/bodyn -- the 435 // caller sends both through its own chunked TLS primitive. ZERO-CEILING 436 // static serving (debt 1785879638): no file-size constant exists on this 437 // path; anything the host can mmap streams. Body ptr/len ride module 438 // statics (scalars, not arrays -- the BSS-array crash class): the daemon 439 // forks per connection, so the pair is per-process and consumed before 440 // the next request in that process. 441static hr_stream_p: i64 = 0 442static hr_stream_n: i64 = 0 443func hr_stream_body() -> i64 { return hr_stream_p } 444func hr_stream_bodyn() -> i64 { return hr_stream_n } 445 446// header half of hr_emit_b, byte-identical headers (incl cacheability-by-ctype + the security set); 447// Content-Length = bodyn, but NO body byte is written -- the stream caller sends the body itself. 448func hr_emit_head(out: *u8, outcap: i64, statusline: *u8, ctype: *u8, bodyn: i64) -> i64 { 449 if outcap < HR_MAGIC_1024 { return 0 - 1 } 450 var j: i64 = 0 451 var k: i64 = 0 452 while statusline[k] != (0 as u8) { out[j] = statusline[k]; j = j + 1; k = k + 1 } 453 let h1: *u8 = "\r\nContent-Type: " as *u8 454 k = 0; while h1[k] != (0 as u8) { out[j] = h1[k]; j = j + 1; k = k + 1 } 455 k = 0; while ctype[k] != (0 as u8) { out[j] = ctype[k]; j = j + 1; k = k + 1 } 456 let h2: *u8 = "\r\nContent-Length: " as *u8 457 k = 0; while h2[k] != (0 as u8) { out[j] = h2[k]; j = j + 1; k = k + 1 } 458 j = j + hr_putdec(((out as i64 + j) as *u8), bodyn) 459 let hA: *u8 = "\r\nConnection: keep-alive\r\nKeep-Alive: timeout=65\r\nCache-Control: " as *u8 460 k = 0; while hA[k] != (0 as u8) { out[j] = hA[k]; j = j + 1; k = k + 1 } 461 var hh: i64 = 1 462 let hm: *u8 = "text/html" as *u8 463 var hq: i64 = 0 464 while hq < 9 { if ctype[hq] != hm[hq] { hh = 0; break } hq = hq + 1 } 465 if hh == 1 { 466 let hc1: *u8 = "no-cache" as *u8 467 k = 0; while hc1[k] != (0 as u8) { out[j] = hc1[k]; j = j + 1; k = k + 1 } 468 } else { 469 let hc2: *u8 = "public, max-age=" as *u8 470 k = 0; while hc2[k] != (0 as u8) { out[j] = hc2[k]; j = j + 1; k = k + 1 } 471 j = j + hr_putdec(((out as i64 + j) as *u8), HR_ASSET_MAXAGE) 472 } 473 let h3: *u8 = "\r\nAccess-Control-Allow-Origin: *\r\nX-Content-Type-Options: nosniff\r\nX-Frame-Options: SAMEORIGIN\r\nReferrer-Policy: strict-origin-when-cross-origin\r\nStrict-Transport-Security: max-age=63072000; includeSubDomains\r\nCross-Origin-Opener-Policy: same-origin\r\nCross-Origin-Embedder-Policy: require-corp\r\nCross-Origin-Resource-Policy: same-origin\r\nContent-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' blob:; worker-src 'self' blob:; font-src 'self' data:; connect-src 'self' http://127.0.0.1:7862; media-src 'self' blob:; frame-ancestors 'self'; base-uri 'none'; object-src 'none'\r\nX-Served-By: nishi-substrate-v2\r\n\r\n" as *u8 474 k = 0; while h3[k] != (0 as u8) { out[j] = h3[k]; j = j + 1; k = k + 1 } 475 if j > outcap { return 0 - 1 } 476 return j 477} 478 479func hr_ends2(s: *u8, n: i64, suf: *u8, sufn: i64) -> i64 { 480 if sufn > n { return 0 } 481 var i: i64 = 0 482 while i < sufn { if s[n - sufn + i] != suf[i] { return 0 } i = i + 1 } 483 return 1 484} 485 486// Canonical clean form of path -> loc (NUL-terminated). Returns locn (>0 => a redirect is warranted), 487// or 0 when the path is already canonical. Order: /index.html before .html (the former is a suffix of it). 488func hr_canon(path: *u8, pn: i64, loc: *u8) -> i64 { 489 if pn <= 1 { return 0 } 490 if hr_ends2(path, pn, "/index.html" as *u8, 11) == 1 { 491 let m1: i64 = pn - 11 492 if m1 <= 0 { loc[0] = 47 as u8; loc[1] = 0 as u8; return 1 } 493 var i1: i64 = 0; while i1 < m1 { loc[i1] = path[i1]; i1 = i1 + 1 } loc[m1] = 0 as u8; return m1 494 } 495 if hr_ends2(path, pn, ".html" as *u8, 5) == 1 { 496 let m2: i64 = pn - 5 497 if m2 <= 0 { return 0 } 498 var i2: i64 = 0; while i2 < m2 { loc[i2] = path[i2]; i2 = i2 + 1 } loc[m2] = 0 as u8; return m2 499 } 500 if path[pn - 1] == (47 as u8) { 501 let m3: i64 = pn - 1 502 var i3: i64 = 0; while i3 < m3 { loc[i3] = path[i3]; i3 = i3 + 1 } loc[m3] = 0 as u8; return m3 503 } 504 return 0 505} 506 507// Join root (trailing '/' trimmed) + path + suffix into file; return length. 508func hr_join(root: *u8, rn: i64, path: *u8, pn: i64, suffix: *u8, file: *u8, cap: i64) -> i64 { 509 var j: i64 = 0; var i: i64 = 0 510 while i < rn { if j < cap - 1 { file[j] = root[i]; j = j + 1 } i = i + 1 } 511 if j > 0 { if file[j - 1] == (47 as u8) { j = j - 1 } } 512 i = 0 513 while i < pn { if j < cap - 1 { file[j] = path[i]; j = j + 1 } i = i + 1 } 514 if (suffix as i64) != 0 { 515 i = 0 516 while suffix[i] != (0 as u8) { if j < cap - 1 { file[j] = suffix[i]; j = j + 1 } i = i + 1 } 517 } 518 file[j] = 0 as u8 519 return j 520} 521 522// Resolve path -> the first existing candidate file (read PER REQUEST = hot content). Candidate order: 523// "/" -> index.html ; dotted last segment (asset) -> exact ; clean URL -> dir-index THEN .html. 524// Returns data ptr (0 = nothing resolved); sets *fnlen (file-path length, for MIME) + *dn (byte count). 525func hr_resolve_read(root: *u8, rn: i64, path: *u8, pn: i64, file: *u8, cap: i64, fnlen: *i64, dn: *i64) -> *u8 { 526 let lenbox: *i64 = (sys_mmap(8)) as *i64; lenbox[0] = 0 527 var data: *u8 = 0 as *u8 528 if pn == 1 { 529 fnlen[0] = hr_join(root, rn, path, pn, "index.html" as *u8, file, cap) 530 data = sys_read_file(file, lenbox) 531 } else { 532 var seg_dot: i64 = 0; var s: i64 = pn - 1 533 while s >= 0 { if path[s] == (47 as u8) { break } if path[s] == (46 as u8) { seg_dot = 1; break } s = s - 1 } 534 if seg_dot == 1 { 535 fnlen[0] = hr_join(root, rn, path, pn, 0 as *u8, file, cap) 536 data = sys_read_file(file, lenbox) 537 } else { 538 fnlen[0] = hr_join(root, rn, path, pn, "/index.html" as *u8, file, cap) 539 data = sys_read_file(file, lenbox) 540 if (data as i64) == 0 { 541 fnlen[0] = hr_join(root, rn, path, pn, ".html" as *u8, file, cap) 542 data = sys_read_file(file, lenbox) 543 } 544 } 545 } 546 dn[0] = lenbox[0] 547 return data 548} 549 550// Emit a 301 with Location (empty body, keep-alive). -1 if it would not fit. 551func hr_emit_redirect(out: *u8, outcap: i64, loc: *u8, locn: i64) -> i64 { 552 if locn + 256 > outcap { return 0 - 1 } 553 var j: i64 = 0; var k: i64 = 0 554 let s1: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: " as *u8 555 k = 0; while s1[k] != (0 as u8) { out[j] = s1[k]; j = j + 1; k = k + 1 } 556 k = 0; while k < locn { out[j] = loc[k]; j = j + 1; k = k + 1 } 557 let s2: *u8 = "\r\nContent-Length: 0\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nX-Served-By: nishi-host\r\n\r\n" as *u8 558 k = 0; while s2[k] != (0 as u8) { out[j] = s2[k]; j = j + 1; k = k + 1 } 559 return j 560} 561 562// ===== v3+slot helpers: universal ad-slot injection (ADDITIVE -- hr_serve3 below is untouched) ===== 563// hr_serve3_slot behaves byte-identically to hr_serve3 when slot_n==0 (gated). With slot bytes: a 564// text/html body containing </body> and NOT carrying the nx-ad-optout marker gets the slot inserted 565// before the LAST </body>; Content-Length stays correct by construction (merge happens before emit). 566// injected[0]=1 ONLY when the slot actually landed (the caller logs a served impression off it). 567 568func hr_ct_is_html(ct: *u8) -> i64 { 569 return hr_eq(ct, "text/html" as *u8, 9) 570} 571 572// index of the LAST "</body>" (case-insensitive) in body, or -1. 573func hr_find_close_body(body: *u8, bn: i64) -> i64 { 574 if bn < 7 { return 0 - 1 } 575 var i: i64 = bn - 7 576 while i >= 0 { 577 if body[i] == (60 as u8) { 578 if hr_ieq(((body as i64 + i) as *u8), "</body>" as *u8, 7) == 1 { return i } 579 } 580 i = i - 1 581 } 582 return 0 - 1 583} 584 585// page-level opt-out marker scan (any page may carry nx-ad-optout to refuse the slot). 586func hr_has_optout(body: *u8, bn: i64) -> i64 { 587 var i: i64 = 0 588 while i + 12 <= bn { 589 if body[i] == (110 as u8) { 590 if hr_eq(((body as i64 + i) as *u8), "nx-ad-optout" as *u8, 12) == 1 { return 1 } 591 } 592 i = i + 1 593 } 594 return 0 595} 596 597 598// ---- SLOT ANCHOR (2026-07-31): let a PAGE choose where its ad goes ------------------------------- 599// WHY: the slot was always injected before the closing body tag -- the absolute bottom of the document. 600// On a long reference page essentially nobody scrolls there, and the MRC rule needs 50% of the creative 601// in view for one CONTINUOUS second. So viewable impressions were structurally near-zero: we measured 602// honestly and still sold a position nobody sees. The honest number does not fix placement, it EXPOSES 603// it -- and this is the mechanism that lets it be fixed. 604// 605// A page opts in by placing the marker where it wants the ad. NO MARKER = the old behaviour, byte for 606// byte, so this cannot change a single existing page. Placement stays a PRODUCT decision made per page, 607// not an engineering default imposed on every site at once. 608const HR_SLOT_MARK: *u8 = "<!--nx-ad-slot-->" as *u8 609 610func hr_find_slot_anchor(d: *u8, n: i64) -> i64 { 611 var i: i64 = 0 612 while i + 17 <= n { 613 var k: i64 = 0 614 var m: i64 = 1 615 while k < 17 { if d[i + k] != HR_SLOT_MARK[k] { m = 0; break } k = k + 1 } 616 if m == 1 { return i } 617 i = i + 1 618 } 619 return hr_find_close_body(d, n) 620} 621 622func hr_serve3_slot(cfg: *u8, cfgn: i64, req: *u8, reqn: i64, out: *u8, outcap: i64, out_n: *i64, slot: *u8, slot_n: i64, injected: *i64) -> i64 { 623 injected[0] = 0 624 out_n[0] = 0 625 let host: *u8 = sys_mmap(256) 626 let path: *u8 = sys_mmap(HR_MAGIC_4096) 627 let root: *u8 = sys_mmap(HR_MAGIC_1024) 628 let file: *u8 = sys_mmap(HR_MAGIC_5120) 629 let hn: i64 = hr_req_host(req, reqn, host, 256) 630 let pn: i64 = hr_req_path(req, reqn, path, HR_MAGIC_4096) 631 let rn: i64 = hr_lookup_root(cfg, cfgn, host, hn, root, HR_MAGIC_1024) 632 if rn == 0 { return HR_S2_MISS } 633 if hr_path_safe(path, pn) == 0 { 634 let b1: *u8 = "<!doctype html><meta charset=utf-8><title>400</title><h1>400 &mdash; bad path</h1>" as *u8 635 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 400 Bad Request" as *u8, "text/html; charset=utf-8" as *u8, b1, hr_slen(b1)) 636 return HR_S2_BAD 637 } 638 let fnlen: *i64 = (sys_mmap(8)) as *i64 639 let dn: *i64 = (sys_mmap(8)) as *i64 640 let loc: *u8 = sys_mmap(HR_MAGIC_4096) 641 let locn: i64 = hr_canon(path, pn, loc) 642 if locn > 0 { 643 let cfile: *u8 = sys_mmap(HR_MAGIC_5120) 644 let cdata: *u8 = hr_resolve_read(root, rn, loc, locn, cfile, HR_MAGIC_5120, fnlen, dn) 645 if (cdata as i64) != 0 { 646 // seq365: CARRY the ?query on the canonical 301 (resolve above used the PATH-only loc; 647 // append after resolve so filesystem lookup never sees query bytes). No-query requests 648 // emit byte-identical redirects to before. 649 let qbuf: *u8 = sys_mmap(HR_MAGIC_2048) 650 let qn: i64 = hr_req_query(req, reqn, qbuf, HR_MAGIC_2048) 651 var locq: i64 = locn 652 if qn > 0 { if locn + qn < HR_MAGIC_4095 { 653 var qi: i64 = 0 654 while qi < qn { loc[locn + qi] = qbuf[qi]; qi = qi + 1 } 655 locq = locn + qn 656 loc[locq] = 0 as u8 657 } } 658 out_n[0] = hr_emit_redirect(out, outcap, loc, locq) 659 if out_n[0] < 0 { out_n[0] = 0; return HR_S2_MISS } 660 return HR_S2_REDIR 661 } 662 } 663 let data: *u8 = hr_resolve_read(root, rn, path, pn, file, HR_MAGIC_5120, fnlen, dn) 664 if (data as i64) == 0 { return HR_S2_MISS } 665 let ct: *u8 = hr_ctype(file, fnlen[0]) 666 var body: *u8 = data 667 var bodyn: i64 = dn[0] 668 if slot_n > 0 { 669 if hr_ct_is_html(ct) == 1 { 670 let cb: i64 = hr_find_slot_anchor(data, bodyn) 671 if cb >= 0 { 672 let oo: i64 = hr_has_optout(data, bodyn) 673 if oo == 0 { 674 let mcap: i64 = bodyn + slot_n + 16 675 let merged: *u8 = sys_mmap(mcap) 676 var w2: i64 = 0 677 var a: i64 = 0 678 while a < cb { merged[w2] = data[a]; w2 = w2 + 1; a = a + 1 } 679 var b2: i64 = 0 680 while b2 < slot_n { merged[w2] = slot[b2]; w2 = w2 + 1; b2 = b2 + 1 } 681 while a < bodyn { merged[w2] = data[a]; w2 = w2 + 1; a = a + 1 } 682 body = merged 683 bodyn = w2 684 injected[0] = 1 685 } 686 } 687 } 688 } 689 let w: i64 = hr_emit_b(out, outcap, "HTTP/1.1 200 OK" as *u8, ct, body, bodyn) 690 if w < 0 { 691 // ZERO-CEILING STREAM (debt 1785879638; operator: no self-imposed limits, no magic numbers): 692 // the body is ALREADY in memory -- emit headers only (they always fit any sane outcap) and 693 // hand the body pointer to the daemon, which sends both through the same chunked TLS send. 694 // No file-size constant exists on this path. 500 remains ONLY for an outcap below the header floor. 695 let hw: i64 = hr_emit_head(out, outcap, "HTTP/1.1 200 OK" as *u8, ct, bodyn) 696 if hw > 0 { 697 hr_stream_p = body as i64 698 hr_stream_n = bodyn 699 out_n[0] = hw 700 return HR_S2_STREAM 701 } 702 let b3: *u8 = "<!doctype html><meta charset=utf-8><title>500</title><h1>500 &mdash; file exceeds serve buffer</h1>" as *u8 703 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 500 Internal Server Error" as *u8, "text/html; charset=utf-8" as *u8, b3, hr_slen(b3)) 704 return HR_S2_TOOBIG 705 } 706 out_n[0] = w 707 return HR_S2_OK 708} 709 710// v3 pipeline: canonical 301 (safe) + clean multi-candidate resolve. Verdicts: OK/MISS/BAD/TOOBIG/REDIR. 711func hr_serve3(cfg: *u8, cfgn: i64, req: *u8, reqn: i64, out: *u8, outcap: i64, out_n: *i64) -> i64 { 712 out_n[0] = 0 713 let host: *u8 = sys_mmap(256) 714 let path: *u8 = sys_mmap(HR_MAGIC_4096) 715 let root: *u8 = sys_mmap(HR_MAGIC_1024) 716 let file: *u8 = sys_mmap(HR_MAGIC_5120) 717 let hn: i64 = hr_req_host(req, reqn, host, 256) 718 let pn: i64 = hr_req_path(req, reqn, path, HR_MAGIC_4096) 719 let rn: i64 = hr_lookup_root(cfg, cfgn, host, hn, root, HR_MAGIC_1024) 720 if rn == 0 { return HR_S2_MISS } 721 if hr_path_safe(path, pn) == 0 { 722 let b1: *u8 = "<!doctype html><meta charset=utf-8><title>400</title><h1>400 &mdash; bad path</h1>" as *u8 723 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 400 Bad Request" as *u8, "text/html; charset=utf-8" as *u8, b1, hr_slen(b1)) 724 return HR_S2_BAD 725 } 726 let fnlen: *i64 = (sys_mmap(8)) as *i64 727 let dn: *i64 = (sys_mmap(8)) as *i64 728 // canonical 301 -- only when the clean target actually resolves (never 301 to a 404) 729 let loc: *u8 = sys_mmap(HR_MAGIC_4096) 730 let locn: i64 = hr_canon(path, pn, loc) 731 if locn > 0 { 732 let cfile: *u8 = sys_mmap(HR_MAGIC_5120) 733 let cdata: *u8 = hr_resolve_read(root, rn, loc, locn, cfile, HR_MAGIC_5120, fnlen, dn) 734 if (cdata as i64) != 0 { 735 // seq365: CARRY the ?query on the canonical 301 (resolve above used the PATH-only loc; 736 // append after resolve so filesystem lookup never sees query bytes). No-query requests 737 // emit byte-identical redirects to before. 738 let qbuf: *u8 = sys_mmap(HR_MAGIC_2048) 739 let qn: i64 = hr_req_query(req, reqn, qbuf, HR_MAGIC_2048) 740 var locq: i64 = locn 741 if qn > 0 { if locn + qn < HR_MAGIC_4095 { 742 var qi: i64 = 0 743 while qi < qn { loc[locn + qi] = qbuf[qi]; qi = qi + 1 } 744 locq = locn + qn 745 loc[locq] = 0 as u8 746 } } 747 out_n[0] = hr_emit_redirect(out, outcap, loc, locq) 748 if out_n[0] < 0 { out_n[0] = 0; return HR_S2_MISS } 749 return HR_S2_REDIR 750 } 751 } 752 // resolve + serve the (canonical) path 753 let data: *u8 = hr_resolve_read(root, rn, path, pn, file, HR_MAGIC_5120, fnlen, dn) 754 if (data as i64) == 0 { return HR_S2_MISS } 755 let ct: *u8 = hr_ctype(file, fnlen[0]) 756 let w: i64 = hr_emit_b(out, outcap, "HTTP/1.1 200 OK" as *u8, ct, data, dn[0]) 757 if w < 0 { 758 let b3: *u8 = "<!doctype html><meta charset=utf-8><title>500</title><h1>500 &mdash; file exceeds serve buffer</h1>" as *u8 759 out_n[0] = hr_emit_b(out, outcap, "HTTP/1.1 500 Internal Server Error" as *u8, "text/html; charset=utf-8" as *u8, b3, hr_slen(b3)) 760 return HR_S2_TOOBIG 761 } 762 out_n[0] = w 763 return HR_S2_OK 764}